The name "view model" suggests that it models the data for the view. That much is obvious. What else can or should go in the view model?
As an example, a view might display a list of items in a shopping cart, fields for customer's credit card info, and fields for customer's billing information. The view model might contain properties for all that OR it might only contain properties for the shopping cart items.
The view model is a class that represents the fields that your view shows/modifies. So for example if you are going to show a shopping cart and customer's credit card all on the same page these properties should all belong to the view model.
You could even put properties like this in your view model if the view is going to show a drop down list of day names:
public IEnumerable<SelectListItem> DayNames
{
get
{
return CultureInfo
.CurrentCulture
.DateTimeFormat
.DayNames
.Select((dayName, index) => new SelectListItem
{
Value = index.ToString(),
Text = dayName
});
}
}
How exactly you use your view models is a judgement call. One developer might have fewer typed ViewModels so they can be reused. Another developer might have more ViewModels, each smaller and more specific to particular actions. And another developer might rely more on ViewData.
If possible, have your view models be well-organized, contain just what the view needs, and consist mostly of light entity objects. If you have a complicated view though, don't be afraid to make a highly customized view model class that will help simplify the view logic. It's okay to make reusable ViewModels that have a little unused data in them, but avoid using just a few one-size-fits-all ViewModels. ViewModels should have just the data needed for that view or very close.
Related
I am planning a new mvc 3 application.
I am trying to make things as simple as possible.
Here's my question.
I'm planning on having many different models with different params. I am going to have crud operations for all these models but I don't want to have a view for each one. I would like to have one list view and one edit view.
I know this goes agains the lose coupled style of mvc architecture but It would be very handy just for me to send the view a model and the view would work out what fields to add etc.
Has anyone heard o a way to do this?
MVC has an Html.EditorFor() helper into which you can give a whole model and MVC will generate a form from it. I have not tried whether this works dynamicly when your view's model is type of object and you give concrete objects into it, but it might work.
But for all those headaches you will have in the future with your approach I would strongly suggest for you to try to make your different models into an object hierachy (so you will have inherintance) and compose your views with different partial views based on the model's type.
I have used the last way of doing things sucessfully on many occasions. Something in the lines of (code in your topmost view):
#model Animal
//Show Animal fields
#if(Model is Cat)
{
//show cat specific fields
Html.Partial("_cat", Model);
}
else if(Model is Dog)
{
//show dog specific fields
Html.Partial("_dog", Model);
}
So in your controller you could pass either a Dog, Cat or Animal to this view and what would be rendered is dependent on the Model's type.
I have an MVC3 C#.Net web app. I have two views that display the same HTML table. However, each View represents a different Model. View 1 = "ProposalEdit", View 2 = "DocEdit". Both the Proposal model and the Doc model have a property:
ICollection<Deliverable> Deliverables.
In each of the Edit Views, I display the Deliverables belonging to the Model of that View. It's identical code in each of the Edit Views, only the Model behind the Edit Views is different. So, there's a lot of duplicate code.
How can I modularize this in order to reduce the duplicate code?
#Mike, that is exactly what I would do. The main point though is having the DisplayTemplates for each model. Even a DateTime object could have a DisplayTemplate if you wanted to.
Edit:
Here's an example of using the DisplayTemplate for just the Deliverables model
#model ICollection<Deliverables>
#foreach (var deliverable in this.Model)
{
#this.Html.DisplayFor(d => deliverable)
}
You would also, of course, have a template under ~\Shared\DisplayTemplates\Deliverables.cshtml or for editing under ~\Shared\EditorTemplates\Deliverables.cshtml
I have an MVC3 project I'm working on that has a View with an associated strongly typed view model. I've been tasked with adding an optional section to this view that would contain the data for a second model, about half of which is shared with the first model.
My question is, what is the best way to implement this? Should I just add the object that the optional model represents to the view model and try to map values from there?
If I do it this way, how can I associate the editors with both models?
Adding the optional model to the view model is the best choice, because, unlike ViewBag, it's type safe and you can still leverage the html helpers. Just remember to check the second model for null reference before you render it (since it's optional).
For sharing properties, your view model can have special getters/setters that would mantain both models synchronized internally.
I think I understand what your asking and this is how I have accomplished it in the past.
Add the optional model as a parameter in the view model and then create a partial view that is typed to that optional model. If the criteria is met that allows that partial view to display then you pass the viewmodel.optionalmodel to that partial view.
You just have to be a bit careful about the overlap of parameters causing any headaches (as in null references)
I am building an admin console and all controllers depend on a dropdown selection for customer.
I would like to move this customer selection to the layout and persist it across all controllers so that you do not need to select it everywhere.
What is the best way to go about doing this?
Thanks in advance.
Move the dropdown to your _layout.cshtml.
Create a BaseView that all views will inherit from and give it a property to store the Customers & Current Customer.
Create a BaseController method that will fill in a BaseView instance.
Store the currently selected customer on your session.
Create a Global Filter and have it check all views to see if they inherit BaseView. If they do it can convert them to a BaseView and then fill in the properties.
Write some code in the _layout that can use the View to fill in the dropdown. I'm a bit fuzzy here since my coworker actually did this part when we did something similar.
When the user changes the dropdown value you can use JSON to call an action method that will update the current customer in session.
I would consider writing HTML helper. You assume that all the birds can fly, but say one day you have another exceptional scenario and you no longer need this dropdown box. Alternatively include it in a partial view and render that view where you need it - it's only one extra line of code.
E.g.
#section main_content{
#{ Html.RenderPartial("MyPartialViewContainingDropDownBox"); }
}
Being a relative newcomer to MVC I'm musing over a little problem. I'm developing a page which relies on a collection of my viewmodel objects. All good. But, as the page has relatively complex functionality I need to get at other objects or collections of the main domain model to display in the UI. Admitedly rather more light weight objects. What's the best way to achieve this?
What I do is create a custom class to encapsulate ANY data I need to display in any certain view / action. So for my Admin areas User controller, I have a AdminUserIndexViewModel class that holds my list of user business objects. I also put any other data I need to display into this class.
For my AdminUserEditViewModel (that corresponds to my Admin Area, User Controller, Edit Action) I might have a single User class, which itself has its Roles attached to modify if need be. If you need to put other information like user settings, or preferences, etc...
If they are not part of the viewmodel you are currently working with then you can use Html.Action to call into another controller method to render another inline view through a controllers method.