65.9K
CodeProject 正在变化。 阅读更多。
Home

初学者理解 ASP.NET MVC 中过滤器和属性的教程

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (80投票s)

2013 年 4 月 15 日

CPOL

6分钟阅读

viewsIcon

364322

downloadIcon

7973

在本文中,我们将尝试了解如何在 ASP.NET MVC 应用程序中使用自定义过滤器和特性。

引言

在本文中,我们将尝试了解如何在 ASP.NET MVC 应用程序中使用自定义过滤器和特性。自定义过滤器和特性是向 MVC 请求响应管道注入额外处理逻辑的绝佳方式。我们将尝试了解有关这些的所有信息,并通过一个简单的示例应用程序来实际应用它们。

背景

在 ASP.NET MVC 应用程序中,用户的请求首先到达 UrlRoutingModule。此模块解析请求的 URL,然后调用相应的控制器和操作。然后,控制器将呈现适当的视图,并将响应发送给用户。

那么,如果我们想在这个请求-响应生命周期中注入一些额外的处理逻辑怎么办?一些可以编写一次并在多个控制器和/或操作中重复使用的额外逻辑。

ASP.NET MVC 提供了一种方法,通过编写自定义过滤器来做到这一点,这些过滤器可用于在请求-响应生命周期中注入额外的处理逻辑。

什么是特性和过滤器

MVC 提供了一种非常简洁的方式来注入操作和控制器的预处理和后处理逻辑。我们通过用特性装饰操作来放置预处理和后处理逻辑,这些特性将调用实现过滤器逻辑的特性类。

例如,如果我们希望在用户已通过身份验证时执行某个操作,则可以使用 [Authorize] 特性来装饰该操作。这将负责调用实现授权过滤器的特性类,以检查用户是否已授权。

[Authorize]
public ActionResult Index()
{
    return View();
}

因此,实现自定义过滤器的方法是实现实现所需过滤器所需的接口。现在,我们可以用此特性装饰操作,以便在调用我们的过滤器逻辑时执行它。如果我们希望控制器中的所有操作都使用此过滤器,则可以用此特性装饰控制器本身。

使用代码

现在,让我们尝试看一下我们可以实现的过滤器类型,以注入我们的自定义处理逻辑。

过滤器类型

现在,将讨论继续进行,让我们首先讨论可以实现的各种过滤器类型,以注入自定义处理逻辑。

  • 授权过滤器
  • 操作过滤器
  • 结果过滤器
  • 异常过滤器

实现自定义过滤器

现在,让我们尝试实现这些过滤器。我们将仅实现自定义过滤器,并在 ViewBag 集合中放置一个简单的消息。然后,我们将这些过滤器与控制器的一个操作一起使用,并尝试在视图页面上查看我们插入到 ViewBag 集合中的自定义消息。

授权过滤器

此过滤器提供身份验证和授权逻辑。它将在操作执行之前执行。要实现此操作,自定义特性类应实现 IAuthorizationFilter 接口。

public class CustomAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
{
    void IAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)
    {
        filterContext.Controller.ViewBag.OnAuthorization = "IAuthorizationFilter.OnAuthorization filter called";
    }
}

现在,当我们用此特性装饰操作方法时,将调用 OnAuthorize 过滤器方法,并且我们的自定义逻辑将得到执行。

注意: 在上面的代码中,我们创建了一个特性,该特性仅在应用程序执行授权时运行。在我们自己的过滤器方法中,我们不做任何与授权相关的操作。如果我们要做自定义身份验证和授权,那么我们将不得不从 AuthorizeAttribute 类派生此特性并实现自定义授权逻辑。也许我们会另外讨论。目前,当应用程序正在进行授权并且在调用操作方法之前,此过滤器将运行,以便我们可以注入我们的自定义逻辑。

操作过滤器

此过滤器将在操作开始执行之前和之后,以及在操作执行之后被调用。我们可以在此过滤器中放入自定义的预处理和后处理逻辑。

现在,要实现此过滤器,我们需要创建一个自定义过滤器特性类并实现 IActionFilter 过滤器接口。此接口提供了两个方法 OnActionExecuting OnActionExecuted ,它们将分别在操作执行之前和之后调用。

public class CustomActionAttribute : FilterAttribute, IActionFilter
{
    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
    {
        filterContext.Controller.ViewBag.OnActionExecuted = "IActionFilter.OnActionExecuted filter called";
    }

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.Controller.ViewBag.OnActionExecuting = "IActionFilter.OnActionExecuting filter called";
    }
}

结果过滤器

此过滤器将在操作方法的执行结果执行之前和之后执行。如果我们希望对操作的结果进行某些修改,则可以使用此过滤器。

要实现结果过滤器,我们需要创建一个自定义过滤器特性类并实现 IResultFilter 接口。此接口提供了两个方法 OnResultExecuting OnResultExecuted ,它们将分别在操作结果之前和之后调用。

public class CustomResultAttribute : FilterAttribute, IResultFilter
{
    void IResultFilter.OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.Controller.ViewBag.OnResultExecuted = "IResultFilter.OnResultExecuted filter called";
    }

    void IResultFilter.OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.Controller.ViewBag.OnResultExecuting = "IResultFilter.OnResultExecuting filter called";
    }
}

异常过滤器

每当控制器或控制器的操作抛出异常时,都会调用此过滤器。这在我们需要自定义错误日志记录模块时特别有用。

要实现此过滤器,我们需要创建一个自定义过滤器特性类,该类实现 IExceptionFilter。此接口提供了一个名为 OnException 的方法,这是调用异常日志记录模块并重定向到某个错误页面的理想位置。

public class CustomExceptionAttribute : FilterAttribute, IExceptionFilter
{       
    void IExceptionFilter.OnException(ExceptionContext filterContext)
    {
        filterContext.Controller.ViewBag.OnException = "IExceptionFilter.OnException filter called";
    }
}

执行顺序

现在,对于上面所有的过滤器,我们有以下过滤器方法。

  • IAuthorizationFilter.OnAuthorization
  • IActionFilter.OnActionExecuted
  • IActionFilter.OnActionExecuting
  • IResultFilter.OnResultExecuted
  • IResultFilter.OnResultExecuting
  • IExceptionFilter.OnException

现在,假设我们将所有过滤器都附加到单个操作方法上,那么这些过滤器的执行顺序将是什么?在正常(非异常)情况下,这些过滤器将按以下顺序执行。

  1. IAuthorizationFilter.OnAuthorization
  2. IActionFilter.OnActionExecuting
  3. IActionFilter.OnActionExecuted
  4. IResultFilter.OnResultExecuting
  5. IResultFilter.OnResultExecuted

如果发生异常,则将调用 OnException ,而不是调用结果过滤器。

使用自定义过滤器

现在,从我们的应用程序中,我们只需要装饰那些需要自定义过滤器功能的动作。让我们尝试在单个操作方法上执行此操作,如下所示:

public class HomeController : Controller
{   
    [CustomAuthorization]
    [CustomAction]
    [CustomResultAttribute]
    [CustomExceptionAttribute]
    public ActionResult Index()
    {
        //throw new Exception("Dummy Exception");
        ViewBag.Message = "Index Action of Home controller is being called.";
        return View();
    }
}

以及在视图页面上查看这些的代码


当我们尝试运行应用程序时


在运行的应用程序中要注意的重要一点是,ViewBag.OnResultExecuted 为空。原因是 IResultFilter.OnResultExecuted 函数在视图已渲染(即操作结果已完成)时被调用。

注意: 建议在所有过滤器方法上设置断点,然后运行应用程序以了解这些过滤器方法的顺序。此外,取消注释控制器中引发虚拟异常的行也将调用 IExceptionFilter.OnException 过滤器方法。

内置特性

ASP.NET MVC 提供了一些内置的特性类,它们提供了部分样板功能。我们可以创建从这些内置类派生的自定义类,并根据我们的需求提供更专业的行为。让我们尝试查看一些内置特性。

  • AuthorizeAttribute:MVC 框架提供了 AuthorizeAttribute ,有助于指定我们的自定义授权策略。
  • ActionFilterAttribute:这是 IActionFilter IResultFilter 的内置实现。此特性可用作基类,以实现操作和结果过滤器的自定义行为。
  • HandleErrorAttribute:这是 IExceptionFilter 的内置实现,使得实现异常处理策略更加容易。

值得关注的点:

这是一篇面向初学者的入门文章,旨在帮助他们熟悉 ASP.NET MVC 应用程序中的过滤器和特性的概念。我们讨论了自定义过滤器和特性在向 MVC 请求-响应周期注入自定义预处理和/或后处理逻辑方面的作用。希望这篇文章能提供一些信息。

历史

  • 2013 年 4 月 15 日: 第一版
© . All rights reserved.