MVC3 does not publish the whole model

I am new to MVC and am really trying to get used to model binding. I have a simple model that I created in a form. However, when I submit this form ONLY, the values ​​of the text field are transferred to the controller. I also need a description field that is executed using DisplayTextFor. Is this something I need to do to fit my order? I could make a shortcut and just make the description a read-only text box without a border so that it looks like text, but I want to do it right. Here is my code:

public class FullOrder { public List<FullOrderItem> OrderList { get; set; } public string account { get; set; } public string orderno { get; set; } } public class FullOrderItem { public int? ID { get; set; } public int? OrderId { get; set; } public string Description { get; set; } public int Qty { get; set; } public decimal? Price { get; set; } } 

Here is a view

 <table class="ExceptionAltRow"> <tr style="background-color: #DDD;"> <td class="strong" style="width:500px;"> Description </td> <td class="strong" style="width:100px;"> Qty </td> <td class="strong" style="width:100px;"> Previous Purchases </td> </tr> @for (int i = 0; i < Model.FullOrder.OrderList.Count(); i++) { <tr> <td> @Html.DisplayTextFor(m => m.FullOrder.OrderList[i].Description) </td> <td> @Html.TextBoxFor(m => m.FullOrder.OrderList[i].Qty, new { @style = "width:50px;" }) </td> </tr> } </table> 

Here is the controller:

 [HttpPost] public ActionResult AddItem(FullOrder f) { //doesn't work description is not passed but qty is } 

Is there a way that I can make my model simply pass the description in the message, even if it is not a text field for a related element from my model?

+7
source share
3 answers

The only data that will be sent to your application is the data that is available in the form that is submitted (unless, of course, the form fields are disabled). You can override what the controller sees by implementing a custom connectivity device .

In this case, your form consists of many instances of one text field:

 @Html.TextBoxFor(m => m.FullOrder.OrderList[i].Qty, new { @style = "width:50px;" }) 

If you want the description and other things to be completed, they must be present on the form. If they should not be visible, you can use the HiddenFor helper:

 @Html.HiddenFor(m => m.FullOrder.OrderList[i].Description) 

See also What Does Html.HiddenFor Do?

+2
source

Of course you cannot make it work that way

First of all, you should know that model binding occurs mainly using sending data from inputs on the client side. Html.DisplayTextFor helper does not generate input, it generates plain text. Texts do not participate in the data sent by the client when submitting the form, so you will not get them bound to the model. If you look at the Request.Form property, you should see a proof - there are no description fields.

What you can do if you want to display the text, as well as allow the description to participate in the values ​​of the form, is to use a hidden field. MVC got an assistant for this

  @for (int i = 0; i < Model.FullOrder.OrderList.Count(); i++) { <tr> <td> @Html.DisplayTextFor(m => m.FullOrder.OrderList[i].Description) @Html.HiddenFor(m => m.FullOrder.OrderList[i].Description) </td> <td> @Html.TextBoxFor(m => m.FullOrder.OrderList[i].Qty, new { @style = "width:50px;" }) </td> </tr> } 

Thus, the submitted form will also contain description values

+1
source

The DisplayTextFor function will only output this text to the browser DOM. Linking to an MVC map basically considers POST / GET variables and automatically sets these values ​​to your model.

If you want to link any data automatically (for example, description text), you will need to save this for some type of input and / or hidden field. Hidden fields work, but are inefficient, since you put a bunch of additional elements in your HTML and you can even edit it using something like Firebug.

My recommendation and what I always did was to expect some of this information to be sent back, and just set it explicitly in the controller action:

  [HttpPost] public ActionResult AddItem(FullOrder f) { // Next line is just showing that you should get the existing order // from your data layer FullOrder existingOrder = orderRepository.GetExistingOrder(); // Now loop through f.OrderList and update the quantities foreach(OrderItem item in f.OrderList) { // Find the existing item and update the quantity. } // Now you have the original information from the DB along with // updated quantities. // Save results or do whatever is next existingOrder.Save(); } 
0
source

All Articles