Razor Pages tip: Define extra handlers for a Razor Page
Hey, before you start reading! I am in the market, looking for new freelance employment opportunities. If you need assistance on any of your ASP.NET Core projects, I am available for hire for freelance work.
I have been tinkering with Razor Pages a little but, and had a requirement where I wanted to make an AJAX request to the server from a Razor Page. A Razor Page source file typically contains 2 handlers, namely OnGet
and OnPost
which handles GET
and POST
requests respectively:
public class IndexModel : PageModel
{
public void OnGet()
{
// Process GET requests
}
public void OnPost()
{
// Process POST requests
}
}
If the handler is an async
method, you can also optionally use an Async
suffix, for example:
public class IndexModel : PageModel
{
public async Task<IActionResult> OnGetAsync()
{
// Process GET requests
}
public async Task<IActionResult> OnPostAsync()
{
// Process POST requests
}
}
As I mentioned before, I wanted to make an AJAX request from the web page, back to the server. Well, it turns out that you can define extra handlers if you choose to. Let’s say for example that I had a handler which returns a JSON result containing a list of stores:
public class IndexModel : PageModel
{
public void OnGet()
{
// Process GET requests
}
public void OnPost()
{
// Process POST requests
}
public IActionResult OnGetStores()
{
// return JSON result with store information
}
}
You can now invoke that handler by passing along the handler
query string parameter, and specifying the name of the handler you wish to invoke. If the name of the method is OnGetStores
, then the name of the handler is stores
. Same, if the name of the method was OnGetStoresAsync
, the name of the handler would also be stores
.
So in other words, assuming the URL for my Page is /map
, I can simply make a GET
request as follows:
GET /map?handler=stores
I did not like passing the name of the handler in a query string, but preferred passing it as part of the path. Well it turns out you can do that as well by adding a route template to the @page
directive:
@page "{handler?}"
@model IndexModel
<!-- rest of code omitted -->
Now I can invoke that handler by making the following request:
GET /map/stores
This is fully documented, but it seems many people miss the fact that you can do this. For more info also refer to the official ASP.NET Core docs: