mvc4中的过滤器
分类:
IT文章
•
2023-11-08 20:29:28
过滤器(Filter)把附加逻辑注入到MVC框架的请求处理。实现了交叉关注。
交叉关注:用于整个应用程序,又不适合放在某个局部位置的功能。
过滤器是.NET的注解属性(Attribute),它们对请求处理管道添加了额外的步骤。
注解属性是派生于System.Attribute的特殊的.NET类。
可以被附加到类、方法、属性、字段等代码元素上。其目的是把附加信息嵌入到已编译的代码中,以便在运行时读回这些信息。
过滤器的基本类型:
过滤器类型
|
接口
|
默认实现
|
描述
|
Authorization
|
IAuthorizationFilter
|
AuthorizationAttribute
|
最先运行
|
Action
|
IActionFilter
|
ActionFilterAttribute
|
在动作方法前后运行
|
Result
|
IResultFilter
|
ActionResultAttribute
|
在动作结果被执行前后
|
Exception
|
IExceptionFilter
|
HandlerErrorAttribute
|
仅在过滤器、动作发生异常时
|
授权过滤器:IAuthorizationFilter
namespace System.Web.Mvc{
// 摘要:定义授权筛选器所需的方法。
public interface IAuthorizationFilter{
// 摘要:在需要授权时调用。
// 参数:filterContext:筛选器上下文。
void OnAuthorization(AuthorizationContext filterContext);
}
}
View Code
注意:
直接实现接口其实是一件非常危险的事;因此创建一个自定义AuthorizeAttribute子类,再实现授权代码比较容易。
public class CustomAuthAttribute:AuthorizeAttribute{
/// <summary>
/// 是否对请求进行授权访问的方式
/// </summary>
/// <param name="httpContext">对请求信息进行访问的方法</param>
protected override bool AuthorizeCore(HttpContextBase httpContext){
return base.AuthorizeCore(httpContext);
}
}
View Code
直接实现IAuthorizationFilter接口的主要原因是为了获取对传递给OnAuthorization()的AuthorizationContext的访问,通过它可以获得更广泛的信息(路由细节、当前控制器和动作方法信息)。使用接口的方式不仅有安全风险且让授权注解属性中建立的逻辑与控制器紧密的耦合在一起,破坏关注分离,不便于维护。
内建的授权过滤器:
虽然使用了AuthorizeAttribute类作为自定义过滤器的基础,但其AuthorizeCore()有自己的实现
当直接使用AuthorizeAttribute时,可以使用它的public属性来指定授权策略
AuthorizeAttribute属性
名称
|
类型
|
描述
|
Users
|
String
|
一个逗号分隔的用户名列表,指定这些用户可以访问动作方法
|
Roles
|
String
|
一个逗号分隔的角色列表,用户必须至少有一个角色
|
public class HomeController : Controller{
[Authorize(Users ="admin,steve,jacqui",Roles ="admin")]
public ActionResult Index(){
return View();
}
}
View Code
异常过滤器:
namespace System.Web.Mvc{
// 摘要:定义异常筛选器所需的方法。
public interface IExceptionFilter{
// 摘要:在发生异常时调用。
// 参数:filterContext:
// 筛选器上下文。
void OnException(ExceptionContext filterContext);
}
}
当一个未处理的异常出现时,OnException()被调用。该方法的参数是一个ExceptionContext 对象,此对象派生于ControllerContext,并提供了许多有用的属性。
名称
|
类型
|
描述
|
Controller
|
ControllerBase
|
返回请求的控制器对象
|
HttpContext
|
HttpContextBase
|
提供对请求细节的访问及对响应的访问
|
IsChildAction
|
Bool
|
若是自动做则返回true
|
RequestContext
|
RequestContext
|
提供对HttpContext和路由数据的访问
|
RouteData
|
RouteData
|
返回请求的路由数据
|
继承自ControllerContext的属性
名称
|
类型
|
描述
|
ActionDescripter
|
ActionDescripter
|
提供动作方法的细节
|
Result
|
ActionResult
|
用于动作方法的结果,通过非空值可取消请求
|
Exception
|
Exception
|
未处理的异常
|
ExceptionHandled
|
Bool
|
如果另一个过滤器已经把这个异常标记为已处理则返回true
|
实现自定义异常过滤器
public class RangeExceptionAttribute : FilterAttribute, IExceptionFilter{
public void OnException(ExceptionContext filterContext){
}
}
使用内建的异常过滤器:
HandleErrorAttribute属性
名称
|
类型
|
描述
|
ExceptionType
|
Type
|
由过滤器处理的异常类型
|
View
|
String
|
该过滤器渲染的视图模板名
|
Master
|
String
|
在渲染这个过滤器的视图时使用的布局名称
|
准备工作:
在web.config文件中启用自定义错误时,HandleErrorAttribute过滤器才会生效,在<system.web>节点中添加一个customErrors属性即可;
<system.web>
<!--定制错误页aa.html-->
<customErrors mode="On" defaultRedirect="/Content/aa.html" />
</system.web>
Mode属性的默认值是RemoteOnly在开发期间,HandleErrorAttribute将不会拦截异常,但当应用程序部署到产品服务器时,并从另一台计算机发出请求时HandleErrorAttribute变生效
[HandleError(ExceptionType =typeof(ArgumentNullException),View ="Null")]
public ActionResult Index(){
return View();
}
在渲染视图时HandleErrorAttribute过滤器会传递一个HandleErrorInfo视图模型对象这是一个封装了异常细节的封装程序
名称
|
类型
|
描述
|
ActionName
|
String
|
返回生成异常的Action名称
|
ControllerName
|
String
|
返回生成异常的Controller名称
|
Exception
|
Exception
|
返回此异常
|
@model HandleErrorInfo
@{
ViewBag.Title = "Sorry";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
</head>
<body>
@Model.Exception.StackTrace
</body>
</html>
View Code
1 namespace System.Web.Mvc{
2
3 // 摘要:定义操作筛选器中使用的方法。
4
5 public interface IActionFilter{
6
7 // 摘要:在执行操作方法后调用。
8
9 // 参数:filterContext:
10
11 // 筛选器上下文。
12
13 void OnActionExecuted(ActionExecutedContext filterContext);
14
15 // 摘要:在执行操作方法之前调用。
16
17 // 参数:filterContext:
18
19 // 筛选器上下文。
20
21 void OnActionExecuting(ActionExecutingContext filterContext);
22
23 }
24
25 }
namespace System.Web.Mvc{
// 摘要:定义结果筛选器所需的方法。
public interface IResultFilter{
// 摘要:在操作结果执行后调用。
// 参数:filterContext:
// 筛选器上下文。
void OnResultExecuted(ResultExecutedContext filterContext);
// 摘要:在操作结果执行之前调用。
// 参数:filterContext:
// 筛选器上下文。
void OnResultExecuting(ResultExecutingContext filterContext);
}
}
动作方法如何返回动作结果,让用户能够将动作方法的意图与动作方法的执行分离。将结果过滤器运用于一个动作方法时会在动作方法返回结果时、但在执行该动作结果之前调用OnResultExecuting。动作结果执行之后调用OnResultExecuted
namespace System.Web.Mvc{
// 摘要:表示筛选器特性的基类。
public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter{
// 摘要:在执行操作方法后由 ASP.NET MVC 框架调用。
// 参数:filterContext:
// 筛选器上下文。
public virtual void OnActionExecuted(ActionExecutedContext filterContext);
// 摘要:在执行操作方法之前由 ASP.NET MVC 框架调用。
// 参数:filterContext:
// 筛选器上下文。
public virtual void OnActionExecuting(ActionExecutingContext filterContext);
// 摘要:在执行操作结果后由 ASP.NET MVC 框架调用。
// 参数:filterContext:
// 筛选器上下文。
public virtual void OnResultExecuted(ResultExecutedContext filterContext);
// 摘要:在执行操作结果之前由 ASP.NET MVC 框架调用。
// 参数:filterContext:
// 筛选器上下文。
public virtual void OnResultExecuting(ResultExecutingContext filterContext);
}
}
public class ProfileAllAttribute: ActionFilterAttribute{
private Stopwatch timer;
public override void OnActionExecuting(ActionExecutingContext filterContext){
timer = Stopwatch.StartNew();
}
public override void OnActionExecuted(ActionExecutedContext filterContext){
timer.Stop();
filterContext.HttpContext.Response.Write(
string.Format("<div>Total elapsed time:{0}</div>", timer.Elapsed.TotalSeconds));
}
}
public class HomeController : Controller{
[ProfileAll]
public ActionResult Index(){ return View();}
}