• .Net 5+MVC+AOP扩展鉴权授权


    1.IActionResult扩展定制
    2.登录功能自定义鉴权授权类
    3.ResourceFilter扩展定制
    4.Filter的多种注册方式
    5.自定义全局鉴权类,让某些控制器或方法不使用该鉴权
    6.鉴权类带参数
    7.自定义三个ActionFitler,分别注册全局/控制器/Action 执行顺序是怎么样的
    8.如果想要控制Filter的执行顺序怎么办?
    9.net自带鉴权授权(推荐,因为在俄罗斯套娃最外层,提前判断鉴权授权)

    1.IActionResult扩展定制

      #region IActionResult扩展
            public JsonResult ToJSON()
            {
                var result = new JsonResult(new
                {
                    Id = 123,
                    Name = "海贝"
                });
    
                result.ContentType = "";
                return result;
    
                //return Json(new
                //{
                //    Id = 123,
                //    Name = "海贝"
                //});
            }
            [CustomAllowAnonymousAttribute]
            public FileResult VerifyCode()
            {
                string code = "";
                Bitmap bitmap = VerifyCodeHelper.CreateVerifyCode(out code);
                base.HttpContext.Session.SetString("CheckCode", code);
                MemoryStream stream = new MemoryStream();
                bitmap.Save(stream, ImageFormat.Gif);
                return File(stream.ToArray(), "image/gif");
            }
    
    
            public string TostingConsole()
            {
                return "";
            }
    
    
            public IActionResult ToNewtonsoftJsonResult()
            {
                return new NewtonsoftJsonResult(new
                {
                    Id = 234,
                    Name = "年轻人不讲武德"
                });
            }
    
            public IActionResult ToXmlResult()
            {
                return new XmlResult("<a href='zhaoxiedu.net'>朝夕官网</a>");
            }
    
            public void ToStringExtension()
            {
                HttpContext.Response.WriteAsync("<a href='zhaoxiedu.net'>朝夕官网</a>");
            }
    
            public StringResult ToStringResult()
            {
                return new StringResult("<a href='zhaoxiedu.net'>朝夕官网</a>");
            }
    
    
            public class NewtonsoftJsonResult : IActionResult
            {
                private object _Data = null;
                public NewtonsoftJsonResult(object data)
                {
                    this._Data = data;
                }
    
                public async Task ExecuteResultAsync(ActionContext context)
                {
                    HttpResponse response = context.HttpContext.Response;
                    response.ContentType = "application/json;charset=utf-8";
                    await response.WriteAsync(Newtonsoft.Json.JsonConvert.SerializeObject(_Data));
                }
            }
    
            public class XmlResult : IActionResult
            {
                private string _Data = null;
                public XmlResult(string data)
                {
                    this._Data = data;
                }
    
                public async Task ExecuteResultAsync(ActionContext context)
                {
                    HttpResponse response = context.HttpContext.Response;
                    response.ContentType = "application/xml;charset=utf-8";
                    await response.WriteAsync(_Data);
                }
            }
    
            public class StringResult : IActionResult
            {
                private string _Data = null;
                public StringResult(string data)
                {
                    this._Data = data;
                }
    
                public async Task ExecuteResultAsync(ActionContext context)
                {
                    HttpResponse response = context.HttpContext.Response;
                    response.ContentType = "text/plain;charset=utf-8";
                    await response.WriteAsync(_Data);
                }
            }
    
            /// <summary>
            /// 自定义扩展
            /// 专门响应成一个Excel文件下载
            /// 1.赋值对应的Content-type
            /// 2.写入文件流到Response
            /// </summary>
            public class ExcelResult : IActionResult //---NPOI
            {
                private object _Data = null;
                public ExcelResult(object data)
                {
                    this._Data = data;
                }
    
                public async Task ExecuteResultAsync(ActionContext context)
                {
                    HttpResponse response = context.HttpContext.Response;
                    response.ContentType = "application/vnd.ms-excel";
                    //1.设置content-Type
                    //2.根据数据生成excel文件
                    //3.把excel文件流写入到response
                    //await response.WriteAsync(_Data);
                }
            }
    
            #endregion
    View Code

    2.鉴权授权(两步走1:自定义类,继承Attribute,2:相关方法注册鉴权类3.可选全局注册鉴权,全局实现AOP)

     1.登录方法

      [HttpPost]
            [CustomAllowAnonymousAttribute]
            public IActionResult Login(string name, string password, string verify)
            {
                string verifyCode = base.HttpContext.Session.GetString("CheckCode");
                if (verifyCode != null && verifyCode.Equals(verify, StringComparison.CurrentCultureIgnoreCase))
                { 
                    #region 这里在工作中的写法是去数据库中去做验证
                    if ("Zhaoxi".Equals(name) && "Zhaoxi".Equals(password))//就认为登录成功了
                    {
                        #region Cookie/Session 自己写   一般使用Sessio为主
                        CurrentUser currentUser = new CurrentUser()
                        {
                            Id = 123,
                            Name = "Zhaoxi",
                            Account = "Administrator",
                            Email = "1030499676",
                            Password = "123456",
                            LoginTime = DateTime.Now
                        }; 
                        //写Session/写Cookies 
                        base.HttpContext.SetCookies("CurrentUser", Newtonsoft.Json.JsonConvert.SerializeObject(currentUser), 30);
    
                        base.HttpContext.Session.SetString("CurrentUser", Newtonsoft.Json.JsonConvert.SerializeObject(currentUser));
                        #endregion
    
                        return base.Redirect("/Fifth/Index");
                    }
                    else
                    {
                        base.ViewBag.Msg = "账号密码错误";
                    }
                    #endregion
    
                }
                else
                {
                    base.ViewBag.Msg = "验证码错误";
                }
                return View();
            }
    View Code

    2.:创建自定义授权类,继承Attribute, IActionFilter 

      public class ActionAuthrizaFilterAttribute : Attribute, IActionFilter
        {
            /// <summary>
            /// 方法执行后
            /// </summary>
            /// <param name="context"></param>
            public void OnActionExecuted(ActionExecutedContext context)
            {
                return;
            }
    
            /// <summary>
            /// 方法执行前
            /// </summary>
            /// <param name="context"></param>
            public void OnActionExecuting(ActionExecutingContext context)
            { 
                //要先判断,当前请求的Action上是否有标记 [CustomAllowAnonymousAttribute]特性
                //如果有继续往后走,如果没有就不需要匿名
                //应该检测两个地方:控制器和Action 
                //判断action 上是否有CustomAllowAnonymousAttribute
                if (!context.ActionDescriptor.FilterDescriptors.Any(item => item.Filter is CustomAllowAnonymousAttribute))
                {
                    return;
                }
    
                //filterContext.ActionDescriptor.IsDefined(typeof(SkipCheckLoginAttribute)
    
                //判断控制器 上是否有CustomAllowAnonymousAttribute
                if (!context.Filters.Any(f => f is CustomAllowAnonymousAttribute))
                {
                    return;//匿名 不检查  
                }
    
                ///获取session
                CurrentUser currentUser = context.HttpContext.GetCurrentUserBySession();
    
                //因为每一次请求来了都要先进入到这儿来,所有,如果有些Action需要避开鉴权;要判断如果标记的是AllowAnonymous,就跳过 
                if (currentUser == null)// 就要拦截
                {
                    if (this.IsAjaxRequest(context.HttpContext.Request))
                    {
                        context.Result = new JsonResult(new
                        {
                            Success = false,
                            Messge = "没有权限"
                        });
                    }
                    context.Result = new RedirectResult("~/fifth/Login");//短路器,只要对context.Result赋值,就不再往后执行
                }
                //继续往后 
            }
    
    
            private bool IsAjaxRequest(HttpRequest request)
            {
                string header = request.Headers["X-Requested-With"];
                return "XMLHttpRequest".Equals(header);
            }
        }
    ActionAuthrizaFilterAttribute

    3.:加在需要做授权的方法上

    4全局注册:鉴权类 对整个系统所有acction都生效 

    5做了全局生效 如果某些方法不需要生效

    1.就自定义空的一个类 继承Attribute

    2.然后在鉴权的类,判断有没有这个类,有就不做鉴权认证

      public class CustomAllowAnonymousAttribute:Attribute
        {
        }
    CustomAllowAnonymousAttribute

    6.鉴权类如果需要带参数

      public class ActionAuthrizaFilterAttribute : Attribute, IActionFilter
        { 
            #region 需要调用其他服务 
          
            //如果需要使用第三方服务:大家切记,要通过依赖注入来完成; 
            private readonly ILogger<ActionAuthrizaFilterAttribute> _ILogger = null;
    
            public ActionAuthrizaFilterAttribute(ILogger<ActionAuthrizaFilterAttribute> logger)
            {
                this._ILogger = logger;
            }
    
            #endregion
             
            //请求来了以后,是要去访问某一个Action;
            //在之前要执行ActionFilter---需要实例化Filter
            //获取当前请求的Controller名称和Action名称,保存起来;
            //权限验证通过以后,就跳转到当前路径下去
    
            private string currentPath = null;
    
            /// <summary>
            /// 方法执行后
            /// </summary>
            /// <param name="context"></param>
            public void OnActionExecuted(ActionExecutedContext context)
            {
                return;
            }
    
            /// <summary>
            /// 方法执行前
            /// </summary>
            /// <param name="context"></param>
            public void OnActionExecuting(ActionExecutingContext context)
            {
    
                Console.WriteLine("开始验证权限。。。。");
    
                //要先判断,当前请求的Action上是否有标记 [CustomAllowAnonymousAttribute]特性
                //如果有继续往后走,如果没有就不需要匿名
                //应该检测两个地方:控制器和Action 
                //判断action 上是否有CustomAllowAnonymousAttribute
    
                //在.NET5中这里获取特性判断,不一样了;在EndpointMetadata获取
                //1.无论是标记在Controller上的自定义特性还是标记在Action上的自定义特性能,在这里都是统一通过context.ActionDescriptor.EndpointMetadata来获取
                if (context.ActionDescriptor.EndpointMetadata.Any(item => item is CustomAllowAnonymousAttribute))
                {
                    return;
                }
    
                ////filterContext.ActionDescriptor.IsDefined(typeof(SkipCheckLoginAttribute)
    
                ////判断控制器 上是否有CustomAllowAnonymousAttribute
                //if (context.Filters.Any(f => f is CustomAllowAnonymousAttribute))
                //{
                //    return;//匿名 不检查  
                //}
    
                ///获取session
                CurrentUser currentUser = context.HttpContext.GetCurrentUserBySession();
    
                //因为每一次请求来了都要先进入到这儿来,所有,如果有些Action需要避开鉴权;要判断如果标记的是AllowAnonymous,就跳过 
                if (currentUser == null)// 就要拦截
                { 
                    _ILogger.LogInformation($"{currentUser?.Name}权限验证通过了。。。");
    
                    if (this.IsAjaxRequest(context.HttpContext.Request))
                    {
                        context.Result = new JsonResult(new
                        {
                            Success = false,
                            Messge = "没有权限"
                        });
                    }
                    context.Result = new RedirectResult("~/fifth/Login");//短路器,只要对context.Result赋值,就不再往后执行
                }
                //继续往后 
            }
    
    
            private bool IsAjaxRequest(HttpRequest request)
            {
                string header = request.Headers["X-Requested-With"];
                return "XMLHttpRequest".Equals(header);
            }
        }
    自定义鉴权类


    7.定义三个ActionFitler,分别注册全局/控制器/Action

    默认执行顺序如何?
    如下:
    1.全局方法执行前
    2.控制器方法执行前
    3.ActionFilter方法执行前
    4. 执行方法
    5.ActionFilter方法执行后
    6.控制器方法执行后
    7.全局方法执行后


    8.如果想要控制Filter的执行顺序怎么办?

    9.net自带鉴权授权(推荐,因为在俄罗斯套娃最外层,提前判断鉴权授权)

    第一步:在在startup.cs中间件里面   添加相关代码

     第二步:在在startup.cs中间件里面   添加鉴权授权相关支持

    第三步:登录成功之后写入用户信息

      [HttpPost]
            [CustomAllowAnonymousAttribute]
            public IActionResult Login(string name, string password, string verify)
            {
                string verifyCode = base.HttpContext.Session.GetString("CheckCode");
                if (verifyCode != null && verifyCode.Equals(verify, StringComparison.CurrentCultureIgnoreCase))
                {
                    #region 这里在工作中的写法是去数据库中去做验证
                    if ("Zhaoxi".Equals(name) && "Zhaoxi".Equals(password))//就认为登录成功了
                    {
                        #region Cookie/Session 自己写   一般使用Sessio为主
                        //CurrentUser currentUser = new CurrentUser()
                        //{
                        //    Id = 123,
                        //    Name = "Zhaoxi",
                        //    Account = "Administrator",
                        //    Email = "1030499676",
                        //    Password = "123456",
                        //    LoginTime = DateTime.Now
                        //};
                        ////写Session/写Cookies 
                        //base.HttpContext.SetCookies("CurrentUser", Newtonsoft.Json.JsonConvert.SerializeObject(currentUser), 30);
    
                        //base.HttpContext.Session.SetString("CurrentUser", Newtonsoft.Json.JsonConvert.SerializeObject(currentUser));
                        #endregion
    
                        #region 鉴权:鉴权,检测有没有登录,登录的是谁,赋值给User
                        //每一个Claim 表示记录当前用户的某一个信息(票证)
    
    
                        //这部分角色有可能是从数据库中查询出来的;---对应当前用户登录的时候,动态查询出的角色信息
                        var rolelist = new List<string>() {
                        
                                "Admin",
                                "Teacher",
                                "Student"
                        };
                         
                        var claims = new List<Claim>()//鉴别你是谁,相关信息
                        {
                            new Claim(ClaimTypes.Role,"Admin"),
                            new Claim(ClaimTypes.Name,name),
                            new Claim("password",password),//可以写入任意数据
                            new Claim("Account","Administrator"),
                            new Claim("role","admin"),
                            new Claim("zhaoxi","zhaoxi")
                        };
    
                        foreach (var role in rolelist)
                        {
                            claims.Add(new Claim(ClaimTypes.Role, role));
                        }
                       
                        //ClaimsPrincipal 用户信息打包,写入到一个身份证中去
                        ClaimsPrincipal userPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Customer")); //针对与当前用户的身份证 
                        //登录//把身份证信息保存到Cookies中
                        HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties
                        {
                            ExpiresUtc = DateTime.UtcNow.AddMinutes(30),//过期时间:30分钟
    
                        }).Wait();//没用await 
    
                        #endregion  
                        var user = HttpContext.User; 
                        return base.Redirect("/Fifth/Index");
                    }
                    else
                    {
                        base.ViewBag.Msg = "账号密码错误";
                    }
                    #endregion
    
                }
                else
                {
                    base.ViewBag.Msg = "验证码错误";
                }
                return View();
            }
    登录代码

    第四步:标记特性,给需要做鉴权的地方acction支持鉴权

     10.多角色授权比较死板

    //这部分角色有可能是从数据库中查询出来的;---对应当前用户登录的时候,
                        //动态查询出的角色信息
                        var rolelist = new List<string>() {
                        
                                "Admin",
                                "Teacher",
                                "Student"
                        };
                         
                        var claims = new List<Claim>()//鉴别你是谁,相关信息
                        {
                            new Claim(ClaimTypes.Role,"Admin"),//角色授权
                            new Claim(ClaimTypes.Name,name),
                            new Claim("password",password),//可以写入任意数据
                            new Claim("Account","Administrator"),
                            new Claim("role","admin"),
                            new Claim("zhaoxi","zhaoxi")
                        };
    
                        foreach (var role in rolelist)
                        {
                            claims.Add(new Claim(ClaimTypes.Role, role));
                        }
    控制器里面的登录方法
      //角色鉴权
            [Authorize(Roles ="Admin")]
            public ViewResult Index01()
            { 
                _Logge.LogInformation("在这里执行了Action");
                return View();
            }
    
            [Authorize(Roles = "Admin,Teacher")]
            public ViewResult Index02()
            {
                _Logge.LogInformation("在这里执行了Action");
                return View();
            }
    
            [Authorize(Roles = "Admin,Teacher,Student")]
            public ViewResult Index03()
            {
                _Logge.LogInformation("在这里执行了Action");
                return View();
            }
    
            [Authorize(Roles = "Admin,Teacher,Student")] //1.标记Authorze 指定角色以逗号分隔:只要是包含登录的时候写入的某一个角色;就通过验证;或者的关系
            [Authorize(Roles = "ABCCC")]//2.如果标记多个特性,且的关系
            public ViewResult Index04()
            {
                _Logge.LogInformation("在这里执行了Action");
                return View();
            }
             
            [Authorize]
            public ViewResult Index05()
            {
                _Logge.LogInformation("在这里执行了Action");
                return View();
            }
    需要鉴权的地方
    //支持角色验证
                services.AddAuthorization(options =>
                {
                    //增加当前角色
                    options.AddPolicy("CustomAuthorizePolicy", policy =>
                    {
                        //这里表示生效的时候,一些验证逻辑
                        policy.RequireRole("Admin,Teacher,Student");
                    });
                });
    startup.cs-ConfigureServices方法

     11.自定义策略认证(推荐)

      public class CustomAuthorizationHandler : AuthorizationHandler<CustomAuthorizationRequirement>
        {
            public CustomAuthorizationHandler()
            {
    
            }
            protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomAuthorizationRequirement requirement)
            { 
                if (requirement.Name == "Policy01")
                {
                    ///策略1的逻辑
                }
    
                if (requirement.Name == "Policy02")
                {
                    ///策略1的逻辑
                }
    
                if (true)
                {
    
                }
    
                //在这里可以自己定义自己的规则
                {
                    //去数据库里面查出所有角色想信息
                    //其实这里可以去数据库里面去做一些查询,然后根据用户的信息,做计算;如果符合就context.Succeed(requirement); 
                    //否则就Task.CompletedTask; 
                }
                //context.User 鉴权成功(登录成功以后),用户的信息; 
                var role = context.User.FindFirst(c => c.Value.Contains("admin"));
                if (role != null)
                {
                    context.Succeed(requirement); //验证通过了
    
                }
                return Task.CompletedTask; //验证不同过
            }
        }
    }
    CustomAuthorizationHandler.cs
      public class CustomAuthorizationRequirement: IAuthorizationRequirement
        {
    
            /// <summary>
            /// 
            /// </summary>
            public CustomAuthorizationRequirement(string policyname)
            {
                this.Name = policyname;
            }
    
            public string Name { get; set; }
        }
    CustomAuthorizationRequirement
     [Authorize(policy: "customPolicy")]
            public ViewResult Index06()
            {
                _Logge.LogInformation("在这里执行了Action");
                return View();
            }
    
            [Authorize(policy: "customPolicy02")]
    
            [Authorize(policy: "customPolicy01")]
            public ViewResult Index07()
            {
                _Logge.LogInformation("在这里执行了Action");
                return View();
            }
    需要验证的地方
      ////支持策略认证
                //services.AddAuthorization(options =>
                //{
                //    options.AddPolicy("customPolicy", polic =>
                //    {
                //        polic.AddRequirements(new CustomAuthorizationRequirement("Policy01"));//指定策略
                //    });
                //});
    
                //services.AddAuthorization(options =>
                //{
                //    options.AddPolicy("customPolicy01", polic =>
                //    {
                //        polic.AddRequirements(new CustomAuthorizationRequirement("Policy02"));
                //    });
                //});
    
    
                //services.AddAuthorization(options =>
                //{
                //    options.AddPolicy("customPolicy02", polic =>
                //    {
                //        polic.AddRequirements(new CustomAuthorizationRequirement("Policy03"));
                //    });
                //});
    
                //在这里标记自定义的授权Hanlder生效
                services.AddSingleton<IAuthorizationHandler, CustomAuthorizationHandler>();
    Startup.cs-Cnfigureservice()

    角色认证+策步骤:
    1.登录时写入角色claimtypes.role
    2.在startup中支持角色认证
    /3.在标记action/控制器的时候增加authorize 参数role,
    4.标记一个,多个role分隔,是或者关系,如果标记多个authorize,roles是且的关系

    自定义步骤
    策略验证;验证的时候自定义策略,再action 控制器使用策略;策略自己定义
    1.定义权限验证的执行类,实现authorizationhandler抽象
    2.在starup注册ioc服务------在action/控制器/全局标记authorize以后,在请求action时,就会先进入到定义的权限验证类中去执行handlerequirementasync
    3.验证方式有很多种; 每一种可以定义一种策略 实现iauthorizationrequirement接口
    4.定义的策略要在验证逻辑中使用;可以当authorizationhandler 的泛型参数;

     12.ResourceFilter做缓存AOP+或者可以把缓存缓存redis

    第一步自定义 缓存类 继承 Attribute

      public class CustomResourceFilterAttribute : Attribute, IResourceFilter
        {
            /// <summary>
            /// 可以把Redis的操作类库给注入进来,保存缓存就保存到Redis中去。。。。
            /// </summary>
    
            public CustomResourceFilterAttribute()
            { 
            
            }
    
            private static Dictionary<string, object> CacheDictionary = new Dictionary<string, object>(); 
           /// <summary>
           /// 在XX资源之前
           /// </summary>
           /// <param name="context"></param>
            public void OnResourceExecuting(ResourceExecutingContext context)
            {
                ///1.先判断缓存中是否有数据
                ///2.如果有数据,就直接拿着数据走了
                ///3.没有就继续往后,就去实例化控制器,去执行Action做计算 
                //缓存:需要一个key;  只要是key不变,拿到的数据就不变;
                //如果做缓存,一般请求路径不变,数据一般不变; 
                string key = context.HttpContext.Request.Path;
                if (CacheDictionary.Any(item=>item.Key==key))
                {
                    context.Result = CacheDictionary[key] as IActionResult;
                }
                //如果没有缓存---就继续往后; 
                Console.WriteLine("CustomResourceFilterAttribute.OnResourceExecuting");
            }
    
            /// <summary>
            /// 在xx资源之后
            /// </summary>
            /// <param name="context"></param>
            public void OnResourceExecuted(ResourceExecutedContext context)
            {
    
                //代码执行到这里,就表示一定完成了逻辑计算;就有结果;
                string key = context.HttpContext.Request.Path;
                CacheDictionary[key] = context.Result;
                Console.WriteLine("CustomResourceFilterAttribute.OnResourceExecuted");
            }
    
        }
    CustomResourceFilterAttribute

    第二步控制器添加特性

       [CustomResourceFilterAttribute]
            public IActionResult Index()
            {
    
                TestServiceException testServiceException = new TestServiceException();
                testServiceException.Show();
    
    
                ViewBag.date = DateTime.Now;
    
                return View();
            }
    controller

    缓存:在第一次请求数据以后,把计算结果保存在内存----

    下一次再来请求的时候,只要是还是要获取之前的数据;就直接取内存数据;不用做计算了;提高性能;
    1.定义一个ResourceFilter 实现IResourceFilter接口
    2.实现方法,标记在action上

    执行顺序:
    1.ResourceFilter---OnResourceExecuting
    2.执行控制器构造函数
    3.执行Action
    4.ResourceFilter---OnResourceExecuted

    13.异常AOP ExceptionFilter  

    第一步:自定义异常类 继承Attribute

    public class CustomExceptionFilterAttribute : Attribute, IExceptionFilter
        {
    
            private readonly IModelMetadataProvider _modelMetadataProvider;
    
            public CustomExceptionFilterAttribute(IModelMetadataProvider modelMetadataProvider)
            {
                _modelMetadataProvider = modelMetadataProvider;
            }
    
            /// <summary>
            /// 当异常发生的时候就触发
            /// </summary>
            /// <param name="context"></param>
            public void OnException(ExceptionContext context)
            {
                //判断异常是否被处理了
                if (!context.ExceptionHandled)
                {
                    if (this.IsAjaxRequest(context.HttpContext.Request))//header看看是不是XMLHttpRequest
                    {
                        context.Result = new JsonResult(new
                        {
                            Result = false,
                            Msg = context.Exception.Message
                        });//中断式---请求到这里结束了,不再继续Action
                    }
                    else
                    {
                        var result = new ViewResult { ViewName = "~/Views/Shared/Error.cshtml" };
                        result.ViewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
                        result.ViewData.Add("Exception", context.Exception);
    
    
    
                        context.Result = result; //断路器---只要对Result赋值--就不继续往后了;
                    }
                    context.ExceptionHandled = true;
                }
            }
            private bool IsAjaxRequest(HttpRequest request)
            {
                string header = request.Headers["X-Requested-With"];
                return "XMLHttpRequest".Equals(header);
            }
        } 
    CustomExceptionFilterAttribute

    第二步:全局注册

       services.AddMvc(option =>
                {
                    //3.全局注册  对当前项目所有Action都生效
                    //option.Filters.Add(new ActionAuthrizaFilterAttribute()); 
                    //option.Filters.Add<ActionAuthrizaFilterAttribute>();//也可以支持以来注入 
                    option.Filters.Add<GlobalActionFilterAttribute>();//全局注册
                    option.Filters.Add<CustomExceptionFilterAttribute>(); //全局异常都可以捕捉
    
                    //option.Filters.Add<Authorize>();
                });
    startup.cs-ConfigureServices()

    第三步:增加异常友好页面

    @*@model ErrorViewModel*@
    @{
        ViewData["Title"] = "Error";
    }
    @{
        ViewData["Title"] = "Error";
        Exception exception = base.ViewData["Exception"] as Exception;
    }
    
    <h1 class="text-danger">Error.</h1>
    <h2 class="text-danger">An error occurred while processing your request.</h2>
    <h1>@exception.Message</h1>
    
    <h3>Development Mode</h3>
    <p>
        Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
    </p>
    <p>
        <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
        It can result in displaying sensitive information from exceptions to end users.
        For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
        and restarting the app.
    </p>
    Error.cshtml

    第四步:有点错误补充不到 增加补充错误措施

         #region 捕捉异常的补充 
                app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");//只要不是200 都能进来
                app.UseExceptionHandler(errorApp =>
                {
                    errorApp.Run(async context =>
                    {
                        context.Response.StatusCode = 200;
                        context.Response.ContentType = "text/html";
                        await context.Response.WriteAsync("<html lang="en"><body>
    ");
                        await context.Response.WriteAsync("ERROR!<br><br>
    ");
                        var exceptionHandlerPathFeature =
                            context.Features.Get<IExceptionHandlerPathFeature>();
    
                        Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
                        Console.WriteLine($"{exceptionHandlerPathFeature?.Error.Message}");
                        Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
    
                        if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
                        {
                            await context.Response.WriteAsync("File error thrown!<br><br>
    ");
                        }
                        await context.Response.WriteAsync("<a href="/">Home</a><br>
    ");
                        await context.Response.WriteAsync("</body></html>
    ");
                        await context.Response.WriteAsync(new string(' ', 512)); // IE padding
                    });
                });
                #endregion
    startup.cs-configure

    T:能正常捕获,F:捕获不了

    14.ResultFilter  结果AOP,呈现结果之前的AOP

    第一步:

      public class CustomoResultFilterAttribute : Attribute, IResultFilter
        {
    
            public void OnResultExecuting(ResultExecutingContext context)
            {
                Console.WriteLine("CustomoResultFilterAttribute.OnResultExecuting");
            }
    
            public void OnResultExecuted(ResultExecutedContext context)
            {
                Console.WriteLine("CustomoResultFilterAttribute.OnResultExecuted");
            }
        }
    
        public class CustomoAsyncResultFilterAttribute : Attribute, IAsyncResultFilter
        {
            public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
            {
                {
                    Console.WriteLine("结果执行前");
                }
                await next.Invoke(); //执行结果
                {
                    Console.WriteLine("结果执行后");
                }
            }
        }
    
        public class CustomoResultFromParentFilterAttribute : ResultFilterAttribute
        {
    
            public override void OnResultExecuted(ResultExecutedContext context)
            {
                base.OnResultExecuted(context);
            }
    
            public override void OnResultExecuting(ResultExecutingContext context)
            {
                base.OnResultExecuting(context);
            }
    
            public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
            {
                return base.OnResultExecutionAsync(context, next);
            }
        }
    CustomoResultFilterAttribute
  • 相关阅读:
    在Linux下OpenCV的下载和编译
    安装GDB-ImageWatch ,在QT中查看图像
    linux下对qt编写的程序进行部署
    GOQTTemplate简单介绍
    寻找激光的交叉点
    基于opencv和QT的摄像头采集代码( GoQTtemplate3持续更新)
    图像处理工程师的要求研究
    如何将QT的pro图标修改的更显著一些
    快速阅读《QT5.9 c++开发指南》2
    小米盒子连接老式电脑显示器(VGA接口)
  • 原文地址:https://www.cnblogs.com/LZXX/p/14659150.html
Copyright © 2020-2023  润新知