dgahel
dgahel

Reputation: 1

Is it good or bad practice to rely on name attribute in the form to post the model to MVC controller?

I have a model containing some complex types including nested lists. So I cannot simply use the model.

My initial thought is using knockoutjs to take care of the user interactions (add/delete list items etc.), and post knockoutjs view model via ajax.

But after some googling, I found I could give meaningful name attributes in my form elements and do regular form submit to post my form model like this.

<input checked="checked" data-val="true" data-val-required="The Boolean field is required." name="Questions[0].SubQuestions[0].OptionAnswers[0]" type="checkbox" value="true">

Of course I still need some javascript for list manipulations and stuff.

Which approach is more preferred?

EDIT:

Sorry for the indexing issue. I was aware it should be sequential and start from 0. I just took a random element from my generated html. The indexing is not really my issue. I just would like to know which approach is more preferred.

I start liking the regular form submission way as it takes advantage of the validation feature of DataAnnotations and Html.ValidationSummary. What's the advantages for ajax post?

Upvotes: 0

Views: 87

Answers (2)

KKS
KKS

Reputation: 3630

You are very close to understand the concept how asp.net mvc model binder works out of the box.

This is the link to an article from where I learnt how to achieve similar requirement.

The way that mvc model binder reads in the properties is by looking for parameterName[index].PropertyName. The index must be zero-based and unbroken. Say suppose, if you have your html like below which is a list for example and it can be your Questions list which is a complex type:

<input type="text" name="people[0].FirstName" value="George" />
<input type="text" name="people[0].LastName" value="Washington" />
<input type="text" name="people[1].FirstName" value="Abraham" />
<input type="text" name="people[1].LastName" value="Lincoln" />
<input type="text" name="people[3].FirstName" value="Thomas" />
<input type="text" name="people[3].LastName" value="Jefferson" />

When you submit the above values to asp.net mvc controller, the above value turns into:

people%5B0%5D.FirstName=George&people%5B0%5D.LastName=Washington&people%5B1%5D.FirstName=Abraham&people%5B1%5D.LastName=Lincoln&people%5B3%5D.FirstName=Thomas&people%5B3%5D.LastName=Jefferson

The mvc model binder then read the above data as:

people[0].FirstName = "George"
people[0].LastName = "Washington"
people[1].FirstName = "Abraham"
people[1].LastName = "Lincoln"
people[3].FirstName = "Thomas"
people[3].LastName = "Jefferson"

So, as you can see we have list items for index 0, 1 and then 3. It is broken! This results in mvc model binder only translating this data to a list of type people for only two items i.e. index 0 and 1. It excludes 3 as there was no data at index 2.

this answer has information from the same article. If you understand this, you will understand the role of name attributes and you will appreciate how easy it is to follow the rules and mvc binder will understand all your posted data.

If you want to make sure that mvc binder constructs a list from the posted data even if any index is missing then refer Eric's answer

Upvotes: 1

Erik Philips
Erik Philips

Reputation: 54638

Yoda's answer is very very good. However there is a known way to have a list of Non-Sequential Indices for postback as Phil Haacked describes in Model Binding To A List (Non-Sequential Indices heading)

<input type="hidden" name="products.Index" value="0" />
<input type="text" name="products[0].Name" value="Beer" />
<input type="text" name="products[0].Price" value="7.32" />

<input type="hidden" name="products.Index" value="1" />
<input type="text" name="products[1].Name" value="Chips" />
<input type="text" name="products[1].Price" value="2.23" />

<input type="hidden" name="products.Index" value="3" />
<input type="text" name="products[3].Name" value="Salsa" />
<input type="text" name="products[3].Price" value="1.23" />

Upvotes: 0

Related Questions