Reuse UI with Partial Views in ASP.NET Core MVC and Razor Pages

While developing ASP.NET Core web applications you often need to reuse parts
of the user interface across many view or razor pages. There are multiple
options to address this requirement simplest being Partial Views. In this
article you will learn what partial views are and how to use them in ASP.NET
Core MVC and Razor Pages applications.
Partials views are .cshtml files that house user interface elements such as
HTML markup tags, tag helpers and razor code. Once created you can use the
partial views on main views and razor pages of the application. By convention
partial page names begin with an underscore (for example, _Partial1.cshtml). For
ASP.NET Core MVC applications they are typically stored under Views/<Controller>
or Views/Shared folder. For ASP.NET Core Razor Pages they are typically stored
under Pages, Pages/<CallingPageFolder> or Pages/Shared folder.
Now that you know what partial views are, let's create one and then use it in
an ASP.NET Core MVC application.
Create and setup a new ASP.NET Core MVC application. Add Shared subfolder
under the Views folder and add a partial view named _CountriesPartial.cshtml
into it.

The _CountriesPartial will render a list of countries as shown below:
@foreach(var item in Model)
{
<h2>@item</h2>
}
Notice that the foreach loop uses Model property. By default, partial views
get access to the view's model. Here, Model refers to the Index views model.
This model is generated in the HomeController as follows:
public IActionResult Index()
{
List<string> countries = new List<string>();
countries.Add("USA");
countries.Add("UK");
countries.Add("India");
return View(countries);
}
As you can see, the Index() action creates a List<string> containing a few
countries. The List<string> then goes to the Index view as its model. Since _CountriesPartial
is housed inside the Index view (discussed soon), the same Model is available to
_CountriesPartial also.
Now that you have _CountriesPartial ready (see the Solution Explorer below)
it's time to use it in the Index view.

There are various ways to render the content of _CountriesPartial onto a
view. They are listed below:
- Use <partial> Tag Helper
- Use Html.Partial() HTML helper
- Use Html.PartialAsync() helper
- Use Html.RenderPartial() method
- Use Html.RenderPartialAsync() method
The <partial> Tag Helper uses tag oriented syntax to indicate the location
where the content of a partial view is outputted. The following markup shows how
it can be used:
<partial name="_CountriesPartial" />
The Partial() and PartialAsync() HTML helpers are quite similar in that they
accept the name of the partial view to be rendered. As you might have guessed
the PartialAsync() helper does so in asynchronous manner. The following code
shows how these helpers can be used.
@Html.Partial("_CountriesPartial")
@await Html.PartialAsync("_CountriesPartial")
The RenderPartial() and RenderPartialAsync() methods write the content of the
partial view directly on the response stream. The Partial() and PartialAsync()
return a string containing the response content of the partial view whereas
RenderPartial() and RenderPartialAsync() return void. The following code shows
how these methods can be used.
@{
Html.RenderPartial("_CountriesPartial");
}
@{
await Html.RenderPartialAsync("_CountriesPartial");
}
Notice they these methods must be called inside a razor code block since they
are void methods.
The following figure shows a sample run of the application.

Using Partial Views in Razor Pages
The use of partial views in razor pages is quite similar to MVC application.
However, there a few differences. Firstly, the partial views are typically
located inside the Pages folder.

For example, here we store _CountriesPartial.cshtml inside the Shared
subfolder of Pages folder. The Index razor page can then house the partial view
using the same techniques discussed earlier.
The following code shows how the List<string> containing a few countries is
generated in the Page Model class.
public class IndexModel : PageModel
{
public List<string> Countries { get; set; }
public void OnGet()
{
Countries = new List<string>();
Countries.Add("USA");
Countries.Add("UK");
Countries.Add("India");
}
}
Notice that the OnGet() page handler create a List<string> as required and
assigns it to the Countries page model property.
The _CountriesPartial.cshtml can render the country list as follows:
@foreach(var item in Model.Countries)
{
<h2>@item</h2>
}
Since counties are expose through the Countries page model property, the
foreach loop accesses them using the Model.Countries property.
The _CountriesPartial.cshtml can be used on the Index partial page just like
the MVC example discussed earlier. The following code shows how the <partial>
Tag Helper can do the job for us.
@page
@model PartialsDemo.Pages.IndexModel
<partial name="_CountriesPartial" />
Specifying model for the partial view explicitly
In the preceding examples the partial view implicitly got access to the main
view's model or page model. However, you can explicitly pass model to the
partial view. Consider the following Index() action.
public IActionResult Index()
{
List<string> countries = new List<string>();
countries.Add("USA");
countries.Add("UK");
countries.Add("India");
ViewBag.Countries = countries;
return View();
}
Here, the List<string> is stored in ViewData rather than passing to the Index
view directly. Then the Index view can explicitly pass this List<string> to the
_CountriesPartial as shown below:
<partial name="_CountriesPartial"
model='ViewData["Countries"]' />
@Html.Partial("_CountriesPartial",ViewData["Countries"])
As you can see, the <partial> Tag Helper now uses the model attribute to
supply the model to the _CountriesPartial.cshtml. Similarly, the Partial() HTML
helper supplies the model via the second parameter.
You can accomplish the same thing in razor pages like this:
<partial name="_CountriesPartial" model="Model.Countries" />
@Html.Partial("_CountriesPartial",Model.Countries)
Here, the model is supplied using the Countries page model property. Since
the model is supplied explicitly the _CountriesPartial needs to be changed
accordingly:
@foreach(var item in Model)
{
<h2>@item</h2>
}
Notice that now the partial view simply uses Model property (rather than
Model.Countries) to access the Listt<string>.
Strongly typed partial views
You can also create strongly typed partial views using the @model directive
and get all the benefits of strongly typed views such as IntelliSense and design
time error checking.
@model List<string>
@foreach(var item in Model)
{
<h2>@item</h2>
}
That's it for now! Keep coding!!