一、使用filter以前应该知道的(不知道也无所谓,哈哈!)web
谈到filter 不得不先了解下aop(Aspect Oriented Programming)面向切面的编程。(度娘上关于aop一大堆我就不在这废话了)编程
下面是我的理解对aop理解(不要板砖): 之前面向过程的编程,某个功能都编写成函数,在须要的时候调用。而面向对象中的编码和设计中,在类中的某个点(或者说是一个横向的切面)去实现一个功能的时候,你们也想实面向过程编码中那样简单的调用(固然不是这么简答,就是打个比方),把实例化类等繁琐的工做交给了系统去作,哈哈aop就出现了! api
web api 提供两种过滤器的基本类型 :安全
1)actionfilterattributemvc
2)exceptionfilterattributeasync
两个类都是抽象类,actionfilter主要实现执行请求方法体以前(覆盖基类方法OnActionExecuting),和以后的事件处理(覆盖基类方法OnActionExecuted)。 exceptionfilter主要实现触发异常方法(覆盖基类方法OnException)。ide
过滤器在实际项目中都是常常会使用到,例如日志、安全验证、全局错误处理等等。 函数
二、实际使用中遇到的问题编码
1)问题一 filter触发不了spa
写了一个filter的例子,继承actionfilterattribute,死活触发不了!呵呵,搞了半天后来才搞明白,filter 继承了mvc4的。
原来webapi 在system.web.http命名空间下,mvc在System.web.mvc下,两个空间都有filter,不知道怎么搞得,继承mvc的了,呵呵!
2)问题二 在action执行前取数据,若是有二个filter,第二个取不到请求消息体数据
需求是这 样的要写二个过滤器,都应用在同一个方法上,第一个取请求http消息体正常,可是第二个再取就是空了?
action
[FilterAttribute1] [FilterAttribute2] public MessageResponse Post(MessageRequest messagerequest) { //方法体信息 ................ }
filter
//处理功能1 public class FilterAttribute1 : ActionFilterAttribute { public async override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) { base.OnActionExecuting(actionContext); //获取请求消息提数据 Stream stream = await actionContext.Request.Content.ReadAsStreamAsync(); Encoding encoding = Encoding.UTF8; stream.Position = 0; string responseData = ""; using (StreamReader reader = new StreamReader(stream, encoding)) { responseData = reader.ReadToEnd().ToString(); } //而后反序列化进行处理 .................. } public async override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { base.OnActionExecuted(actionExecutedContext); //获取返回消息数据 var response = await actionExecutedContext.Response.Content.ReadAsAsync( actionExecutedContext.ActionContext.ActionDescriptor.ReturnType); } } //处理功能2 public class FilterAttribute2 : ActionFilterAttribute { public async override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) { base.OnActionExecuting(actionContext); //获取请求消息提数据 Stream stream = await actionContext.Request.Content.ReadAsStreamAsync();
//在这stream值是空的。 Encoding encoding = Encoding.UTF8; stream.Position = 0; string responseData = ""; using (StreamReader reader = new StreamReader(stream, encoding)) { responseData = reader.ReadToEnd().ToString(); } //而后反序列化进行处理
.................. } }
始终没有想没那个白,为何第二个filter取不到?请教前辈有的说当第一个stream 取完,流关闭了,因此取不到,有的说第一个取后,加锁了.....等等,到如今我仍是没有搞明白究竟是为何,还好找到解决方法,代码总算是能够王下写。换了一种思路,从actionContext中找到了取得输入参数的方法,正好是所须要的请求消息数据。实现以下
//修改后,后边filter数据照常取出,问题解决 public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) { base.OnActionExecuting(actionContext); string responsemessagebody = ""; Dictionary<string, object> actionargument = actionContext.ActionArguments;
foreach (KeyValuePair<string, object> arg in actionargument ) {
//天天action的消息体不一样能够tostring,而后处理 responsemessagebody += arg.ToString();
//请求消息体相同
能够直接使用
(typeobject)arg 直接使用 } ........... }
三、总结一下还有些须要注意
1)在action执行前终止请求时,应该使用填充方法Response,将不返回action方法体。
例如:当验证判断不合法时,返回错误信息而再也不继续执行action代码。
代码以下: