[转]Create Custom Exception Filter in ASP.NET Core

本文转自:http://www.binaryintellect.net/articles/5df6e275-1148-45a1-a8b3-0ba2c7c9cea1.aspx

In my previous article I explained how errors in an ASP.NET Core web application can be dealt with  using middleware. I also mentioned that time that you can also use exception  filters to handle errors. In this article I will explain how to do just that.

In ASP.NET MVC 5 you used the [HandleError] attribute and OnException()  controller method to deal with exceptions that arise in the actions of a  controller. In ASP.NET Core the process is bit different but the overall concept  is still the same. As you are probable aware of, filters sit in the ASP.NET Core  pipeline and allow you to execute a piece of code before or after an action  execution. To understand how errors can be handled in ASP.NET Core let‘s create  an exception filter called HandleException and then try to mimic the behavior of  [HandleError] of ASP.NET MVC 5.

Begin by creating a new ASP.NET web application. Then add a class to it named  HandleExceptionAttribute. This class needs to inherit from  ExceptionFilterAttribute base class. The complete code of this class is shown  below:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
....
....

public class HandleExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
      var result = new ViewResult { ViewName = "Error" };
      var modelMetadata = new EmptyModelMetadataProvider();
      result.ViewData = new ViewDataDictionary(
              modelMetadata, context.ModelState);
      result.ViewData.Add("HandleException",
              context.Exception);
      context.Result = result;
      context.ExceptionHandled = true;
    }
 }
}

The HandleExceptionAttribute class overrides the OnException() method of t he  base class. The OnException() method is called only when there is an unhandled  exception in an action. Inside, we create a ViewResult object that represents  the custom error page. It is assumed that the view representing the custom error  page is Error.cshtml. Later we will write some code to remove this hard-coding.

Then the code creates an empty object of EmptyModelMetadataProvider class.  This is required because we need to initialize the ViewData of the request and  add exception details in it. Then ViewData property of the ViewResult is  assigned to a new ViewDataDictionary object. While creating the  ViewDataDictionary the IModelMetadataProvider object created earlier is passed  to the constructor along with the context‘s ModelState.

We would like to store the exception details into the ViewData so that the  Error view can retrieve them and possibly display on the page. To facilitate  this HandleException key is added to the ViewData. The exception being thrown  can be obtained using context‘s Exception property.

Then Result property of context is set to the ViewResult we just configured.  Finally, ExceptionHandled property is set to true to indicate that the exception  need not be bubbled up any further.

Now open the HomeController and decorate the Index() action with the [HandleException]  attribute.

[HandleException]
public IActionResult Index()
{
    throw new Exception("This is some exception!!!");
    return View();
}

Also add Error.cshtml in Shared folder and write the following code to it:

@{
    Exception ex = ViewData["HandleException"] as Exception;
}

<h1>@ex.Message</h1>

<div>@ex.StackTrace</div>

As you can see the Error view can grab the exception details using the  HandleException key stored in the ViewData. The Message and StackTrace  properties of the Exception are then outputted on the page.

If you run the application you should see the error page like this:

So far so good. Now let‘s add a couple of features to our [HandleException]  attribute:

  • The ViewName should be customizable
  • There should be provision to handle only specific type of exceptions

Go ahead and add two public properties to the HandleExceptionAttribute class.  These properties are shown below:

public class HandleExceptionAttribute : ExceptionFilterAttribute
{

    public string ViewName { get; set; } = "Error";
    public Type ExceptionType { get; set; } = null;
    ....
    ....
}

The ViewName property allows you to specify a custom view name that is then  used while forming the ViewResult. The ExceptionType property holds the Type of  the exception you wish to handle (say DivideByZeroException or FormatException).

Then modify the OnException() as shown below:

 public override void OnException(ExceptionContext context)
{
  if(this.ExceptionType != null)
  {
    if(context.Exception.GetType() == this.ExceptionType)
    {
      ....
      ....
    }
  }
  else
  {
    ....
    ....
  }
}

The OnException() method now checks whether a specific ExceptionType is to be  handled (non null value). If yes then it checks whether the exception being  thrown matches with that type (inner if block) and accordingly ViewResult is  configured. If no specific ExceptionType is to be checked then control directly  goes in the else block. The code in both the cases is shown below:

var result = new ViewResult { ViewName = this.ViewName };
var modelMetadata = new EmptyModelMetadataProvider();
result.ViewData = new ViewDataDictionary
(modelMetadata, context.ModelState);
result.ViewData.Add("HandleException", context.Exception);
context.Result = result;
context.ExceptionHandled = true;

This code is quite similar to what you wrote earlier. But this time it uses  the ViewName property while forming the ViewResult.

Now open the HomeController and change the [HandleException] attribute like  this:

[HandleException(ViewName ="CustomError",
ExceptionType =typeof(DivideByZeroException))]
public IActionResult Index()
{
    throw new Exception("This is some exception!!!");
    return View();
}

Now the [HandleException] attribute specifies two properties - ViewName and  ExceptionType. Since ExceptionType is set to the type of DivideByZeroException  the [HandleException] won‘t handle the error (because Index() throws a custom  Exception). So, rename Error.cshtml to CustomError.cshtml and throw a  DivideByZeroException. This time error gets trapped as expected.

It should be noted that [HandleException] can be applied on top of the  controller class itself rather than to individual actions.

[HandleException]
public class HomeController : Controller
{
....
....
}

More details about the ASP.NET Core filters can be found here.

That‘s it for now! Keep coding!!

Bipin Joshi is a software consultant, trainer, author and a yogi having 21+ years of experience in software development. He conducts online courses in ASP.NET MVC / Core, jQuery, AngularJS, and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced Yoga way of life he also teaches Ajapa Meditation to interested individuals. To know more about him click here.

时间: 2024-10-15 04:19:17

[转]Create Custom Exception Filter in ASP.NET Core的相关文章

java中如何创建自定义异常Create Custom Exception

9.创建自定义异常 Create Custom Exception  (视频下载) (全部书籍) 马克-to-win:我们可以创建自己的异常:checked或unchecked异常都可以, 规则如前面我们所介绍,反正如果是checked异常,则必须或者throws,或者catch.到底哪个好,各路架构师大神的意见是50对50.见我本章后面的附录.sun公司开始说,checked异常可以使你的系统异常语义表达很清楚.但很多人经过一段时间的实践后,马上表示了异议.checked异常是java独有的,

如何利用Serilog的RequestLogging来精简ASP.NET Core的日志输出

这是该系列的第一篇文章:在ASP.NET Core 3.0中使用Serilog.AspNetCore. 第1部分-使用Serilog RequestLogging来简化ASP.NET Core的日志输出(本篇文章) 第2部分-使用Serilog记录所选的端点名称[敬请期待] 第3部分-使用Serilog.AspNetCore记录MVC属性[敬请期待] 作者:依乐祝 译文地址:https://www.cnblogs.com/yilezhu/p/12215934.html 原文地址:https://

Using MongoDB with Web API and ASP.NET Core

MongoDB is a NoSQL document-oriented database that allows you to define JSON based documents which are schema independent. The schema can be mapped with Tables in a Relational Database. A schema in MongoDB is called as collection, and a record in thi

.net mvc Authorization Filter,Exception Filter与Action Filter

一:知识点部分 权限是做网页经常要涉及到的一个知识点,在使用MVC做权限设计时需要先了解以下知识: MVC中Url的执行是按照Controller->Action->View页面,但是我们经常需要在函数执行所指定的Action之前或者action方法之后处理一些逻辑,为了处理这些逻辑,ASP.NET MVC允许你创建action过滤器Filter,我们都知道在Action上使用的每一个 [Attribute]大都是自定义的Filter. mvc提供四种类型的Filter接口:IActionFi

Exception Handling in ASP.NET Web API webapi异常处理

原文:http://www.asp.net/web-api/overview/error-handling/exception-handling This article describes error and exception handling in ASP.NET Web API. HttpResponseException Exception Filters Registering Exception Filters HttpError HttpResponseException Wha

[转]Writing Custom Middleware in ASP.NET Core 1.0

本文转自:https://www.exceptionnotfound.net/writing-custom-middleware-in-asp-net-core-1-0/ One of the new features from ASP.NET Core 1.0 is the idea of Middleware. Middleware are components of an application that examine the requests responses coming in t

[转]How to Create Custom Filters in AngularJs

本文转自:http://www.codeproject.com/Tips/829025/How-to-Create-Custom-Filters-in-AngularJs Introduction Filter in Angular JS is a way that will help you to represent your data in View in a certain format. There are many inbuilt filters provided by Angular

在ASP.NET Core使用Middleware模拟Custom Error Page功能

一.使用场景 在传统的ASP.NET MVC中,我们可以使用HandleErrorAttribute特性来具体指定如何处理Action抛出的异常.只要某个Action设置了HandleErrorAttribute特性,那么默认的,当这个Action抛出了异常时MVC将会显示Error视图,该视图位于~/Views/Shared目录下. 自定义错误页面的目的,就是为了能让程序在出现错误/异常的时候,能够有较好的显示体验.有时候在Error视图中也会发生错误,这时ASP.NET/MVC将会显示其默认

asp.net core系列 68 Filter管道过滤器

一.概述 本篇详细了解一下asp.net core filters,filter叫"筛选器"也叫"过滤器",是请求处理管道中的特定阶段之前或之后运行代码.filter用于处理横切关注点. 横切关注点的示例包括:错误处理.缓存.配置.授权和日志记录. filter可以避免重复代码,通过Attribute特性来实现filter过滤.Filter适应于 Razor Pages,  API controllers,  mvc controllers.filter基类是IFi