Exception handling is very important in programming. On the one hand, it can give user-friendly tips and on the other hand, it is also for program security. In ASP.NET Core, many solutions have been provided for us by default. Here is a summary.
1. Inherit Controller and override OnActionExecuted
When creating a new controller using vs, you will inherit a Controller class by default, override OnActionExecuted, and add exception handling. Under normal circumstances, we will create a new BaseController and let all Controllers inherit the BaseController. code is as follows
public class BaseController : Controller
{
public override void OnActionExecuted(ActionExecutedContext context)
{
var exception = context.Exception;
if (exception != null)
{
context.ExceptionHandled = true;
context.Result = new ContentResult
{
Content = $"BaseController错误 : { exception.Message }"
};
}
base.OnActionExecuted(context);
}
}
The advantage of this processing method is of course that it is simple, but the disadvantage is also obvious. If the cshtml page throws a mistake, it will not be captured at all. Of course, if the project itself is a web api project without a view, this is still possible.
2. Using ActionFilterAttribute
ActionFilterAttribute is a feature that implements IActionFilter and IResultFilter itself, so whether errors are thrown in action or view, they can theoretically be captured. We create a new ExceptionActionFilterAttribute, overwrite OnActionExecuted and OnResultExecuted, and add exception handling. The complete code is as follows.
public class ExceptionActionFilterAttribute:ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
var exception = context.Exception;
if (exception != null)
{
context.ExceptionHandled = true;
context.Result = new ContentResult
{
Content = $"错误 : { exception.Message }"
};
}
base.OnActionExecuted(context);
}
public override void OnResultExecuted(ResultExecutedContext context)
{
var exception = context.Exception;
if (exception != null)
{
context.ExceptionHandled = true;
context.HttpContext.Response.WriteAsync($"错误 : {exception.Message}");
}
base.OnResultExecuted(context);
}
}
There are two ways to use it,
- Label [TypeFilter (typeof (ExceptionActionFilter)] in the controller.
- Inject globally using filter method in Startup.
services.AddControllersWithViews(options =>
{
options.Filters.Add<ExceptionActionFilterAttribute>();
})
3. Using IExceptionFilter
We know that ASP.NET Core provides five types of filters, and IExceptionFilter is one of them. As the name suggests, this is used to handle exceptions. IExceptionFilterAttribute in ASP.NET Core has implemented IExceptionFilter, so we only need to inherit the ExceptionFilterAttribute and rewrite the methods in it. Similarly, a new CustomExceptionFilterAttribute inherits the ExceptionFilterAttribute, overrides OnException, and adds exception handling. The complete code is as follows
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
context.ExceptionHandled = true;
context.HttpContext.Response.WriteAsync($"CustomExceptionFilterAttribute错误:{context.Exception.Message}");
base.OnException(context);
}
}
Note that the ExceptionFilterAttribute also provides the asynchronous method OnExceptionAsync. You only need to override one of these two processing methods. If both are overridden, both methods will be executed once.
There are two ways to use it,
- Label [CustomExceptionFilter] in the controller.
- Inject globally using filter method in Startup.
services.AddControllersWithViews(options =>
{
options.Filters.Add<CustomExceptionFilterAttribute>();
})
4. Using ExceptionHandler
In startup, vs new projects will be added by default
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
The above code basically means: The development environment uses app.UseDeveloperExceptionPage ();. The production environment will jump to the home/error page.
The UseDeveloper ExceptionPage will give specific error messages, including Stack trace, Query, Cookies, and Headers. There are some changes after net core 3.1. If accept: text/html is added to the request header, the html page will be returned. If you don't add it, only an error will be returned.
Note: app. UseDeveloper ExceptionPage (); should be placed at the front.
if (!env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(builder =>
{
builder.Run(async context =>
{
var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
await context.Response.WriteAsync($"error:{exceptionHandlerPathFeature.Error.Message}");
});
});
}
5. Customize Middleare processing
Global processing through middleware.
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await next(context);
}
catch (System.Exception ex)
{
//处理异常
}
}
}