一、使用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代碼。
代碼以下: