views:

43

answers:

2

I have not been using "model binding" in my MVC application -- that is, I haven't tried the thing of "mapping" form inputs to one or more classes in the Action parameter list, in the manner that is described in many places. Instead, I just send over parameters for each individual form field, or use FormCollection.

I was thinking I might like to try this, but I am confused about the basic premise. It seems the idea is that you use the same model for your "binding" (going from View to Controller) that you use for your ViewModel (going from Controller to View). (I am using strongly-typed views with a separate ViewModel for each View.)

Yet, I find that the needs of my View are quite different from the needs of my Action -- the View, for example, may need several SelectLists from which the user can choose. The Action, however, only needs to know which items the user has chosen, not all the options in each list.

It is really customary to use the same class going in both directions?

For example, here is one of my ViewModel classes:

    public class IntervieweeSelectLists
{
    public SelectList intervieweesList { get; set; }            
    public ClientSelectLists districtFilterLists { get; set; }
    public SchoolDisplayListInfo schoolListDisplay { get; set; } 
    public long selectedIntervieweeID { get; set; }             
    public string selectedIntervieweeName { get; set; }         
    public string selectedSiteID { get; set; }                  
    public bool needsInterviewList { get; set; }                
    public bool needsClientSelectLists { get; set; }          
}

(Plus there are some methods, etc.)

This class is needed by the View, but not all of it is needed by the Action -- i.e., intervieweesList, districtFilterLists, needsInterviewList, etc.

I guess my question is: if I were to write a custom model binder to bind this class, would I have to recreate the whole class in the model binder, including the SelectLists, the contents of which come from the database, when all I really need is the things the user has selected? Or would I set all the values from an existing instance of this class, sent in to the model binder from the View?

Sorry if this is incoherent ... something is missing from my understanding here. Help! :)

+1  A: 

I would only recreate those properties which make sense on the model binder. Having to populate the SelectListItems from the DB is a huge overhead if the property value won't be used (as generally happens) on your action unless some error occur server-side, in which case you would need to recreate the whole ViewModel to re-display the view.

Anero
+1  A: 

You don't need a custom model binder. When your IntervieweeSelectLists is returned in the controller action, your lists will be empty as the data passed back from a post will not contain that information. So you have a object that has the answers you need with empty lists. Now lets say something doesn't validate and you need to display all the lists again. Well the controllers actions knows when this model is going to be displayed so the lists only need to be populated before the model is passed into a view. If you don't need to pass the model into a view, and just store the results, as there is no need to populate the lists.

Erik Philips
Well, the reason I was considering a custom model binder is that, when I tried putting the above class in the parameter list of the Action, all the fields came back null (or default value), even though Model.IsValid was true. It just seemed like the default model binder couldn't figure it out. But it could be that I haven't followed the correct naming convention for the fields.
Cynthia
OK, when I tried changing the HTML field names to match what's in the class, I am getting values back (progress!). However, some of the fields returned are buried in lower levels of the class -- i.e., the selected district property is within the districtFilterLists object. It's not picking that up at all -- districtFilterLists is null. So I think I do need a custom model builder -- or drastically change my ViewModel class. But thanks, I feel I am finally getting somewhere. I have no colleagues -- I am the entire IT dept. -- so I needed someone to bounce ideas off of.
Cynthia
Sounds like you are writing your HTML manually. You should use the DisplayFor and EditFor html helpers to create the html for you. They will automatically create the names for you. I would highly recommend checking out the ASP.Net MVC demos on http://www.asp.net. (Also Model.IsValid is only validating, if you don't have validation data annotations, then the property is valid by default)
Erik Philips
Usually I do use HTML helpers (though not the "For" ones), but I have discovered you can't use HTML helpers when you want to set the value of a control programmatically -- e.g. I have an "add note" textbox with submit button. When a note is added, it shows up in a table underneath. At that point I want the add note textbox to go blank, but whatever the user entered remains there if it's a helper. I don't feel that's user-friendly (it's not the expected behavior to most users) so I avoid HTML helpers in those cases. Thanks for the links though; I will check them out.
Cynthia
BTW, I did end up writing a custom model binder for my notes list, as I could not figure out a way to get the default model binder to bind it -- it's a list where each one has an edit and delete button (similar to a datagrid) and the buttons do not have identical names -- the note ID is appended to the name. My custom binder works great and I am much more knowledgable than yesterday. :) Thanks for getting me pointed in the right direction.
Cynthia