- Exception Handling (1), in ASP.NET MVC
- Exception Handling (2), in ASP.NET Web API
- Exception Handling (3), in ASP.NET Core MVC
- Exception Handling (4), in ASP.NET Core Web API --- this article
- Exception Handling (5), in ASP.NET Summary
- Exception Handling (6), HttpStatusCode
- Exception Handling (7), C# Exception Handling Statements
Introduction
- A: Exception Handling in Development Environment for ASP.NET Core Web API
- Approach 1: UseDeveloperExceptionPage
- Approach 2: UseExceptionHandler // This is something new compaired to ASP.NET Core MVC, but we can do the same for MVC module
- B: Exception Handling in Production Environment for ASP.NET Core Web API
- Approach 1: UseExceptionHandler
- 1: Exception Handler Page
- 2: Exception Handler Lambda
- Approach 2: UseStatusCodePages
- 1: UseStatusCodePages, and with format string, and with Lambda
- 2: UseStatusCodePagesWithRedirects
- 3: UseStatusCodePagesWithReExecute
- Approach 3: Exception Filter
- Local
- Global
- Approach 1: UseExceptionHandler
A: Exception Handling in Developer Environment
Approach 1: UseDeveloperExceptionPage
The ASP.NET Core starup templates generate the following code,
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
......
}
The UseDeveloperExceptionPage extension method adds middleware into the request pipeline. The Developer Exception Page is a useful tool to get detailed stack traces for server errors. It uses DeveloperExceptionPageMiddleware to capture synchronous and asynchronous exceptions from the HTTP pipeline and to generate error responses. This helps developers in tracing errors that occur during development phase. We will demostrate this below.
- Start Visual Studio and select Create a new project.
- In the Create a new project dialog, select ASP.NET Core Web Application > Next.
- In the Configure your new project dialog, enter WebAPISample for Project name.
- Select Create.
- In the Create a new ASP.NET Core web application dialog, select,
- .NET Core and ASP.NET Core 5.0 in the dropdowns.
- ASP.NET Core Web API
- Create
Note (01/13/2023):
Here, it seems one picture is missing. However, we do not have the VS 2019 16.8 any more, the new VS 2019 16.11 layout is different. So, we borrow a similar graph in the same location from Exception Handling (3), In ASP.NET Core MVC with a modification: the RED arrow indicates that we open a ASP.NET Web API, instead of MVC.

#region snippet_GetByCity
[HttpGet("{city}")]
public WeatherForecast Get(string city)
{
if (!string.Equals(city?.TrimEnd(), "Redmond", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException(
$"We don't offer a weather forecast for {city}.", nameof(city));
}
//return GetWeather().First();
return Get().First();
}
#endregion
Run the app, we will have this





Approach 2: UseExceptionHandler
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
//app.UseDeveloperExceptionPage();
app.UseExceptionHandler("/error-local-development");
}
else
{
app.UseExceptionHandler("/error");
}
}
In the preceding code, the middleware is registered with:
- A route of /error-local-development in the Development environment.
- A route of /error in environments that aren't Development that we will discuss later on.
Step 2
- Right click Controllers > add > controller.
- In the Add New Scaffolded Item dialog, select API in the left pane, and
- API Controller - Empty > Add.
- In the Add Controller dialog, Change ErrorController for controller name > Add.
public class ErrorController : ControllerBase
{
[HttpGet]
[Route("/error-local-development")]
public IActionResult ErrorLocalDevelopment(
[FromServices] IWebHostEnvironment webHostEnvironment)
{
if (webHostEnvironment.EnvironmentName != "Development")
{
throw new InvalidOperationException(
"This shouldn't be invoked in non-development environments.");
}
var context = HttpContext.Features.Get<IExceptionHandlerFeature>();
return Problem(
detail: context.Error.StackTrace,
title: context.Error.Message);
}
[HttpGet]
[Route("/error")]
public IActionResult Error() => Problem();
}
The preceding code calls ControllerBase.Problem to create a ProblemDetails response. We will have


B: Exception Handling in Production Environment
- B: Exception Handling in Production Environment for ASP.NET Core Web API
- Approach 1: UseExceptionHandler
- 1: Exception Handler Page
- 2: Exception Handler Lambda
- Approach 2: UseStatusCodePages
- 1: UseStatusCodePages, and with format string, and with Lambda
- 2: UseStatusCodePagesWithRedirects
- 3: UseStatusCodePagesWithReExecute
- Approach 1: UseExceptionHandler
Approach 1: UseExceptionHandler
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
......
}
Run the app, and Trigger an exception the same way as before, and we will get three different outputs from Swagger, Browser and Postman, the below is a demo from Postman:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//app.UseExceptionHandler("/error");
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 500;
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
await context.Response.WriteAsync("ERROR!<br><br>\r\n");
var exceptionHandlerPathFeature =
context.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
await context.Response.WriteAsync(
"File error thrown!<br><br>\r\n");
}
await context.Response.WriteAsync(
"<a href=\"/\">Home</a><br>\r\n");
await context.Response.WriteAsync("</body></html>\r\n");
await context.Response.WriteAsync(new string(' ', 512));
});
});
}
......
}
We got the result from Swagger,

Approach 2: UseStatusCodePages

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseStatusCodePages();
......
}
Run the app, trigger a 404 error, result will be,

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseStatusCodePages("text/plain", "Status code page, status code: {0}");
......
}
Run the app, trigger a 404 error, result will be,

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseStatusCodePages(async context =>
{
context.HttpContext.Response.ContentType = "text/plain";
await context.HttpContext.Response.WriteAsync(
"Status code lambda, status code: " +
context.HttpContext.Response.StatusCode);
});
......
}
Run the app, trigger a 404 error, result will be,

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/MyStatusCode?code={0}");
......
}
Add an Action method in ErrorController,
public string MyStatusCode(int code)
{
return "You got error code " + code;;
}
Run the app, trigger a 404 error, result will be,

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/Home/MyStatusCode2", "?code={0}");
......
}
Run the app, trigger a 404 error, result will be,

Approach 3: Exception Filter
Although Exception filters are useful for trapping exceptions that occur within MVC (Web API) actions, but they're not as flexible as the built-in exception handling middleware, UseExceptionHandler. Microsoft recommend using UseExceptionHandler, unless you need to perform error handling differently based on which MVC or Web API action is chosen.
The contents of the response can be modified from outside of the controller. In ASP.NET 4.x Web API, one way to do this was using the HttpResponseException type. ASP.NET Core doesn't include an equivalent type. Support for HttpResponseException can be added with the following steps:
Step 1
public class HttpResponseException : Exception
{
public int Status { get; set; } = 400;
public object Value { get; set; }
public HttpResponseException(string value)
{
this.Value = value;
}
}
Step 2
public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order { get; } = int.MaxValue - 10;
public void OnActionExecuting(ActionExecutingContext context) { }
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception is HttpResponseException exception)
{
context.Result = new ObjectResult(exception.Value)
{
StatusCode = exception.Status,
};
context.ExceptionHandled = true;
}
}
}
The preceding filter specifies an Order of the maximum integer value minus 10. This allows other filters to run at the end of the pipeline.
services.AddControllers(options => options.Filters.Add(new HttpResponseExceptionFilter()));
Step 4
[TypeFilter(typeof(HttpResponseExceptionFilter))]
[HttpGet]
[Route("/Filter")]
public IActionResult Filter()
{
throw new HttpResponseException("Testing custom exception filter.");
}
Where in Step 3 and 4, the filter could be registered either locally in Step 4, or globally in Step 3.

Summary
- The exception handling patterns for ASP.NET Core MVC module and Web API module are quite similar;
- ASP.NET Core intruduced a Development mode for exception handling for both MVC and Web API modules, and also for other module such as Web App.
- The Major tool is UseExceptionHandler, recommended by Microsoft, instead of Exception Filters.
- Handle errors in ASP.NET Core web APIs --- MS
- Handle errors in ASP.NET Core --- MS
- Error Handling and ExceptionFilter Dependency Injection for ASP.NET Core APIs --- Filter
- Global Exception Handling in ASP.NET Core WEB API --- talkingdotnet.com
- Filters in ASP.NET Core --- MS

theJavoPosted Jun 15, 2021, 2:50 PM
Hi!, great article, thanks!. Only one question, is it possible to customize the statuscode or will always return 400 ?
Pranam BhatPosted May 30, 2021, 6:57 AM
Thank you for sharing 💯