MVC Razor View: how to display a list of text fields for the <Task> list in the model?

I have a List<Task> in my model. This list contains 2 tasks (say) in it

 public List<Task> Tasks { get; set; } public class Task { public Task() { Title=""; Total= 0; } public string Title{ get; set; } public int Total{ get; set; } } 

Now in my razor mode, I want to make 2 text fields for each of the Tasks in the List<Tasks> my model.

I did not loop, just placed direct text fields, for example:

 @Html.TextBoxFor(m => m.Tasks[0].Title, new { @maxlength = "50"}) @Html.TextBoxFor(m => m.Tasks[0].Total, new { @maxlength = "2"}) <br> @Html.TextBoxFor(m => m.Tasks[1].Title, new { @maxlength = "50"}) @Html.TextBoxFor(m => m.Tasks[1].Total, new { @maxlength = "2"}) 

This displays the form in order, but pressing the submit button does nothing in FF. However, it is excellent in IE9.

The view source shows that this html is created as follows:

 <input id="Tasks_0__Title" maxlength="50" name="Tasks[0].Title" type="text" value="" /> <input data-val="true" data-val-number="The field Total must be a number." data-val-required="The Total field is required." id="Tasks_0__Total" maxlength="2" name="Tasks[0].Total" type="text" value="" /> 

This HTML does not look right. It has name="Tasks[0].Total" , which seems odd.

How can I do this so that I can access the text field values ​​from List<> in my controller after publishing?

thanks

EDIT: I just kept one row for the test. This is the html that I see in FF.

 <input id="Tasks_0__Title" type="text" value="" name="Tasks[0].Title" maxlength="50"> <input id="Tasks_0__Total" type="text" value="" name="Tasks[0].Total" maxlength="2" data-val-required="The Total field is required." data-val-number="The field Total must be a number." data-val="true"> 

This is not a message when I click the submit button.

Now, if I change name="Tasks[0].Title" to name="Tasks_0__Title" and name="Tasks_0__Total" in FIREBUG, he writes well.

If I completely delete the name, it is also published in FF

+3
source share
1 answer

You should use Tasks[0].Total and Tasks[1].Total instead of Items :

 @Html.TextBoxFor(m => m.Tasks[0].Title, new { @maxlength = "50"}) @Html.TextBoxFor(m => m.Tasks[0].Total, new { @maxlength = "2"}) <br/> @Html.TextBoxFor(m => m.Tasks[1].Title, new { @maxlength = "50"}) @Html.TextBoxFor(m => m.Tasks[1].Total, new { @maxlength = "2"}) 

name="Tasks[0].Total" not odd. This is how the name should be entered so that the model binder can return the value to the POST action. See this blog post for the default wire format used by the middleware when working with lists and dictionaries.

Having said that, I recommend you use the editor templates => instead of writing these 5 lines of code in your view, replace them with:

 @Html.EditorFor(x => x.Tasks) 

and then inside the corresponding editor template ( ~/View/Shared/EditorTemplates/Task.cshtml ), which will be automatically displayed for each element of the Tasks collection:

 @model Task @Html.TextBoxFor(m => m.Title, new { @maxlength = "50"}) @Html.TextBoxFor(m => m.Total, new { @maxlength = "2"}) <br/> 

Now you can leave the editor templates to worry about the proper naming convention, etc.

As for your POST action:

 [HttpPost] public ActionResult Foo(MyViewModel model) { // model.Tasks should be correctly bound here ... } 
+4
source

All Articles