Dan
Dan

Reputation: 724

Binding a list belonging to another object in a custom model binder in ASP.NET MVC

I realize something like this has been asked, but this may be a little different.

Below is my Event object:

Event : IEvent
  public int Id
  public string Title
  public List<EventContact> Contacts

And EventContact:

EventContact
  public int Id
  public string Name
  public string Email

So, an Event has a list of EventContact objects. Now, Event also implements IEvent - hence the custom model binder. I use IEvent instead of Event, so when the default model binder tries to do its thing, it lets me know it can't create an `IEvent'.

I have my view with populated with the contact info:

<input type="text" name="contact[0].Name" value="DB Value"/>
<input type="text" name="contact[1].Name" value="DB Value"/>
<input type="text" name="contact[2].Name" value="DB Value"/>

<input type="text" name="contact[0].Email" value="DB Value"/>
<input type="text" name="contact[1].Email" value="DB Value"/>
<input type="text" name="contact[2].Email" value="DB Value"/>

<!-- Event fields, etc -->

So, in my custom model binder I am able to see all the values - sweet! The only thing is, I'm really not sure how to get all the contact fields and create a list of contacts from them, along with binding all the Event fields.

Upvotes: 2

Views: 823

Answers (1)

Dan
Dan

Reputation: 724

To accomplish the above, I simply queried the existing binding context's ValueProvider for all EventContact fields and sent that along to the default model binder with a new binding context:

IDictionary<string, ValueProviderResult> contactValueProvider = bindingContext.ValueProvider
            .Select(t => new { t.Key, t.Value })
            .Where(t => t.Key.Contains("EventContact"))
            .ToDictionary(t => t.Key, t => t.Value);

ModelBindingContext contactBindingContext = new ModelBindingContext()
        {
            ModelName = "EventContact",
            ModelState = bindingContext.ModelState,
            ModelType = typeof(List<EventContact>),
            PropertyFilter = bindingContext.PropertyFilter,
            ValueProvider = contactValueProvider
        };

_event.Contacts = ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, contactBindingContext) as IQueryable<EventContact>;

It works, so I'm happy :P

Upvotes: 1

Related Questions