.netcore的AOP讲解( 三)

667 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

前言

今天继续讲解.netcore的AOP,话不多说,我们来看看吧。

ExceptionFilter扩展

包含了IExceptionFilter和IAsyncExceptionFilter的多种实现

开始扩展定制

同步异常的执行特点---如果实现ActionFilterAttribute抽象父类,在执行的时候, 只会执行异步版本的方法---在源码中他是直接判断了,如果有异步版本,同步版本就不执行了

ExceptionFilter封装扩展落地

异常的标准处理方式

分情况返回不同数据

//CustomExceptiionFilter.csusing Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
​
namespace 练习Demo.Unity.Filter
{
    public class CustomExceptiionFilter : Attribute, IExceptionFilter
    {
​
        private readonly IModelMetadataProvider _ModelMetadataProvider;
        public CustomExceptiionFilter(IModelMetadataProvider ModelMetadataProvider)
        {
            this._ModelMetadataProvider = ModelMetadataProvider;
        }
        public void OnException(ExceptionContext context)
        {
            //这里进行异常处理或者将响应结果给客户端
            //给客户端有两种形式
            //1.页面展示
            //2.包装成JSON格式
​
            if (IsAjaxRequest(context.HttpContext.Request))  //判断是否为Ajax请求,
            {
                context.Result = new JsonResult(
                    new
                    {
                        Success = false,
                        Message = context.Exception.Message,
                    }
               );
​
            }
            else
            {
                ViewResult result = new ViewResult { ViewName = "/Views/Shared/Error.cshtml" };
​
                result.ViewData = new ViewDataDictionary(_ModelMetadataProvider, context.ModelState);
​
                result.ViewData.Add("Excption",context.Exception);
                context.Result = result;  //断路器  --只要给context.Result赋值了,就不会往后执行了
​
            }
        }
​
​
​
        private bool IsAjaxRequest(HttpRequest request)
        {
            string header = request.Headers["X-Requested-With"];
            return "XMLHttpRequest".Equals(header);
        }
    }
}
​
​
​
//ExcepitonFController.csusing Microsoft.AspNetCore.Mvc;
using 练习Demo.Unity.Filter;
​
namespace 练习Demo.Controllers
{
    public class ExcepitonFController : Controller
    {
        [TypeFilter(typeof(CustomExceptiionFilter))]
        public IActionResult Index()
        {
            throw new Exception("抛出异常");
        }
    }
}
​
​
​
//Error.cshtml
​
@model ErrorViewModel
@{
   
    Exception exception = ViewData["Excption"] as Exception;
}
​
<h1 class="text-danger">Error.</h1>
@if(exception != null)
{
<h1 class="text-danger">@exception.Message</h1>    
}
<h2 class="text-danger">An error occurred while processing your request.</h2>
<h2>大家好</h2>
​

异常处理的场景分析

Action出现没有处理的异常

Action出现已经处理的异常

Service层的异常

View绑定时出现了异常

不存在的Url地址

其他Filter中发生的异常

比如: ActionFilter发生异常可以捕捉到

Resource、 ResultFilter捕捉不到

控制器构造函数出现异常

ExceptionFilter未捕捉到的异常处理

中间件支持

//program.cs
//如果HTTp请求中的Response中的状态不是200,就会进入Home/Error中
app.UseStateCodePagesWithReExcute("/Home/Error/{0}")
​
    
    
//下面拼装一个Response输出
 app.UseExceptionHandler(erroAPP=>{
     。
 })
​

综合支持可以捕捉到所有的异常

ExceptionFilter+中间件==处理所有的异常

鉴权授权

授权背景介绍

Http协议无状态Cookies+Session授权基本配置

ASP.NETCore传统授权的基本配置

使用中间件

配置授权过程

授权生效

代码:

//program.cs
  
//授权配置
builder.Services.AddAuthentication(option =>
{
    option.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    option.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    option.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    option.DefaultForbidScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    option.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,option =>
{
    option.LoginPath = "/userloginAuten/login";   //如果没有获取到用户信息,鉴权失败,授权自然也失败,跳转到指定的Action
});
​
​
//使用中间件
app.UseAuthorization();  //鉴权
app.UseAuthorization();   //授权
​
​
​
​
//UserloginAutenController.cs
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
​
namespace 练习Demo.Controllers
{
    public class UserloginAutenController : Controller
    {
        [Authorize]
        public IActionResult Index()
        {
            return View();
        }
​
​
​
        public IActionResult Login()
        {
            return View();
        }
​
​
        [HttpPost]
        public async Task<IActionResult> login(string name, string password)
        {
​
            var claims = new List<Claim>()
                    {    new Claim("useid","1"),
                        new Claim(ClaimTypes.Role, "Admin"),
                        new Claim(ClaimTypes.Role, "User"),
                    };
​
            ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Customer"));
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal, new AuthenticationProperties
            {
                ExpiresUtc = DateTime.UtcNow.AddMinutes(60)
            });
​
            var user = HttpContext.User;
            return base.Redirect("/userloginAuten/Index");
​
​
        }
​
    }
}
​
​
//login.cshtml
​
​
    @*
    For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
}
​
<h2>登录</h2>
@*<section>*@
   @* @using (Html.BeginForm("login","userloginAuten",new {sid="123",Accout="111"},
     FormMethod.Post,true,new {@class="form-horizontal",role="form"}
    ))
​
    {
        @Html.AntiForgeryToken()
        <hr/>
        @Html
        ValidationSummary(true);
​
        <div>
             @Html.LabelFor(m=>m.Name, new {@class = "col-sm-1"})
            <div>
                 @Html.TextBoxFor(m=>m.Name, new {@class = "form-control",@placeholder="请输入用户名"})
            </div>
​
        </div>
​
         <div>
             @Html.LabelFor(m=>m.Password, new {@class = "col-sm-1"})
            <div>
                 @Html.TextBoxFor(m=>m.Password, new {@class = "form-control",@placeholder="请输入密码"})
            </div>   
        </div>
​
​
        <div><button type="submit">登录</button></div>
        @base.ViewBag.msg
​
​
    }
​
​
</section>*@

总结:还是那句话,一步步来,加油!