# 5个过滤器
1、AuthorizationFilter:鉴权授权
2、ResourceFilter:资源
3、ExceptionFilter:异常
4、ActionFilter:方法
5、ResultFilter:结果
# 过滤器执行顺序
# 过滤器多种扩展方式
- 通过实现IActionFilter接口来完扩展。
public class SyloneActionFilterAttribute:Attribute,IActionFilter
- 通过继承ActionFilterAttribute(系统提供的实现)。
public class SyloneActionFilterAttribute:ActionFilterAttribute
- 异步版本的实现,通过实现IAsyncActionFilter接口来实现。
public class SyloneActionFilterAttribute:Attribute,IAsyncActionFilter
# 过滤器多种注入
- 过滤器的特性可以定义在全局配置中,Filter必须是无参数构造函数,或者构造函数注入。
options.Filters.Add<GlobalExceptionFilter>();
- 过滤器的特性可以定义在Action、Controller中
[CustomActionFilter]
Filter必须是无参数构造函数。[TypeFilter(typeof(MyFilterAttribute))]
可以有参数构造函数,可以支持依赖注入。[ServiceFilter(typeof(MyFilterAttribute))]
可以有参数构造函数,可以支持依赖注入。但是如果要使用这个,必须在【Startup.cs】中注册服务。
注册服务时若过滤器中使用的属性注入则必须使用第三方注入。builder.RegisterType(typeof(MyFilterAttribute)).PropertiesAutowired()
# ResourceFilter扩展定制做缓存
自定义一个特性类,继承Attribute,实现接口IResourceFilter,实现接口中的方法。
# ReusltFilter应用-开发双语言系统功能
双语言系统其实就需要两个视图,要根据语言的不同,来选择不同的视图;因为在渲染视图之前,会进入到OnResultExecuting方法,就可以在这个方法中确定究竟使用哪一个视图文件。
# ExceptionFilter异常处理
- 实现方法,先判断,异常是都被处理过,如果没有被处理过,就处理。
- 分情况处理:1.如果是ajax请求,就返回JsonReulst,如果不是Ajax,就返回错误页面。
public class CustomExceptionAttribute : Attribute, IExceptionFilter
{
private readonly IModelMetadataProvider _modelMetadataProvider = null;
/// <summary>
/// 依赖注入:Model元数据的驱动
/// </summary>
public CustomExceptionAttribute(
IModelMetadataProvider modelMetadataProvider
) {
_modelMetadataProvider = modelMetadataProvider;
}
/// <summary>
/// 当异常发生的时候出发到这里来
/// </summary>
/// <param name="context"></param>
public void OnException(ExceptionContext context)
{
//判断异常有没有被处理过
if (context.ExceptionHandled == false) {
//没有处理过,在这里开始处理
//如果是Ajax请求(看看Header是不是XMLHttpRequest)
if (this.IsAjaxRequest(context.HttpContext.Request))
{
//中断式:如果对Result赋值,请求到这里结束了,不在继续Action
context.Result = new JsonResult(new
{
Result = false,
Msg = context.Exception.Message
});
}
else {
//跳转到异常页面
var result = new ViewResult { ViewName = "~/Views/Errors.cshtml" };
result.ViewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
result.ViewData.Add("Exception", context.Exception);
result.ViewData.Add("ErrDate", DateTime.Now);
//中断式:如果对Result赋值,请求到这里结束了,不在继续Action
context.Result = result;
}
context.ExceptionHandled = true;//指定异常已经被处理了
}
}
/// <summary>
/// 判断是不是Ajax请求
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private bool IsAjaxRequest(HttpRequest request)
{
string header = request.Headers["X-Requested-With"];
return "XMLHttpRequest".Equals(header);
}
}
注册到Action上,只对Action生效
一般不会注册到Action上,一般会注册到全局(在【Startup.cs】中创建的【ConfigureServices】方法中进行全局注册)。
# ExceptionFilter-异常捕捉覆盖
- 控制器实例化异常——能。
- 异常发生在Try-cache中——不能,因为异常已经被捕捉到了。
- 在视图中发生异常——不能。
- 在Service层(业务逻辑层)中发生异常——能。
- 在Action中发生异常——能。
- 请求错误路径异常——不能(但是可以通过中间件解决)。
在【Startup.cs】中创建的【Configure】方法中进行使用,只要状态不是200,就可以处理
//只要不是200,都能进来
app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");
app.UseExceptionHandler(errorApp => {
errorApp.Run(async context =>
{
context.Response.StatusCode = 200;
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
await context.Response.WriteAsync("Error!!!<br><br>\r\n");
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>\r\n");
}
await context.Response.WriteAsync("<a href=\"/\">Home</a><br>\r\n");
await context.Response.WriteAsync($"<p>{ exceptionHandlerPathFeature?.Error.Message}</p><br>\r\n");
await context.Response.WriteAsync("</body></html>\r\n");
await context.Response.WriteAsync(new string(' ', 512));//IE padding
});
});
# 避开Filter的检查
如果全局注册,Filter生效于所有的Action,如果有部分Action我希望你不生效,可以避开Filter的检查
- [AllowAnonymous] 跳过登录验证
- [IgnoreAntiforgeryToken] 跳过防范anti攻击
- 自定义的匿名Filter
自定义一个特性类,继承Attribute
需要在需要匿名的Filter内部,检查是否需要匿名(检查是否标记的有匿名特)如果有就避开
使用Action