asp.net core MVC 過濾器之ActionFilter過濾器(二)

bzt820801發表於2017-08-26

本系類將會講解asp.net core MVC中的內建過濾器的使用,將分為以下章節

  asp.net core MVC 過濾器之ExceptionFilter過濾器(一)

  asp.net core MVC 過濾器之ActionFilter過濾器(二)

  asp.net core MVC 過濾器之ResultFilter過濾器(三)

  asp.net core MVC 過濾器之ResourceFilter過濾器(四)

  asp.net core MVC 過濾器之AuthorizationFilter過濾器(五)

簡介

Action過濾器將在controller的Action執行之前和之後執行相應的方法。

實現一個自定義Action過濾器

自定義一個全域性異常過濾器需要實現IActionFilter介面

public class ActionFilter : IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        Console.WriteLine("action執行之後");
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        Console.WriteLine("action執行之前");
    }
}

IActionFilter需要實現兩個方法OnActionExecuted,OnActionExecuting。OnActionExecuting將在Action之前執行,OnActionExecuted在Action之後執行。

知道原理之後我們們就可以利用其特性來簡化我們的程式碼,在MVC中一個重要的概念就時Model驗證,我們定義Model約束,然後在Action中驗證Model是否繫結成功,我們的Action中重複地寫如下程式碼

 

[HttpGet]
public ActionResult Get()
{
    if (!ModelState.IsValid) return BadRequest("引數錯誤!");
}

 這樣重複的程式碼不僅增加程式碼複雜都也不美觀,我們可以在ActionFilter中自動完成

 

public void OnActionExecuting(ActionExecutingContext context)
{
    if (context.ModelState.IsValid) return;

    var modelState = context.ModelState.FirstOrDefault(f => f.Value.Errors.Any());
    string errorMsg = modelState.Value.Errors.First().ErrorMessage;
    throw new AppException(errorMsg);
}

當Model繫結錯誤時,我們丟擲異常資訊,並在上一章節的異常過濾器ExceptionFilter中捕獲,返回錯誤資訊給請求方。

我們也可以利用ActionFilter的特性來記錄Action的執行時間,當Action執行時間過慢時輸出警告日誌

 

public class ActionFilter : IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        var httpContext = context.HttpContext;
        var stopwach = httpContext.Items[Resources.StopwachKey] as Stopwatch;
        stopwach.Stop();
        var time = stopwach.Elapsed;

        if (time.TotalSeconds > 5)
        {
            var factory = context.HttpContext.RequestServices.GetService<ILoggerFactory>();
            var logger = factory.CreateLogger<ActionExecutedContext>();
            logger.LogWarning($"{context.ActionDescriptor.DisplayName}執行耗時:{time.ToString()}");
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        var stopwach = new Stopwatch();
        stopwach.Start();
        context.HttpContext.Items.Add(Resources.StopwachKey, stopwach);
    }
}

上面的程式碼利用使用HttpContext傳遞一個Stopwach來計算action的執行時間,並在超過5秒時輸出警告日誌。

 

註冊全域性過濾器

註冊方法與ExceptionFinter相同。找到系統根目錄Startup.cs檔案,修改ConfigureServices方法如下

 services.AddMvc(options =>
            {
                options.Filters.Add<ActionFilter>();
            });

 

相關文章