Partial Views
So far, we have only worked with complete Views - everything returned to the client exists in this View. However, there are many ways of splitting up the markup into several places, which is a good thing for several reasons, the most obvious being to re-use view markup and/or logic in multiple places.
We'll talk about Layouts, the concept where you can have a common template wrapped around your Views, in one of the upcoming chapters of this tutorial, but right now we'll discuss Partial Views. As the name indicates, Partial Views allows you to split your Views into several files. Why would you want to do that?
The most obvious reason is of course that you can take a part of a View and separate it into a Partial View, allowing you to re-use this specific part in other views as you want to. So for instance, if you have a login form on your page, you can put this into a Partial View and insert it wherever you would like for a login form to appear, across multiple pages. As an added benefit, you are making the original View less cluttered, by breaking it up into smaller components.
Now that you know what a Partial View is, let's talk about how you can add one to your project and then use it in your Views.
Adding a Partial View
Partial Views in ASP.NET MVC usually follow these conventions:
- They are located in the same folder as the View using it, or if multiple views are using it (the most common situation) they should be placed in a "Shared" folder inside of your Views folder
- Its filename usually starts with an underscore, simply to indicate that this is not a regular/full View
With that in place, let's add the Partial View. We'll add it to our Shared folder, to ensure that all of our Views can access it easily:
In the dialog, just make sure that you check the "Create as partial view":
Visual Studio will now create a new empty View for you, which you can put markup and Razor code into just like with a regular View. For instance, I put the following into my Partial View:
<div>Hello, world!</div>
<div>Today is @DateTime.Now.ToString()</div>
Now let's try referencing it from one of our Views, e.g. one you created when we discussed regular views earlier in this tutorial. We'll use one of the methods of the Html Helper object found in the MVC framework called PartialAsync():
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
@await Html.PartialAsync("_Greeting")
<span>More stuff here....</span>
Don't worry about the await keyword at this point - it relates to the Asynchronous nature of the PartialAsync() method, but it's a bit beyond the scope of this tutorial.
When your View is rendered, the content of the Partial View is automatically injected into the place where you called the PartialAsync() method, mixing in with the rest of the View. Notice that we didn't have to specify a complete filename and path of the Partial View - the Shared folder is automatically searched during the View Discovery process. However, if you had placed your Partial View in an entirely different place, you may need to specify the full, relative path like this:
@await Html.PartialAsync("/Views/SomeFolder/SomeSubFolder/_Greeting.cshtml")
Passing data into Partial Views
Since a Partial View is basically just a regular View, you have the same options if you need access to data in your Partial View. You can use a strongly typed Model (e.g. the same Model used in the parent View) or custom data through a ViewDataDictionary instance or even a combination of both. Since these mechanisms are the same for regular Views and Partial Views, I won't go into details about it here, but instead dig deeper into the subject in our article on passing data into Views.
I will leave you with a cool little example of how all of this can be done with the PartialAsync method, though. It's based on a pretty common scenario, where your Partial View contains the markup needed to render an object multiple times inside your View. We can do this by calling the PartialAsync() method inside of a loop and we can use a ViewDataDictionary instance to pass in the index of the current iteration:
@for (int i = 0; i < 3; i++)
{
@await Html.PartialAsync("_Greeting", Model, new ViewDataDictionary(ViewData) { { "index", i } })
}
Inside your Partial View, you can easily access the custom data:
<span>
Iteration number @ViewData["index"]
</span>
By default, you can automatically access the same ViewData in your Partial View as in the parent View, but as illustrated by the example above, you are of course free to pass in new data.
Summary
Partial Views allow you to split your Views into small "components", which can be re-used across multiple Views, while making the original View less cluttered.