I'm starting to develop a new ASP.NET MVC application, and I'd like to make sure that my understanding about the way of developing applications under MVC pattern is correct.
Question 1: Suppose that I have some main views (MainView1, MainView2, ...) with some partial views in it (PartialView1, PartialView2, PartialView3, ...). From what I have understood about MVC, I should define a Model for each view. e.g. I have to define PartialModel, PartialModel2, ... and also define my main models which are containers of the partial models which have been used in them:
public class MainModel1
{
public PartialModel1 Partial1 {get;set}
public PartialModel2 Partial2 {get;set}
public PartialModel3 Partial3 {get;set}
}
This way when I want to redirect to MainView, I can initialize the models used in that view by using this Model. Is my understanding of MVC correct? Or should communication between Views and Models be in another form in MVC?
Question 2: If the above is correct, Then suppose I have a partial view in some of my main view pages. This partial view has a submit button which calls an action method. This action method should somehow return the main page's view with the right viewmodels for views. Is there any recommendation about how to get/set viewmodels of other views in a partial view's action?
Thanks.
You understanding is correct. Each view (no matter whether it is main or partial) should have a corresponding view model (unless in the very rare case where this view contains only static html of course). And following this logic a main view that has to render other partial views will have a view model which itself will have reference (maybe as properties) to view models that are required by those partial views.
There is another technique which is using the Html.Action helper. In this case the partial is rendered through another controller/action than the main one. So you don't need to reference the partial view model in the main view model. They will be completely distinct. Take a look at the following blog post to learn more about Html.Action.
Your understanding is perfectly fine. This is what you can also refer to ViewModel in Asp.net MVC.
So, What basically is an Asp.net MVC ViewModel ?
In ASP.NET MVC, ViewModels allow you to shape multiple entities from one or more data models or sources into a single object, optimized for consumption and rendering by the view. The below image illustrates the concept of a ViewModel:
The purpose of a ViewModel is for the view to have a single object to render, alleviating the need for UI logic code in the view that would otherwise be necessary. This means the only responsibility, or concern, of the view is to render that single ViewModel object, aiding in a cleaner separation of concerns (SoC). Concerns are distinct aspects of the application that have a particular purpose (i.e., concern), and keeping these aspects apart means your application is more organized, and the code more focused. Putting data manipulation code in its own location away from the view and controller, enforces SoC.
Using ViewModels in MVC for finer granularity and better SoC leads to more easily maintainable and testable code. Remember, unit testing is about testing small units.
Along with better coding practices, there are many business reasons demonstrating why you might consider using ViewModels:
Incorporating dropdown lists of lookup data into a related entity
Master-detail records view
Pagination: combining actual data and paging information
Components like a shopping cart or user profile widget
Dashboards, with multiple sources of disparate data
Reports, often with aggregate data
Related
OK, I have been hearing discussion about "ViewModels" in regards to MS's ASP.NET MVC.
Now, that is intended to be a specific kind of Model, correct? Not a specific kind of View.
To my understanding, it's a kind of Model that has a specific purpose of interacting with the View? Or something like that?
Some clarification would be appreciated.
Essentially Model and View Model are both simple classes with attributes.
The main objective of these classes are to describe (to "Model") an object for their respective audiences that are respectively the controller and the view.
So you are completely right when you say
To my understanding, it's a kind of
Model that has a specific purpose of
interacting with the View
So, while Model classes are effectively Domain Entities that your application interact with, View Models are simple classes that your views interact with.
Hope it helps :)
Update:
Microsoft has developed a specialized version of the Presentation Pattern by Martin fowler largely based on the Model-View-Controller and called it Model-View-ViewModel (MVVM) for PF application. This pattern is targeted at modern UI development platforms where UI developers have different requirements based more on business logic than traditional developers. Have a look here for a bit of theory
In the simplest of terms, I like to think of the following:
Model: Strictly looks and feels like your data model. For all intents and purposes it is only a class representation of your data model. It has no knowledge of your View or any elements within your View. That said, it should not contain any attribute decorators (ie; Required, Length, etc.) that you would use for your View.
View Model: Serves as a data-binder between your View and your Model and in many cases, is also a wrapper for your Model. It would be rendered useless without the View, so it typically isn't reusable across multiple Views and Controllers like a standard Model is.
As an example, your Model may have the following properties, which are direct representations of your data source:
public string FirstName { get; set; }
public string LastName { get; set; }
Now, since your View Model is tied to your View, it may have the following property - which concatenates the Model's FirstName field and LastName field together as one string:
[Display(Name = "Customer Name")]
public string CustomerFullName { get { return String.Format("{0} {1}", myModel.FirstName, myModel.LastName) }}
I found this article a very useful resource for understanding how the "Domain Model" and "View Model" interact within an MVC application, particularly in regards to binding. Best of all includes examples instead of abstract descriptions.
"Since MVC has been released I have observed much confusion about how best to construct view models. Sometimes this confusion is not without good reason since there does not seem to be a ton of information out there on best practice recommendations. Additionally, there is not a “one size fits all” solution that acts as the silver bullet. In this post, I’ll describe a few of the main patterns that have emerged and the pros/cons of each. It is important to note that many of these patterns have emerged from people solving real-world issues."
http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx
WikiPedia has a more complete description of Model vs. ModelView than you'll get in an SO answer: http://en.wikipedia.org/wiki/Model_View_ViewModel
I quote:
Model: as in the classic MVC pattern, the model refers to either (a) an object model that represents the real state content (an object-oriented approach), or (b) the data access layer that represents that content (a data-centric approach).
View: as in the classic MVC pattern, the view refers to all elements displayed by the GUI such as buttons, windows, graphics, and other controls.
ViewModel: the ViewModel is a “Model of the View” meaning it is an abstraction of the View that also serves in data binding between the View and the Model. It could be seen as a specialized aspect of what would be a Controller (in the MVC pattern) that acts as a data binder/converter that changes Model information into View information and passes commands from the View into the Model. The ViewModel exposes public properties, commands, and abstractions. The ViewModel has been likened to a conceptual state of the data as opposed to the real state of the data in the Model.
There is a notion of a ViewModel, but it is not generally associated with Asp.net MVC. MVC uses the Model View Controller patter, where the controller handles interactions, builds up data from the Model, and then passes that data to the View for display.
ViewModels (and the Model View ViewModel pattern) is more generally associated with Silverlight and WPF. Xaml is a bit different in that the views can do two-way binding to the ViewModels, so the technology is a little different. For example, if you bind a textbox to a field, as you type into that textbox, the value of the field is updated dynamically. This sort of interaction isn't really possible in web pages since web pages are stateless.
The similarity in the two patterns is that they are both trying to separate the logic from the display. The most common use/reason for this is testing: you want to be able to perform from code (via a testing framework) all the interactions that a user will invoke via the User Interface.
I'm looking for a best practice for embedding a form on multiple pages as a partial view.
I have a contact form I'm looking to embed on multiple pages on a site. Usually, the form would be on a contact page and the contact model could be the model for the view and use data annotations for validation. However, the view is already strongly typed.
How can I create a reusable form in a partial view and embed it on the page? I'm using N2 on the site, so the pages have to already have a strongly-typed model, but I would be open to extending those objects.
Personally, I recommend using for Html.RenderAction() for cross-cutting concerns such as these.
The handler for your contact form is going to need to exist independently of the page your are currently viewing so you are left with 3 options:
Manually add it to the response of
the current action
Manually add it to the response of
the current controller by way of a
base controller that modifies the
ViewState or ViewModel
Call the RenderAction()
HtmlHelper inside of the current view
Of these 3 options, while the third is technically more costly than 1 and 2 (because it initiates a brand new request), it is also the most maintanaible solution. By calling RenderAction() you have the advantage of being able to completely isolate your contact form from the rest of the view and thus you won't have to worry about hacking it into the current controller responses.
Use RenderPartial if data model for partial view is already in main view's model, in other case use RenderAction (then the action of the partial view will create its view model itself).
My MVC application contains a parent model, which will contain 1 or more child models.
I have set up the main view to display properties from the parent model, and then loop through a collection of my child models (of various types, but all inheriting from the same base type). Each of the child models have a corresponding partial view.
My "parent" view iterates over the child models like this:
foreach (ChildBase child in ViewData.Model.Children)
{
Html.RenderPartial("Partials/"+child.ChildType.ToString()+"Child",
section);
}
My application has the appropriate /Partials/ChildType1.ascx, ChildType2.ascx, etc. Everything works great.
Is this an appropriate way to use Partial Views? It feels slightly off-kilter due to the dynamic names, but I don't know another way to perform dynamic selection of the proper view without resorting to a big switch statement.
Is it advisable to use the same view for multiple "modes" of the same model? I would like to use the same .ascx for displaying the "read only" view of the model, as well as an edit form, based on which Controller Action is used to return the view.
Iconic,
It's difficult to answer the questions without knowing exactly what you're trying to achieve.
I'll have a go though:
If you're familiar with web forms, think of your partial view as a webforms usercontrol for the moment and think of the part of your model that is relevant to your partial views as a 'fragment of information' that want to pass across to the partial view.
Natural choices for using a partial view would be for elements used in many views across your site.
So ... in answer:
1.Although what you are doing is valid, it doesn't seem quite correct. An example of a partial view I have used might be a row in a grid of data where you'd call the partial view passing in the row object as its model:
foreach (MyObject o in Model.objects)
{
Html.RenderPartial("Shared/gridRowForObject.ascx", o, ViewData);
}
You can strongly type your views also to expect a specific type to be passed through as the Model object.
Again another use might be a login box or a 'contact me form' etc.
2._Ultimately this is a personal design decision but I'd go for the option that requires the least application/presentation logic and the cleanest code in your view. I'd tend to avoid writing to many conditional calls in your view for example and by inferring a base type to pass across to all of your partial views as in your example, may well tie you down.
When learning the MVC framework I found the Oxite code to be useful.
I hope that helps.
And what do you put in your View?
A recent blog from Scott Hanselman about using a special model binder for easier testing led me to think about the following:
What do you put in your controller logic building the view model, and what should be put in the view? what he does is this:
var viewModel = new DinnerFormViewModel {
Dinner = dinner,
Countries = new SelectList(PhoneValidator.Countries, dinner.Country)
};
return View(viewModel);
Now, I use the same way of passing data to my view, but I am unsure about how he deals with the Countries property. You could argue both sides:
Wrapping the Countries list in the SelectList prepares the data for the view, much like you create a viewmodel DTO to pass your data.
On the other hand, it somehow feels like you're specifically manipulating the data to be used in a dropdown list, limiting the way the view deals with your data from the controller.
I feel this is a bit of a gray area on the separation of concerns between the view and the controller, and I can't really decide which way to go. Are there any best practices for this?
PS: To keep it simple, let's assume the default ASP.NET MVC context, so basically your out of the box project. Default view engine and all that jazz.
In MVC (at least this flavor of it), one of the controller's responsibilities is to prepare the data for the view. So I think it is perfectly acceptable to prepare a specific model for the views consumption that implies it will be used in a drop-down. In this case the controller is just making it easier for the view and in fact prevents awkward code from having to otherwise be trickling into the view. It also keeps one from having those magic strings in the ViewData like VieData["Countries"].
So to sum up, while it may seem that there is some gray area in terms of responsibilities, ultimately that is the job of the controller: to interact with the view and to transform the domain model into other models that are easier to consume by the view.
Some suggest that having one all-encompassing view model per view is ideal (dubbed Thunderdome Principle).
On the main page of my site, I would like to show several views which rely on their own controllers for data retrieval. I do not want to retrieve anything from the DAL in my Home controller.
For example, I want to show view listing top 5 news, a view with random quote from the database, another view with the users shopping cart contents, etc.
After Googling around, I found RenderAction method which is almost perfect, but it's not available in RC1, only in Futures, and apparently, it has some issues.
I found RenderPartial as well, but that relies on the main controller to pass data to the view.
Additional clarification:
The main reason I do not want data access logic in the Home controller is to avoid repeating the code and logic. I will use top 5 news view in several pages/controllers. I do not want to repeat data retrieval in every one of them. I already did separate a lot of logic and validation to business layer. The solution I'm after is RenderAction or UserControls as in classic ASP. I know i can use them in MVC as well, but... whats the point? I mean, if what i'm asking is too complicated or too absurd (reusable UI components), then MVC is definitely not for me, and I'd consider it seriously inferior to classic ASP.NET, because this requirement is really simple.
What you're asking is to basically not perform data access in the HomeController, this seems like a dogmatic approach. I would consider either using RenderAction from the Futures assembly (not sure what's wrong with it, I use it in a number of projects) or SubControllers from MvcContrib.
While I can understand the desire not to replicate functionality in multiple controllers, I don't understand the reluctance to have your Home controller interact with the DAL. I think the partial view is definitely the way to go. My solution to not replicating the functionality would be to push the code that generates the data for the various views into your business or data layer. You could then reference it from each of the required controller actions that use the partial views. Putting it in the business layer could isolate the controller from your data layer, if that's what you desire, but I still think it's the proper job of the controller action to obtain and provide the data to the view.
Another potential solution would be to populate the view generated by your Home controller via Ajax callbacks to the various controller actions that generate the required view components. The drawback to this is that it doesn't fail gracefully in the absence of javascript in the browser.
EDIT
Based on your clarification, I would suggest implementing a base controller that fills the ViewData for the shared controls in ActionExecuted (so that it's done only when the action succeeds). Derive your other controllers from the base controller when you want to inherit this behavior.
If you really don't want to use RenderAction, then the only other option you have is to load the necessary data pieces with action filters. Your home controller could then look like this:
public class HomeController : Controller
{
[RequireNews]
[RequireQuotes]
[RequireCart]
public ActionResult Index()
{
return View();
}
}
These action filters could be re-used where they are needed. You might also choose to place these on the controller class itself.