I recently encountered an issue while implementing a JSON solution for a client. If the action parameter name matches a property name of the model, the binder fails to bind ANY properties.
An example:
Controller People
public ActionResult SetEmails(Person emails){
...
return Content("");
}
Because the parameter name was called "emails" and that matches a property name of the Person model called "Emails".. the binder fails, but does not give any indication as to why..
They had a model called Person
public class Person {
public string Name { get; set; }
public List&开发者_StackOverflow中文版lt;string> Emails { get; set; }
public Person() {
Emails = new List<string>();
}
}
Is this a bug, or a 'feature' ?
Just as a side note, my question is more in regards to how an arguments name could cause a conflict to a binder? The name shouldn't matter as it's the class type that defines it's schema to match against the json data.. why should the binder care what you name the argument or if it matches a property name within the class type of the argument itself?
The problem is that you have an ambiguity in your dictionary, with two elements both named "emails" (though with different casing). DefaultModelBinder
cannot resolve this ambiguity.
Two possible solutions: (1) if you are passing back an entire person model, change the name of your top-level element to "person" (which makes more sense, given the context), which would remove the ambiguity, and allow the binding to take place as expected, or (2) if you are just passing back a list of emails, change your action signature to public ActionResult SetEmails(List<Emails> emails)
.
I would not call what you have experienced either a bug or a feature, but an issue with your design.
I'm not saying I like this for an answer, but you CAN avoid changing your property name.
Wrap your JSON object with the variable name of the parameter (in this case, it's "emails"). So this works:
data: JSON.stringify( { emails: { Name: "my name", Emails: ["a@a.com", "b@b.com"]} } );
but this doesn't - the modelbinder returns null instead:
data: JSON.stringify( { Name: "my name", Emails: ["a@a.com", "b@b.com"]} );
Still, this is pretty crappy. However things work deep under the covers, there's no reason my web client should have to know what the parameter name in the controller is in order to work correctly. As far as I'm concerned, it's a bug in MVC's modelbinder.
精彩评论