Aspian
Aspian

Reputation: 2065

Custom error handling middleware in ASP.NET Core 3.1?

I am working on a project in ASP.NET Core 3.1. by using clean architecture which is composed of 4 different layers namely Persistence - Domain - Application - Web.

In the Web layer, I have an Admin area which is going to be made with React and also I have an online store which will be using this Admin area but it will be made as an html online store without using REST API. My REST API routes is like this: localhost:5001/api/v1/...

I wanted to know, how could I make a custom error handling middleware which will be able to send status code and error message as json when there is an error in my REST API service and at the same time, it will be able to send them as html views when there is an error in html pages which don't consume REST APIs.

Upvotes: 2

Views: 3806

Answers (2)

joakimriedel
joakimriedel

Reputation: 1969

One way would be to differentiate the requests by path.

In your Configure method:

app.UseWhen(o => !o.Request.Path.StartsWithSegments("/api", StringComparison.InvariantCultureIgnoreCase),
    builder =>
    {
        builder.UseStatusCodePagesWithReExecute("/Error/{0}");
    }
);

This assumes that your API Controllers are marked with [ApiController] attribute and that you use at least compatibility version of 2.2 which will render JSON Problem Details (RFC7807).

Edit: Unintentionally left out the HTML part. You also need a controller action that routes the Error codes to render HTML results. Something like

[AllowAnonymous]
[Route("/Error/{code:int?}")]
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error(int? code)
{
    ViewBag.Code = code.GetValueOrDefault(500);
    return View();
}

and a matching Razor page such as

    <h1>Error @(ViewBag.Code ?? 500)</h1>

Upvotes: 3

mehtarit
mehtarit

Reputation: 111

I have not tested this code, however, what do you think about using customExceptions and then handling your response based on the exception thrown?

public async Task Invoke(HttpContext httpContext)
{
    try {
      await _next.Invoke(httpContext);
    }
    catch (RestApiException ex) {

      httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;  
      httpContext.Response.ContentType = "application/json";
      string jsonString = JsonConvert.SerializeObject(ex.Message);
      await httpContext.Response.WriteAsync(jsonString, Encoding.UTF8)
    }
    catch (HtmlPagesException ex)
    {
       httpContext.Response.StatusCode =   (int)HttpStatusCode.InternalServerError;  
       context.Response.ContentType = "text/html";
       //write the html response to the body -> I don't know how to do this yet.
    }

}

Upvotes: 3

Related Questions