Filter的生效范围和执行顺序
1.标记在Action上,就只对当前Action生效
2.标记在Controller上,就对controller上中的所有Action生效
3.全局注册,对于当前整个项目中的Action都生效
startup.cs 中ConfigureServices方法
services.AddMvc(option=>
{
option.Filters.Add<CustomActionFilterAttribute>();//全局注册
});
定义三个ActionFilter,分别注册全局,控制器,Action
执行顺序如下:
1.控制器实例化
2.全局注册的Filter-- OnActionExecuting
3.控制器注册的Filter-OnActionExecuting
4_Actioin注册的Filter-OnActionExecuting
5.执行Action内部的逻辑算计
6.Action注册的Filter-OnActionExeculed
7.控制器注册的Filter-OnActionExecuted
8.全局注册的Filter. OnActionExecuted
执行顺序可以更改。
在注册Filter的时候,指定Order的值, 执行顺序,按照Order的值,从小到大执行;
1.实现接口ActionFilterAttribute
public class CustomGlobalActionFilterAttribute :ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
Console.WriteLine("CustomGlobalActionFilterAttribute.OnActionExecuted");
}
public override void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine("CustomGlobalActionFilterAttribute.OnActionExecuting");
}
}
2.使用Order改变顺序
结果
ResourceFilter
就是为了缓存而存在.
当经过授权验证后,进入ResourceFilter 如果有缓存,就立马返回,不继续执行下去 。没有缓存就一步一步走下去。
练习
1.新建一个ResourceFilter的类,实现IResourceFilter接口
public class CustomResourceFilterAttribute : Attribute, IResourceFilter
{
private static Dictionary<string, object> CacheDictionary = new Dictionary<string, object>();
/// <summary>
/// 在XXX资源之前执行
/// </summary>
/// <param name="context"></param>
public void OnResourceExecuting(ResourceExecutingContext context)
{
//这里就判断是否有缓存,只要是key 不变,缓存就不变
string key = context.HttpContext.Request.Path;
if (CacheDictionary.Any(item=>item.Key==key))
{
//断路器,只要是对Result赋佰,就不继续往后走了
context.Result = CacheDictionary[key] as IActionResult;
}
Console.WriteLine("CustomResourceFilterAttribute.OnResourceExecuting");
}
/// <summary>
/// 在XXX资源之后执行
/// </summary>
/// <param name="context"></param>
public void OnResourceExecuted(ResourceExecutedContext context)
{
//进入此方法就代表,已经完成了业务处理
string key = context.HttpContext.Request.Path;
CacheDictionary[key] = context.Result;
Console.WriteLine("CustomResourceFilterAttribute.OnResourceExecuted");
}
}
2.应用
Filter匿名
如果全局注册,Filter生效于所有的Acion;如果有部分Action不生效,匿名---可以避开Filter的检查;
如何支持自定义的Filter
1.自定义一个特性;
public class CustomAllowAnonymousAttribute:Attribute
{
}
2.在需要匿名的Filter内部,检查是否需要匿名(检查是否标记的有匿名特性) ,如果有就直接避开
public class CustomActionFilterAttribute : Attribute, IActionFilter
{
/// <summary>
/// 方法执行前
/// </summary>
/// <param name="context"></param>
public void OnActionExecuting(ActionExecutedContext context)
{
if (context.ActionDescriptor.EndpointMetadata.Any(item=>item.GetType()
==typeof(CustomAllowAnonymousAttribute)))//如果有标记的有特殊记号,就避开检查
{
return;
}
}
public void OnActionExecuted(ActionExecutingContext context)
{
}
}
3.使用
ExceptionFilter
1.自定义一个CustomExceptionFilterAltribute ,实现lExceptionFilter按口,
public class CustomExceptionFilterAttribute : Attribute, IExceptionFilter
{
private IModelMetadataProvider _modelMetadataProvider = null;
public CustomExceptionFilterAttribute(IModelMetadataProvider modelMetadataProvider)
{
_modelMetadataProvider = modelMetadataProvider;
}
/// <summary>
/// 当异常发生的时候触发到这里处理
/// </summary>
/// <param name="context"></param>
public void OnException(ExceptionContext context)
{
if (!context.ExceptionHandled)//判断异常是否被处理过
{
//在这里处理
//在这里处理如果 是Ajax请求===返回Json .
if (this.IsAjaxReguest(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 IsAjaxReguest(HttpRequest request)
{
string header = request.Headers["X-Requested-With"];
return "XMLHttpRequest".Equals(header);
}
}
2.实现方法,先判断,异常是否被处理过,如果没有被处理过,就处理;
3.分情况处理: 1如果是ajax请求,就返回JosnResult, 如果不是Ajax请求,就返回错误页面
4.全局注册(注册到Action上,只是对action生效)
全局注册--startup.cs 中ConfigureServices方法
services.AddMvc(option =>
{
option.Filters.Add<CustomExceptionFilterAttribute>();//注册全局异常
});
注册到Action上
ExceptionFilter能捕捉到哪些异常
1.控制器实例化异常--------------捕捉的到
2.异常发生在Try-cache中-------捕捉的不到
3.在视图中发生异常--------------捕捉的不到
4.Service层发生异常-------------捕捉的到
5.在action中发生异常------------捕捉的到
6.请求错误路径异常--------------可以使用中间件来支持,只要不是200的状态,就可以