1. 程式人生 > >在ASP.NET Core MVC中子類Controller攔截器要先於父類Controller攔截器執行

在ASP.NET Core MVC中子類Controller攔截器要先於父類Controller攔截器執行

ons art bsp 分享 code 執行 configure resp 攔截器

我們知道在ASP.NET Core MVC中Controller上的Filter攔截器是有執行順序的,那麽如果我們在有繼承關系的兩個Controller類上,聲明同一種類型的Filter攔截器,那麽是父Controller類的Filter攔截器先執行呢,還是子Controller類的Filter攔截器先執行呢?

首先我們新建一個ASP.NET Core MVC項目。

然後我們新建四個IActionFilter攔截器:MyActionOneAttribute、MyActionTwoAttribute、MyActionThreeAttribute和MyActionFourAttribute

MyActionOneAttribute攔截器將會全局聲明在ASP.NET Core MVC項目的所有Controller上:

/// <summary>
/// MyActionOneAttribute攔截器將會全局聲明在ASP.NET Core MVC項目的所有Controller上
/// </summary>
public class MyActionOneAttribute : Attribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        
using (var writer = new StreamWriter(context.HttpContext.Response.Body)) { writer.Write("<div>MyAction 1 OnActionExecuted</div></body></html>"); } } public void OnActionExecuting(ActionExecutingContext context) { using (var
writer = new StreamWriter(context.HttpContext.Response.Body)) { context.HttpContext.Response.ContentType = "text/html"; context.HttpContext.Response.StatusCode = 200; writer.Write("<html><head></head><body><div>MyAction 1 OnActionExecuting</div>"); } } }

MyActionTwoAttribute攔截器將會聲明在父Controller類BaseController上:

/// <summary>
/// MyActionTwoAttribute攔截器將會聲明在父Controller類BaseController上
/// </summary>
public class MyActionTwoAttribute : Attribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        using (var writer = new StreamWriter(context.HttpContext.Response.Body))
        {
            writer.Write("<div>MyAction 2 OnActionExecuted</div>");
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        using (var writer = new StreamWriter(context.HttpContext.Response.Body))
        {
            writer.Write("<div>MyAction 2 OnActionExecuting</div>");
        }
    }
}

MyActionThreeAttribute攔截器將會聲明在子Controller類HomeController上:

/// <summary>
/// MyActionThreeAttribute攔截器將會聲明在子Controller類HomeController上
/// </summary>
public class MyActionThreeAttribute : Attribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        using (var writer = new StreamWriter(context.HttpContext.Response.Body))
        {
            writer.Write("<div>MyAction 3 OnActionExecuted</div>");
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        using (var writer = new StreamWriter(context.HttpContext.Response.Body))
        {
            writer.Write("<div>MyAction 3 OnActionExecuting</div>");
        }
    }
}

MyActionFourAttribute攔截器將會聲明在子Controller類HomeController的Index方法上:

/// <summary>
/// MyActionFourAttribute攔截器將會聲明在子Controller類HomeController的Index方法上
/// </summary>
public class MyActionFourAttribute : Attribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        using (var writer = new StreamWriter(context.HttpContext.Response.Body))
        {
            writer.Write("<div>MyAction 4 OnActionExecuted</div>");
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        using (var writer = new StreamWriter(context.HttpContext.Response.Body))
        {
            writer.Write("<div>MyAction 4 OnActionExecuting</div>");
        }
    }
}

然後我們在ASP.NET Core MVC項目中Startup類的ConfigureServices方法中,全局聲明MyActionOneAttribute攔截器到項目的所有Controller上:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(MyActionOneAttribute));
    });
}

然後我們定義父Controller類BaseController,它繼承於Microsoft.AspNetCore.Mvc.Controller,並聲明了MyActionTwoAttribute攔截器:

[MyActionTwo]
public class BaseController : Controller
{

}

然後我們定義子Controller類HomeController,它繼承於BaseController,並在類上聲明了MyActionThreeAttribute攔截器,Action方法Index上聲明了MyActionFourAttribute攔截器:

[MyActionThree]
public class HomeController : BaseController
{
    [MyActionFour]
    public IActionResult Index()
    {
        using (var writer = new StreamWriter(HttpContext.Response.Body))
        {
            writer.Write("<div>Index</div>");
        }

        return new EmptyResult();
    }
}

並且我們在HomeController的Action方法Index中,輸出了一個字符串"<div>Index</div>"。

所以現在我們相當於是在子Controller類HomeController的Index方法上,同時聲明了MyActionOneAttribute、MyActionTwoAttribute、MyActionThreeAttribute和MyActionFourAttribute四個攔截器,那麽這四個攔截器的執行順序是什麽樣的呢?

現在我們運行ASP.NET Core MVC項目,在Web瀏覽器中輸出結果如下:

技術分享圖片

從上圖結果中,我們可以看出:

  • 最先執行的是全局聲明的MyActionOneAttribute攔截器
  • 然後執行的是聲明在子Controller類HomeController上的MyActionThreeAttribute攔截器
  • 接著執行的是聲明在父Controller類BaseController上的MyActionTwoAttribute攔截器
  • 最後執行的是聲明在子Controller類HomeController的Index方法上的MyActionFourAttribute攔截器

所以這個結果證明了聲明在子Controller類上的Filter攔截器,要先與聲明在父Controller類上的Filter攔截器執行!

在ASP.NET Core MVC中子類Controller攔截器要先於父類Controller攔截器執行