Join Jess Chadwick for an in-depth discussion in this video Handling HTTP verbs with custom logic, part of ASP.NET Core: Razor Pages.
- [Narrator] Now that I've created the HTML form that allows users to post data, it's time to shift focus back to the server and process that data. When Visual Studio initially generated this page model, it generated a class that was completely empty, except for one method; a method named OnGet that doesn't have a return value. This is a clue to help you get started using one of Razor Pages' most powerful features: the ability to execute different code based on the HTTP Verb that the request was made with.
In other words, whenever this Razor Page is requested through an HTTP Get request, like when you navigate to the page in the browser, Razor Pages looks for a method named OnGet and executes it prior to rendering the Razor in the CSHTML page. Likewise, when a Razor Page is requested with an HTTP Post request, as is what happens during a form post, Razor Pages looks for a method named OnPost and executes it prior to rendering the page's markup.
Since this page is going to be used to add and edit recipes, it should first be able to load the data for an existing recipe on the initial Get of the page so that the ASP4 helpers can populate the form fields for editing. To load the recipe, I'll add the following code into the OnGet method. First I'll create an instance of the recipesService. Then, I'll call the find method on that service to retrieve a specific recipe from the database.
I'll pass in the recipe's ID from the ID property on this class. I'm using GetValueOrDefault here to convert the nullable long value into a regular long value. If the ID is null, it'll pass the value '0' to the find method, which will return a null recipe. Then at the end, if for whatever reason the find method returns a null value, just create a new recipe object instead. Note that just like I can use Add Inject to inject dependencies in a view, I can also inject this RecipesService into my page model class as well.
Except in a class, you do it a little bit differently. Just add the dependency as a constructor parameter. Simple enough. Now let's run the page and see it in action. And there it is, the data for the existing recipe. One nice thing about Razor Pages is that it has full support for asynchronous calls and that applies to the OnGet as well.
That means that I can change this method to use C-Sharp's async and await key words to return a task and then use the async version of this method. I won't demonstrate this code since you won't be able to tell the difference anyway, but now that the OnGet method returns a task, Razor Pages will wait for this data to load before completing the request.
For what it's worth, a lot of people like to put the suffix 'async' at the end of asynchronous methods like this, which Razor Pages supports as well. Since both variations are supported, it's really up to you and your personal preference. Now that the page is executing logic OnGet request, let's wire it up to handle posts as well. To do that, I'll add a new method that looks exactly like the OnGet method, except named OnPost.
I'm not actually going to show you how to work with the post and form data just yet. That'll come in just a little bit. However, for now, let's have this method pretend that is has successfully saved the data and redirect to the recipe page that's supposedly been updated. To do that, I'm going to have this method return an object called an action result. Since this is an asynchronous method returning a task already, that means I'm going to change the type of the task to the generic Task<IActionResult.
An action result is Razor Pages' way of communicating what you want to happen to the request after the method has been run. As you've already seen in the OnGet method, Razor Pages doesn't make you return an action result. However, if your method returns 'void' or a task without a return value, then Razor Pages treats that as the equivalent as returning a page result, which would look like this: The page result action simply says, "I'm done executing logic. Go ahead and render the markup in the Razor Page." Now page result is a pretty good default, but there are plenty of other types of action results that allow you to do things such as return a custom HTTP status code, reject the request as unauthenticated, redirect to another URL, or even render some raw content directly into the response that has nothing to do with the markup in the Razor Page.
You can check out the Razor Pages documentation to see all of the various action result types and how to use them, but for now, I'm going to have this post request redirect the user to the recipe page with a RedirectToPage result by using the associated helper method available on the page model base class. I'll use the version of the helper that takes two parameters: the path to the Razor Page and any route values that it needs.
In this case, I'm redirecting to the recipe page in the root of my site, and passing the ID of the recipe currently being edited. With this information, Razor Pages will look at the route data for the recipe page and automatically generate the correct URL to get there. The net result? When I run the site, and post the form by clicking the submit button, the OnPost method is executed, returns our RedirectToPage action result, and the Razor Pages framework redirects me to the recipe page.
- Creating a new application
- Setting up pages
- Rendering dynamic content
- Reusing markup with layouts
- Increasing the maintainability of pages
- Processing data
- Validating input
- Securing an application