Partial Pages

Partial Pages are Razor files containing snippets of HTML and server-side code to be included in any number of pages or layouts. Partial pages can be used to break up complex pages into smaller units, thereby reducing the complexity and allowing teams to work on different units concurrently.

Rendering Partial Pages

Partial pages are included in the calling page in a number of ways. The page's Html property has a Partial() method:

@Html.Partial("MenuPartial")

The Html property also offers 3 other methods for rendering the content of partial pages: PartialAsync, RenderPartial and RenderPartialAsync. Both methods ending with Async are for rendering partials that contain asynchronous code, although the preferred way to render separate units of UI that are dependent on asynchronous processing is to use ViewComponents. Both of the methods with Render in their name return void whereas the other two methods return an IHtmlString (raw HTML). Therefore the Render methods must be called within a code block as a statement:

@{ Html.RenderPartial("MenuPartial"); }

The Render methods result in their output being written directly to the response, so they may result in improved performance in certain situations. However, in the majority of cases, these improvements are unlikely to be significant, so the Partial and PartialAsync methods are recommended on the basis that you should strive to minimise the number of code blocks in your Razor page.

Calls to any of the rendering methods do not result in Viewstart files being executed.

From ASP.NET Core 2.1, the recommended mechanism for including partial pages is the Partial tag helper:

<partial name="MenuPartial" />

Naming And Locating Partial Pages

Whether you use the tag helper or the Html.Partial or Html.RenderPartial methods you do not pass in the path of the partial file. The framework searches predetermined locations for the file name that you pass in: the root Pages folder, [Pages root]/Shared (from ASP.NET Core 2.1 onwards), and a folder named Views/Shared. The last of these locations is the default location for partial views in an MVC application.

It is possible to add any location to the search paths using Razor view engine options in the ConfigureServices method in StartUp. The following code block adds the Pages/Partials folder to the search paths, meaning that you can place partial files there and have them found:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().AddRazorOptions(options =>
    {
        options.PageViewLocationFormats.Add("/Pages/Partials/{0}.cshtml");
    });
}

Partial files do not have any kind of special naming convention. The default site template includes partials named _ValidationScriptsPartial.cshtml and __CookieConsentPartial.cshtml. The leading underscore in the file names serves no technical purpose, but it became customary to name any Razor file that isn't intended to be served directly with a leading underscore in MVC 3 onwards, with the introduction of the Razor view engine e.g. _Layout.cshtml, _ViewStart.cshtml etc. The reason for this lies in the older ASP.NET Web Pages framework, where Razor was originally introduced. The Web Pages framework was configured to explicitly forbid the serving of files with the leading underscore in their name.

Strongly Typed Partials

Just like standard Razor pages, partial pages support the @model directive specifying the type for the partial's data model. All of the rendering methods have overloaded versions that take a model to be consumed in the partial.

The following example features a standard Razor page named PartialDemo.cshtml along with its PageModel file content (shown first). The PageModel class includes a property named Animals of type List<string> that will be passed from the PartialDemo content page as a model to the partial:

PartialDemo.cshtml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorPagesTest.Pages
{
    public class PartialDemoModel : PageModel
    {
        public List<string> Animals = new List<string>();
        public void OnGet()
        {
            Animals.AddRange(new[] { "Antelope", "Badger", "Cat", "Dog" });
        }
    }
}

Here is the content page PartialDemo.cshtml, which includes a partial taghelper passing the Animals property to Partial1.cshtml as its model:

@page
@model PartialDemoModel
@{
}
<partial name="_Partial1" model="Model.Animals" />

And finally the content of the partial, named _Partial1.cshtml with the @model declaration:

@model List<string>
<h1>List of Animals</h1>
<ul>
    @foreach (var item in Model)
    {
        <li>@item</li>
    }
</ul>

The PageModel includes a property named Animals, which is a list of strings. This is populated in the OnGet handler and then passed to the partial page in the tag helper.

The partial has an @model directive, specifying that the model for the page is expected to be a list of string. The content is iterated and rendered as an unordered list:

Rendering partial with a model

Note that the partial page does not feature an @page directive. That would make the file a full Razor Page and will lead to a NullReferenceException related to the model not being declared.

Last updated: 05/07/2018 11:54:39

© 2018 - Learn Razor Pages.
All rights reserved.