views:

54

answers:

2

A "Lookup" in this example is an IList<string> of state abbreviations. Generally, your Domain Model POCOs won't include these options. ViewModels usually take this responsibility referencing both the original Domain Model as well as the Lookup object, but what happens when the Domain Models are nested and you are using MVC templates (which won't have access to the original Model's root properties?

Is there a way to include the Lookups in one object and the Model in a different object for the template? Is it permissible to assemble on-the-fly a ViewModel specific to that Template within the View (which would have to include any nested data from there)? I would think static methods to pull down Lookup values is bad.

Any ideas?

Notes (to my knowledge):

A Domain Model POCO from a repository doesn't change in structure. If you need a single Model to have both the Customer object and the DDL options for US State for example, you normally have a ViewModel that references the Customer object and the Customer Lookup lists.

However, when you have a nested Domain Model (aggregate root), the nested objects have no where to put the Lookup Lists, and the MVC templates cannot access the root level View Model (their view model is the partial Model).

Edit:

Is there some way to put the DDL lists in the root level of the ViewModel, then when you get to the Customer object, construct a new ViewModel that references the root level DDL lists and the current Customer object to send to the template? This would eliminate duplicate data in the Model as well as use a single Model for all the Views. The only bad would be Controller like data assembly code in your view (which is just as bad).

+1  A: 

For static, unchanging lists like state abbreviations, you could use Application state or Cache entry. These types of lists could be loaded in Application_Start from a database.

Dave Swersky
Not a bad idea, but if you figure out how to get templates to access dynamically changing option lists too, you would probably handle them all the same.
Dr. Zim
+2  A: 

A couple of suggestions. First, use separate view models for your views -- don't directly use your domain models. These view models can, and should, carry the extra data needed by the view. Second, you can use the overloads on DisplayFor/EditorFor to pass additional view data to the template. That way your template can be specific to a particular domain model and yet have access to the additional data in the view model.

tvanfosson
That works great until you have nested Domain Models. If you have Order->Customer where Customer gets their own Template, how does the template access the US State choices? You would have to have a VM for the Order, then a sub VM for the Customer, but somehow link Order to Customer with the VMs involved without altering their POCOs.
Dr. Zim
Which would mean that Order.OrderLine[0] would become something like OrderVM.Order.OrderLineVM[0].OrderLine for the data, OrderVM.OrderOptionsVM for the Order option lists and OrderVM.Order.OrderLineVM[0].OrderLineOptionsVM for the Order Line options. This means you would repeat the DDL lists for each OrderLine in your data.
Dr. Zim
@Dr. Zim - if you put in additional view data, for example, the DDLs, when calling DisplayFor, this should be propagated through-out any nested calls since it's added to the ViewDataDictionary passed to the template (which would, in turn, pass it to any templates that it renders). It's not ideal, since it's no longer strongly-typed, but I think it should work. You would then only need to add it to the top-level view model, then add it as additional view data for each template rendered, e.g., `<%= Html.DisplayFor( m => m.Order, new { States = Model.StateList } ) %>`
tvanfosson