Extending Razor Pages
If you move beyond the basics of working with Razor Pages, there are at least two things you should know to support creating Pages that do more than one thing and integrate with existing code.
In an earlier column, I advocated for Razor Pages as a better model for Web Development than the Model-View-Controller pattern. I demonstrated why I thought that way in a followup column.
But that second column just covered the basics of building Razor Pages. Here's two more things that you'll need to do with Razor Pages.
First, it's not unusual to have a View that needs more than a single processing method -- a page that supports both updating and deleting customers, for example.
The easiest way to implement that in a Razor Page is to put what you consider the "primary" function of the page behind the submit button. On a page that allows users to both update and delete a customer, the "primary" function would probably be the update function. Clicking the submit button will automatically trigger the OnPost method in your Razor Page's code file, so you should put the update code in the OnPost method.
You can implement any "secondary" activities -- deleting the customer, in this scenario -- through an anchor tag (you're free, of course, to style that anchor tag to look like a button, if you want). In the View component of your Razor Page, your anchor tag must include an asp-page-handler attribute, and you set that attribute to some string value of your choice.
In this example, since I'm supporting deleting customers, it made sense to me to set the handler's value to "Delete":
<a asp-page="/Customers/Update" asp-page-handler="Delete">Delete</a>
Your next step is to tie an OnGet or OnPost method to the value you set in the handler attribute and put the "delete customer" code in that method. To tie an OnGet method to my anchor tag with its handler set to "Delete," I'd create a method like this:
public void OnGetDelete()
Following this pattern, the code file for your Razor Page will typically have an OnGet method to support the initial display of the page, an OnPost method to support the "primary" update functionality and, potentially, multiple OnGet<handler> methods to support "secondary" functionality.
If you're uncomfortable with using OnGet methods to do updates (which does violate RESTful standards), you can also add handlers to your submit buttons using Tag Helpers. This example will, when clicked, invoke my Page's OnPostDelete method:
<input type="submit" value="Delete Customer" asp-route-handler="delete" />
Using Tag Helpers, you can also add a handler to your form's postback method. This might make sense if you're going to dynamically set the handler name when a View is requested. This example uses a property on the Model property to set the method being called:
<form asp-page-handler="@Model.HandlerName" method="post">
If, within a Controller's Action method, you're using the RedirectToPageResult method to send the user to a Page, you can pass your handler value as the second parameter to the method. That would also let you have multiple OnGet<handler> methods to handle the initial display of your page.
Integrating with ASP.NET MVC
As fond as I am of Razor Pages, I don't want to suggest that there isn't a role for the Controllers-and-Views approach (it's the obvious option when you have a method that needs to choose between different views). In addition, if you want to add additional functionality to an existing MVC application with Razor Pages, that will be easier if your new Pages can work with existing Controllers. In either scenario, you're going to need to integrate Razor Pages with Controllers.
Fortunately, that's easy to do. By default, your Razor Page methods return void. However, you can change them to return IActionResult, the interface implemented by the objects typically returned from a Controller's Action methods. This is a perfectly acceptable OnPost method, for example:
public IActionResult OnPost()
This allows you, from within your Razor Page methods, to integrate your Razor Pages with Controllers and Action methods. The PageModel class that your RazorPage inherits from includes a RedirectToRoute method, for example, that accepts Controller and Action method names. To send the user to the DisplayList method in the Customer controller at the end of a method, you could use code like this:
return RedirectToRoute("DisplayList", "Customer");
In these three columns I've tried to make a case for Razor Pages as a better model for creating Web applications, to show how to create Razor Pages and (in this column) to provide tools and advice for real-world application. Now you should be trying Pages out and seeing if you agree.
For convenience, the first two columns are:
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.