Partial Pages consist of fragments 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. They can also be used to provide content for updating part of the rendered web page via AJAX in client side script.
A partial page is a single .cshtml file. It has no PageModel and it doesn't
have an @page directive at the top. A partial can be strongly typed
- have an @model directive, or it can work purely with ViewData.
For the purposes of this article, I will be using a strongly typed partial.
The example will use the same ICarService that I featured in a
previous article I wrote about
working with JSON in Razor Pages. A collection of Car objects
will be passed to the partial for display, which will be invoked via client-side
script. I'll include the code for the creating and registering the
ICarService here to save time:
First, the Car entity:
The service has one method that conforms to an interface, generating and returning a list of cars:
This service is registered with the ASP.NET Core Dependency Injection system so that it can be made available throughout the application:
The partial itself is contains an HTML table styled using Bootstrap. It is named _CarPartial.cshtml and is placed in the Pages/Shared folder - that being one of the default search locations for partials in Razor Pages. The model that the partial expects is a List<Car>:
In MVC, the partial would be returned from a controller action. The equivalent in a Razor Pages application is a
handler method.
Most often, the handler method that serves up partials will not be the primary
handler method in a specific page. Instead, a named handler will be used. The
following code shows a basic PageModel that includes a named handler (
OnGetCarPartial) returning a
PartialViewResult:
The thing that is missing from Razor Pages is the Partial helper method
(return Partial(...)) that MVC enjoys. Therefore you have to
explicitly create an instance of PartialViewResult and return that,
passing in the current ViewData dictionary and, optionally, a model for the
partial (if it expects one).
Here is the content page where jQuery is used to make the AJAX request when the button is clicked:
Notice particularly the URL that is passed to the load method -
the name of the named handler method (without the OnGet part) is
passed to a querystring value called handler. If you prefer not to
have a query string, you can create a
route template in the Razor Page that adds an optional item named
handler to the route values:
@page "{handler?}"
This enables you to can pass the name of the handler as a segment of the URL:
$('#grid').load('/ajaxpartial/carpartial');
Here is an alternative version that uses the Fetch API instead of the XMLHttpRequest object via jQuery:
The good news is that the boilerplate required to construct the
PartialViewResult will no longer be necessary from ASP.NET Core 2.2 (due
to RTM later this year), because the PageModel class will be
getting a Partial helper method just like controllers in MVC. At
that point, the current OnGetCarPartial method can be changed to the
following:
Summary
So the trick to returning Partials from client-side code in Razor Pages is to
explicitly construct an instance of PartialViewResult (at the
moment) and to return that, and to use named handler methods in an existing
PageModel rather than creating new Razor Pages just to return Partials.