.net core 過濾器的介紹及使用


.netcore過濾器有以下幾種類型

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
 
namespace NetCoreApp.Filters
{
    //優先級1:權限過濾器:它在Filter Pipleline中首先運行,並用於決定當前用戶是否有請求權限。如果沒有請求權限直接返回。
    public class MyAuthorization : IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
 
        }
    }
    //優先級2:資源過濾器: 它在Authorzation后面運行,同時在后面的其它過濾器完成后還會執行。Resource filters 實現緩存或其它性能原因返回。因為它運行在模型綁定前,所以這里的操作都會影響模型綁定。
    public class MyResourceFilterAttribute : IResourceFilter
    {
        //這個ResourceFiltersAttribute是最適合做緩存了,在這里做緩存有什么好處?因為這個OnResourceExecuting是在控制器實例化之前運營,如果能再這里獲取ViewReuslt就不必實例化控制器,在走一次視圖了,提升性能
        private static readonly Dictionary<string, object> _Cache = new Dictionary<string, object>();
        private string _cacheKey;
        /// <summary>
        /// 這個方法會在控制器實例化之前之前
        /// </summary>
        /// <param name="context"></param>
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            _cacheKey = context.HttpContext.Request.Path.ToString();//這個是請求地址,它肯定是指向的視圖
            if (_Cache.ContainsKey(_cacheKey))
            {
                var cachedValue = _Cache[_cacheKey] as ViewResult;
                if (cachedValue != null)
                {
                    context.Result = cachedValue;
                }
            }
        }
        /// <summary>
        /// 這個方法是是Action的OnResultExecuted過濾器執行完之后在執行的(每次執行完Action之后得到就是一個ViewResult)
        /// </summary>
        /// <param name="context"></param>
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            _cacheKey = context.HttpContext.Request.Path.ToString();//這個是請求地址
            if (!string.IsNullOrEmpty(_cacheKey) && !_Cache.ContainsKey(_cacheKey))
            {
                //因為這個方法是是Action的OnResultExecuted過濾器執行完之后在執行的,所以context.Result必然有值了,這個值就是Action方法執行后得到的ViewResult
                var result = context.Result as ViewResult;
                if (result != null)
                {
                    _Cache.Add(_cacheKey, result);
                }
            }
        }
    }
    //優先級3:方法過濾器:它會在執行Action方法前后被調用。這個可以在方法中用來處理傳遞參數和處理方法返回結果。
    public class MyActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            //context.HttpContext.Response.WriteAsync("abc");
        }
 
    }
    //優先級4:異常過濾器:被應用全局策略處理未處理的異常發生前異常被寫入響應體
    public class MyExceptionFilterAttribute:ExceptionFilterAttribute
    {
        private readonly IModelMetadataProvider _moprovider;
        public MyExceptionFilterAttribute(IModelMetadataProvider moprovider)
        {
            this._moprovider = moprovider;
        }
        public override void OnException(ExceptionContext context)
        {
            base.OnException(context);
            if (!context.ExceptionHandled)//如果異常沒有被處理過
            {
                string controllerName = (string)context.RouteData.Values["controller"];
                string actionName = (string)context.RouteData.Values["action"];
                //string msgTemplate =string.Format( "在執行controller[{0}的{1}]方法時產生異常",controllerName,actionName);//寫入日志
 
                if (this.IsAjaxRequest(context.HttpContext.Request))
                {
 
                    context.Result = new JsonResult(new
                    {
                        Result = false,
                        PromptMsg = "系統出現異常,請聯系管理員",
                        DebugMessage = context.Exception.Message
                    });
                }
                else
                {
                    var result = new ViewResult { ViewName = "~Views/Shared/Error.cshtml" };
                    result.ViewData = new ViewDataDictionary(_moprovider, context.ModelState);
                    result.ViewData.Add("Execption", context.Exception);
                    context.Result = result;
                }
                    
;            }
        }
        //判斷是否為ajax請求
        private bool IsAjaxRequest(HttpRequest request)
        {
            string header = request.Headers["X-Requested-With"];
            return "XMLHttpRequest".Equals(header);
        }
    }
    //優先級5:結果過濾器:它可以在執行Action結果之前執行,且執行Action成功后執行,使用邏輯必須圍繞view或格式化執行結果。
    public class MyResultFilterAttribute : ResultFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext context)
        {
            base.OnResultExecuting(context);
        }
        public override void OnResultExecuted(ResultExecutedContext context)
        {
            base.OnResultExecuted(context);
        }
    }
}

過濾器的全局注冊

Startup.cs中

namespace NetCoreApp
{
    public class Startup
    {
        public IConfiguration Configuration { get; } //構造函數注入:Configuration用於讀取配置文件的
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
 
        public void ConfigureServices(IServiceCollection services)
        {
            
            services.Configure<CookiePolicyOptions>(options =>
            {
 
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
 
            Action<MvcOptions> filters = new Action<MvcOptions>(r=> {
                r.Filters.Add(typeof(MyAuthorization));
                r.Filters.Add(typeof(MyExceptionFilterAttribute));
                r.Filters.Add(typeof(MyResourceFilterAttribute));
                r.Filters.Add(typeof(MyActionFilterAttribute));
                r.Filters.Add(typeof(MyResultFilterAttribute));
            });
            
 
            services.AddMvc(filters) //注冊全局過濾器
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
 
            services.AddAuthentication();
            services.AddSession();       
        }   
    }
}

局部注冊

我們創建了過濾器,除了注冊這個過濾器為全局過濾器外,還可以在單個控制器,或者單個方法上使用過濾器

以控制器為列,平常我們直接在在控制器上打上我們的創建的過濾器的特性標簽就好了

[MyActionFilter] //在這里打上你自己創建的過濾器名稱就好了
public class HomeController : Controller
{
    private IUser _user { get; set; }
    public HomeController(IUser user)//構造函數
    {
        this._user = user;
    }
    public IActionResult Index()
    {
        ViewBag.Now = DateTime.Now.ToString();
        return View();
    }
}

但是,如果你的過濾器中使用了,構造函數注入對象的形式,直接在控制器上打特性標簽就行不通了。(因為特性需要的參數必須是在這個特性構造前就已經寫好了的,不能依賴注入提供的) 

例如:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    private ILogger<MyActionFilterAttribute> _logger;
    public MyActionFilterAttribute(ILogger<MyActionFilterAttribute> logger)
    {
        this._logger = logger;
    }
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        _logger.LogWarning("在這里執行了Action方法");//記錄日志
    }
}

這時候我們就需要用另外一種形式對我們的過濾器進行注冊了

方式一:使用TypeFilter這種形式,

[TypeFilter(typeof(MyActionFilterAttribute))] 就表示這個MyActionFilterAttribute這個過濾器對象的創建交給DI來完成。

[TypeFilter(typeof(MyActionFilterAttribute))] //這時候需要這樣使用
public class HomeController : Controller
{
    public IActionResult Index()
    {
        ViewBag.Now = DateTime.Now.ToString();
        return View();
    }
}

方式二:使用ServiceFilter這種形式

[ServiceFilter(typeof(MyActionFilterAttribute))]就表示這個MyActionFilterAttribute這個過濾器對象的創建交給DI來完成

但是這種方式需要多一個配置,就是需要在Startup.cs類中的ConfigureServices方法中添加一段配置代碼

services.AddScoped(typeof(MyActionFilterAttribute));

這樣就可以在可控制器中使用ServiceFilter了

[ServiceFilter(typeof(MyActionFilterAttribute))]
public class HomeController : Controller
{    
    public IActionResult Index()
    {
        ViewBag.Now = DateTime.Now.ToString();
        return View();
    }
}

原文地址:https://blog.csdn.net/Fanbin168/article/details/89492788


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM