Partials and AJAX In Razor Pages

Updating portions of a page using AJAX and partial views is a routine task in ASP.NET MVC applications. The experience is little different in ASP.NET Core Razor Pages - not much, but enough to stump some people. Here is some advice on accomplishing this task, and a preview of some additional help coming in the near future.

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.