Firstly, bear with me here. I have a custom model binder which is successfully mapping form data to a custom object. Within this model binder it also maps form items to different custom object. What I feel I should be able to do is create a separate model binder to take care of this second mapping. This is a simplified version.
Custom objects:
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public string Description { get; set; }
public IEnumerable<SubCategory> SubCategories { get; set; }
}
public class SubCategory
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Status { get; set; }
}
If my form passes back a bunch of Ids for the SubCategories, what I need to do is run off to the data repository and hydrate the SubCategory object. From the form, a list of subcategories would be submitted in the following format:
<input type="text" name="Name" value="This Category" />
<input type="hidden" name="subcat.Index" value="0" />
<select name="subcat[0].Id">
<option value="1">Something</option>
<option value="2">Something else</option>
</select>
<input type="hidden" name="subcat.Index" value="1" />
<select name="subcat[1].Id">
<option value="1">Something</option>
<option value="2">Something else</option>
</select>
<input type="hidden" name="subcat.Index" value="2" />
<select name="subcat[2].Id">
<option value="1">Something</option>
<option value="2">Something else</option>
</select>
Writing a custom to map the Category is obviously simple, writing the model binder which will in turn map the SubCategory (within the model binder I would run off an query my data repository) is proving a little difficult.
I am not sure how clear I have made this, apologies, thanks for reading and please let me know if there is something I can say to make this clearer!
My take on this is that model binders should be constructing presentation models, not entity types from your repository. The model binder should be a very simple mapping from the key/value collection of the form to a presentation model which is mostly scalar values with possibly some relationships to other types that are mostly scalar values or lists. Having to materialize entity instances from a repository adds a lot of complication, as you have found.
Moreover, it's unnecessary. Using a presentation model has a large number of advantages, including:
So in your example, the subcategories would come in from the form collection as a list of integers. Therefore, the presentation model should have the same list of integers. In the controller, after binding, you can call a method to transfer the model values from the presentation model to a materialized category instance from the repository.