Lesson 3

Customizing Handler Methods and Error Handling

Introduction

Welcome to the next lesson of our course on Razor Pages in ASP.NET Core. So far, we’ve covered the basics of page handlers and how to handle different HTTP methods within Razor Pages. In this lesson, we will dive deeper into customizing handler methods and implementing robust error handling in your web applications. Understanding how to handle errors gracefully is crucial for providing a seamless user experience and debugging issues effectively. By the end of this lesson, you will be able to create custom handler methods for different HTTP methods, configure basic and custom error handling, and display meaningful error messages to users.

Handler Methods in Razor Pages

Handler methods in Razor Pages are methods that respond to HTTP requests based on the request method (e.g., GET, POST). They help execute the appropriate logic for different types of requests.

Handler methods are methods in the code-behind file (e.g., Index.cshtml.cs) that process incoming requests. You can create custom handlers for different HTTP methods like GET, POST, PUT, DELETE, etc.

Here, we'll add a custom GET handler method in Index.cshtml.cs.

C#
1using Microsoft.AspNetCore.Mvc.RazorPages; 2 3public class IndexModel : PageModel 4{ 5 public string Message { get; private set; } 6 7 public void OnGet() 8 { 9 Message = "Hello, welcome to our website!"; 10 } 11}

In this example, we've created a handler method OnGet() that sets a greeting message. This method responds to GET requests to the /Index page.

Now, let’s update the Index.cshtml Razor Page to display the message set by the OnGet handler.

HTML, XML
1@page 2@model IndexModel 3@{ 4 ViewData["Title"] = "Home page"; 5} 6 7<div> 8 <h1>@Model.Message</h1> 9</div>

When you navigate to the /Index page, you should see the message, "Hello, welcome to our website!"

Handling Common Errors

It's crucial for any web application to handle errors correctly to provide a user-friendly experience and facilitate easier debugging.

HTTP status codes provide insight into how an HTTP request was handled by the server. Some commonly encountered ones include:

  • 404 Not Found: The requested resource could not be found.
  • 500 Internal Server Error: An error occurred on the server.

We can handle these common errors by configuring the application’s middleware to display appropriate error pages.

Example of Error Handling: Configuring Main File

Here’s how to set up basic error handling in Program.cs:

C#
1var builder = WebApplication.CreateBuilder(args); 2builder.Services.AddRazorPages(); 3var app = builder.Build(); 4 5app.UseExceptionHandler("/error/500"); // Handles server errors 6app.UseStatusCodePagesWithReExecute("/error/{0}"); // Handles status code errors 7 8app.MapRazorPages(); 9 10app.MapGet("/error/{code}", (int code) => $"Error code: {code}"); 11app.MapGet("/trigger500", context => throw new Exception("Simulated server error")); 12app.Run();

This code configures basic error handling in an ASP.NET Core application:

  1. Initialize and Configure Services: Initializes the application and adds Razor Pages services.

  2. Error Handling: Sets up middleware to handle server errors and status code errors.

    • UseExceptionHandler("/error/500"): Redirects server errors to /error/500.
    • UseStatusCodePagesWithReExecute("/error/{0}"): Re-executes requests to handle status code errors (e.g., 404) by redirecting to /error/{0}.
      • Path Template: The {0} in the path is a placeholder for the status code. For example, a 404 error transforms the path to /error/404, and a 500 error transforms it to /error/500.
      • Dynamic Path Resolution: This dynamic inclusion ensures that each specific status code is handled appropriately by directing it to a centralized error page.
  3. Map Razor Pages and Error Endpoints: Defines routes for Razor Pages and custom error pages.

    • app.MapRazorPages(): Maps Razor Pages.
    • app.MapGet("/error/{code}", (int code) => $"Error code: {code}"): Defines a custom error page showing the error code.
    • app.MapGet("/trigger500", context => throw new Exception("Simulated server error")): Defines a test endpoint that simulates a server error.
Example: Creating a Basic Error Page

To adequately display error messages when something goes wrong, we need to create a dedicated error page. Here, we'll create a simple Razor Page to handle error codes and display messages.

Error.cshtml:

HTML, XML
1@page "{code:int}" 2@model ErrorModel 3<!DOCTYPE html> 4<html> 5<head> 6 <title>Error Page</title> 7</head> 8<body> 9 <h1>Error: @Model.Code</h1> 10 <p>@Model.Message</p> 11</body> 12</html>

This HTML page will capture the error code from the URL and use it to display a relevant message to the user.

Error.cshtml.cs:

C#
1using Microsoft.AspNetCore.Mvc.RazorPages; 2 3public class ErrorModel : PageModel 4{ 5 public int Code { get; private set; } 6 public string Message { get; private set; } 7 8 public void OnGet(int code) 9 { 10 Code = code; 11 Message = code switch 12 { 13 404 => "Page not found.", 14 500 => "Internal server error.", 15 _ => "An error occurred." 16 }; 17 } 18}

This model backs the Razor page and includes logic to set the error message based on the error code. When the Error.cshtml page is accessed, the OnGet method is invoked, setting Code and the corresponding Message.

In summary, we've created a basic error page (Error.cshtml) and its associated model (Error.cshtml.cs) to handle and display error messages based on the HTTP status code. This ensures that when an error occurs, a meaningful message is shown to the user.

Custom Error Handling

In this section, we’ll look at how to customize error pages further to show more detailed information or tailored messages.

We can modify the ErrorModel to include more detailed error information or create different error pages for different status codes. Let's update the Error.cshtml and Error.cshtml.cs files to display a more detailed error message.

Update the Error.cshtml to include a stack trace:

HTML, XML
1@page "{code:int}" 2@model ErrorModel 3<!DOCTYPE html> 4<html> 5<head> 6 <title>Error Page</title> 7</head> 8<body> 9 <h1>Error: @Model.Code</h1> 10 <p>@Model.Message</p> 11 <pre>@Model.StackTrace</pre> 12</body> 13</html>

Update the ErrorModel to capture the stack trace:

C#
1using Microsoft.AspNetCore.Mvc.RazorPages; 2using System.Diagnostics; 3 4public class ErrorModel : PageModel 5{ 6 public int Code { get; private set; } 7 public string Message { get; private set; } 8 public string StackTrace { get; private set; } 9 10 public void OnGet(int code) 11 { 12 Code = code; 13 Message = code switch 14 { 15 404 => "Page not found.", 16 500 => "Internal server error.", 17 _ => "An error occurred." 18 }; 19 20 if (code == 500) 21 { 22 StackTrace = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 23 } 24 else 25 { 26 StackTrace = ""; 27 } 28 } 29}

When a 500 error occurs, this page will now display the stack trace, aiding in debugging.

Triggering and Testing Errors

Testing error handling is important to ensure that your users see meaningful messages when something goes wrong.

We can add links to our home page to simulate these errors for testing purposes. Update the Index.cshtml to include links to trigger errors:

HTML, XML
1@page 2@model IndexModel 3@{ 4 ViewData["Title"] = "Home page"; 5} 6 7<div> 8 <h1>Welcome to the Home Page!</h1> 9 <p> 10 <a href="/trigger404">Trigger 404</a> | 11 <a href="/trigger500">Trigger 500</a> 12 </p> 13</div>

Now, clicking on the "Trigger 404" link will navigate to a non-existent page, invoking the 404 error handler.

Lesson Summary

In this lesson, we focused on customizing handler methods and implementing robust error handling in Razor Pages. We covered how to create custom handler methods, configure basic and custom error handling, and simulate errors for testing purposes.

To summarize:

  • We learned what handler methods are and how to create them.
  • We configured the application to handle common errors (404, 500) and created a basic error page.
  • We customized the error handling to display detailed messages and stack traces.
  • We added links to trigger and test error handling.

Let's go and practice now!

Enjoy this lesson? Now it's time to practice with Cosmo!

Practice is how you turn knowledge into actual skills.