ASP.NET MVC: Default model binder not working on Safari (but does work for Firefox)
Very strange issue... I have something like this in my Controller:
public ActionResult Initialize(IEnumerable<MyModel> Requests)
{
...
}
I generate form elements in my submitting View that look like this:
Requests[90ed54f6-4650-44c7-8cc2-c4d225a9a334].Name
Requests[90ed54f6-4650-44c7-8cc2-c4d225a9a334].Address
Requests[db67e8e5-94f8-4b35-b69c-65184980f2a1].Name
Requests[db67e8e开发者_StackOverflow中文版5-94f8-4b35-b69c-65184980f2a1].Address
On Firefox, when I submit this with multiple elements, the binder works and I get a collection of objects. On Safari, the exact same data always generates only 1 object in the collection.
Weirdly, in the debugger if I look at Requests.Params.AllKeys[] I see the values -- they're being submitted, just somehow not binding. I use Firebug on Firefox but don't have an equivalent tool for Safari. Since I see the values in the Request.Params, I assume that it's not an issue with the form values being passed in -- just something about they way they're being bound to the ViewModel...
The binder is kind of black magic to me -- I'm not sure where this lives and if I can step through this to see what it's doing.
Any ideas what this might be or how I might chase this down?
Edit: This works correctly in IE as well -- just Safari is acting weird.
Edit 2: I lied... Safari does not post the index values as I would expect:
Requests.index = {GUID}
Requests[90ed54f6-4650-44c7-8cc2-c4d225a9a334].Name
Requests[90ed54f6-4650-44c7-8cc2-c4d225a9a334].Address
Requests.index = {GUID}
Requests[db67e8e5-94f8-4b35-b69c-65184980f2a1].Name
Requests[db67e8e5-94f8-4b35-b69c-65184980f2a1].Address
Both Firefox and Internet Explorer post both Requests.index
values as comma separated values, but Safari only posts the first. I'm not sure what "correct" is for this case, but this is something I can sink my teeth into.
I assume that the "index" is a GUID that functions as the request's id. I would assume that you would actually generate something like:
<input type="hidden" name="Requests[0].ID" value="90ed54f6-4650-44c7-8cc2-c4d225a9a334" />
<input type="text" name="Requests[0].Name" />
<input type="text" name="Requests[0].Address" />
Of course, your MyModel class will need to have the ID property to hold the Guid.
My suspicion is that it has something to do with how the query parameters are encoded, but honestly I have never set up collections the way you are and it's not clear to me how the model binder should interpret the parameter index -- perhaps it's mapping them all onto 0 -- if it's not numeric.
Compare actual values POST'd by each browser:
public ActionResult Initialize(FormCollection collection)
{
//... dump the collection's NameValueCollection ...
}
And compare actual HTML rendering of the form between browsers, just to be sure.
So the final solution to this had to do with improperly placed <input>
tags. Specifically, I was placing a hidden <input>
after a <tr>
and before a <td>
. On Firefox and IE it's very forgiving and this was working. On Safari for some reason, it would not consider the 2nd-Nth elements to be valid form inputs. Putting the <input>
elements inside of the <td>
worked for all browsers.
Thanks for your help guys.
精彩评论