本文转自: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.

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

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

    9.创建自定义异常 Create Custom Exception 马克-to-win:我们可以创建自己的异常:checked或unchecked异常都可以, 规则如前面我们所介绍,反正如果是chec ...

  2. 002.Create a web API with ASP.NET Core MVC and Visual Studio for Windows -- 【在windows上用vs与asp.net core mvc 创建一个 web api 程序】

    Create a web API with ASP.NET Core MVC and Visual Studio for Windows 在windows上用vs与asp.net core mvc 创 ...

  3. 004.Create a web app with ASP.NET Core MVC using Visual Studio on Windows --【在 windows上用VS创建mvc web app】

    Create a web app with ASP.NET Core MVC using Visual Studio on Windows 在 windows上用VS创建mvc web app 201 ...

  4. Global exception handling in asp.net core webapi

    在.NET Core中MVC和WebAPI已经组合在一起,都继承了Controller,但是在处理错误时,就很不一样,MVC返回错误页面给浏览器,WebAPI返回Json或XML,而不是HTML.Us ...

  5. Custom Exception in ASP.NET Web API 2 with Custom HttpResponse Message

    A benefit of using ASP.NET Web API is that it can be consumed by any client with the capability of m ...

  6. [转]How do you create a custom AuthorizeAttribute in ASP.NET Core?

    问: I'm trying to make a custom authorization attribute in ASP.NET Core. In previous versions it was ...

  7. [转]ASP.NET Core Exception Filters and Resource Filters

    本文转自:https://damienbod.com/2015/09/30/asp-net-5-exception-filters-and-resource-filters/ This article ...

  8. Asp.Net Core Filter 深入浅出的那些事-AOP

    一.前言 在分享ASP.NET Core Filter 使用之前,先来谈谈AOP,什么是AOP 呢? AOP全称Aspect Oriented Programming意为面向切面编程,也叫做面向方法编 ...

  9. Filters in ASP.NET Core

    Filters in ASP.NET Core allow code to be run before or after specific stages in the request processi ...

随机推荐

  1. 获取oracle 库所有表名

    (mybatis多参)

  2. UIImageView 动画

    1.UIImageView 动画 1.1 播放图片集 @property (nonatomic, strong) UIImageView *playImageView; self.playImageV ...

  3. 看了这篇Dubbo RPC面试题,让天下没有难面的面试题!

      前言: RPC非常重要,很多人面试的时候都挂在了这个地方!你要是还不懂RPC是什么?他的基本原理是什么?你一定要把下边的内容记起来!好好研究一下!特别是文中给出的一张关于RPC的基本流程图,重点中 ...

  4. 51nod1464(trie + dfs)

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1464 题意: 中文题诶~ 思路: 将所有半回文串构建成一棵字 ...

  5. loj #6342. 跳一跳

    #6342. 跳一跳 题目描述 现有一排方块,依次编号为 1…n1\ldots n1…n.方块 111 上有一个小人,已知当小人在方块 iii 上时,下一秒它会等概率地到方块 iii(即不动),方块  ...

  6. loj #2508. 「AHOI / HNOI2018」游戏

    #2508. 「AHOI / HNOI2018」游戏 题目描述 一次小 G 和小 H 在玩寻宝游戏,有 nnn 个房间排成一列,编号为 1,2,…,n,相邻房间之间都有 111 道门.其中一部分门上有 ...

  7. Python之路迭代器协议、for循环机制、三元运算、列表解析式、生成器

    Python之路迭代器协议.for循环机制.三元运算.列表解析式.生成器 一.迭代器协议 a迭代的含义 迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的 ...

  8. Java实现二维码生成的方法

    1.支持QRcode.ZXing 二维码生成.解析: package com.thinkgem.jeesite.test; import com.google.zxing.BarcodeFormat; ...

  9. Qt 学习之路 2(40):隐式数据共享

    Qt 学习之路 2(40):隐式数据共享 豆子 2013年1月21日 Qt 学习之路 2 14条评论 Qt 中许多 C++ 类使用了隐式数据共享技术,来最大化资源利用率和最小化拷贝时的资源消耗.当作为 ...

  10. 自己写的一个ASP.NET服务器控件Repeater和GridView分页类

    不墨迹,直接上代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; usin ...