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.