In ASP.NET WebForms, UserControls were used to break the application into smaller pieces. Each piece represented an important part of the application. In ASP.NET MVC application you can achieve the same effect using RenderPartial and RenderAction methods. In this article we are going to demonstrate how to use RenderPartial to construct and use partial views.
Understanding RenderPartial:
RenderPartial serves the purpose of rendering a UserControl in an ASP.NET MVC application. The views rendered are called PartialViews. In order to use a partial view in your application add a MVC UserControl to your application. The screenshot below shows which project template to select when adding a user control to your MVC application.
You can add the MVC View UserControl in your current view folder or in the shared folder. First the view folder will be searched for the specified user control followed by the shared folder.
We have added a simple "Categories.ascx" to our views folder. Now, let's see how we can load the partial views on the page. Inside the view page you can load the partial view using RenderPartial HTML helper method.
Now, if you run the page you will see that the partial view is loaded inside the view page as shown in the screenshot below:
Passing Data to Partial View:
In the previous example our partial view was independent which means it was not dependent on any data populated by the view page. In real world applications this might not be the case. We may need to pass additional data to our partial view. The good news is that the partial view has access to the same ViewData dictionary which is used by the view page.
Consider a situation in which we need to pass a list of categories to the partial view. The view page List.aspx has the controller CategoryController. The controller List action is responsible for populating the categories in the ViewData as shown below:
Now, the Categories.ascx partial view can easily access the ViewData["Categories"] as shown below:
This shows that the ViewData dictionary is shared between the view page and the view user control (partial view). We can even make it better by strong typing the partial view and sending the model as a second parameter to the RenderPartial method. The code below shows how to make the ViewUserControl as a strongly typed view which can handle IEnumerable<Category> collection.
And here is the RenderPartial method passing the Model as the second parameter.
Or even better you can assign the ViewData.Model and use that to pass the Model to the RenderPartial method.
The result is shown below:
Since, the ViewData dictionary is shared between the ViewUserControl and the ViewPage you can easily make changes to the object in the ViewUserControl and it will be reflected in the ViewPage using the controller.
Caching Partial Views:
In WebForms you could easily cache the contents of the UserControl. Let's check out how we can cache partial views in an ASP.NET MVC application.
Using OutputCache Directive:
The most direct way of caching the partial views is by using the OutputCache directive. Let's add the directive on the ViewUserControl and see the result.
We are caching the ViewUserControl to "60" seconds which means it is cached to 1 minute. The DateTime is displayed on the view to indicate the request time. The DateTime value will indicate if the partial view is cached or not.
The view page List.aspx is also adjusted. It now includes an ActionLink which will call the "List" action. It also consists of a DateTime indicator just like ViewUserControl.
When you run the page and click the "Show List" button you will find out that the view user control "Categories" is never cached. Both the view page and the view user control will show the same time. There is a problem in Html.RenderPartial which prevents it from caching the user control. Html.RenderPartial method completely ignores the OutputCache directive in the user control.
Using OutputCache Action Filters:
Our next technique is to use the OutputCache action filters to cache the contents of the action. This means that we need to return the user control from the controller action. This is performed by using RenderAction HTML helper method. The render action method will invoke the action on the controller and inject the returned HTML to the calling page.
The RenderAction in the above code will invoke the "PartialList" action which is defined below:
The result is shown in the screenshot below:
The screenshot above shows that the complete view page along with the partial view is cached. Once, again we have failed to cached the component. Let's see our last approach.
WebForms Engine to the Rescue:
Phil Haack blogged about this method a while ago. He leveraged the power of the WebForms engine to cache the partial view. You can read his post here.
The idea is simple! We are going to use our view user control as a ASP.NET WebForms user control using a runat="server" tag. First, we need to register our user control in the directive which is accomplished using the following code:
Now, we can use the UserControl in our page using the code below:
Now, if you run the application and click the "Show List" button you will notice that the user control is cached at a differen t time than the page.
Hopefully, in the future release of MVC the defect in RenderPartial wil be fixed!
Conclusion:
In this article we learned about Partial Views. We also learned how to perform caching using partial views. In the next article we are going to take a look at the RenderAction HTML helper method and how it can be used in an ASP.NET MVC application.
[Download Sample]