Binding non-sequential lists with a custom model binder
Asked Answered
L

1

8

I know that if I want to bind non-sequential elements to a list in MVC I can use the Index syntax described here.

However, I'm unable to get remote validation to work with this (using the Remote attribute).

For example, if I had a model like this:

public class AddUsers {
    public List<User> Users { get; set; }
    public string Comment { get; set; }
}

public class User {
    [Remote("UsernameAvailable", "User")]
    public string Name { get; set; }
}

Then suppose in my view I have the following (I'm deliberately leaving out Html helpers I'm using for clarity):

<input type="hidden" name="Users.Index" value="foo" />
<input type="text" name="Users[foo].Name" />

<input type="hidden" name="Users.Index" value="bar" />
<input type="text" name="Users[bar].Name" />

In a form post, the Index field goes along for the ride, which helps the model binder bind everything nicely, like:

Comment=bla&Users.Index=foo&Users[foo].Name=john&Users.Index=bar&Users[bar].Name=bob

But when remote validation triggers, only this is sent to my action (two separate requests, one for each item being validated):

Users[foo].Name=john
Users[bar].Name=bob

Without an Index, The model binder doesn't know what to do with this. It can neither bind to a User, a List<User>, nor an AddUser.

Which brings me to my question.

Would there be a way to write a custom model binder that can handle non-sequential lists without needing to use the Index notation? I must admit that it is difficult for me to see why the Index notation would be necessary (except perhaps as an optimization of some kind).

I'm using MVC 4, and .NET 4.5.

Note: I've never messed around with custom model binders before, so I'm really just looking for some general guidance about whether it would be possible (or just a dead end), and possibly some pointers for getting started.

Libya answered 22/3, 2013 at 17:26 Comment(6)
In theory the Remote validator should work fine. Can you maybe extend your post how do you want to use the Remote validor and remote action looks like?Duffel
@nemesv, I have updated my post. Is this enough clarification? Neither a validation action taking a User, a List<User> nor an AddUser will be able to bind, because the Index is missing.Libya
I was able to solve my problem by adapting the solution from [this answer][1] [1]: https://mcmap.net/q/836730/-mvc-model-binding-to-a-collection-where-collection-does-not-begin-with-a-0-indexLibya
you mention a helper not used to clarify the question. It seems to me that your hidden index fields are not being submitted to the server. Something in your helper may be doing this, for example disabled fields are not posted to the server.Marashio
@HonorableChow, the reason the Index fields aren't submitted to the server is because of the way Remote Validation works. It works individually on the properties, rather than serializing the whole form. When the whole form is serialized during a POST, the Index fields do show up.Libya
Instead of Remote attribute which works on the client side, use a custom attribute that validates on the server side.Nicosia
S
0

I was able to solve my problem by adapting the solution from this answer – Eric Mar 22 '13 at 22:28

Subaqueous answered 22/3, 2013 at 17:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.