• web api 开发之 filter


    web api 开发之 filter

    1、使用filter之前应该知道的(不知道也无所谓,哈哈!)

      谈到filter 不得不先了解下aop(Aspect Oriented Programming)面向切面的编程。(度娘上关于aop一大堆我就不在这废话了)

      下面是个人理解对aop理解(不要板砖): 以前面向过程的编程,某个功能都编写成函数,在需要的时候调用。而面向对象中的编码和设计中,在类中的某个点(或者说是一个横向的切面)去实现一个功能的时候,大家也想实面向过程编码中那样简单的调用(当然不是这么简答,就是打个比方),把实例化类等繁琐的工作交给了系统去做,哈哈aop就出现了! 

      web api 提供两种过滤器的基本类型 :

      1)actionfilterattribute

      2)exceptionfilterattribute

      两个类都是抽象类,actionfilter主要实现执行请求方法体之前(覆盖基类方法OnActionExecuting),和之后的事件处理(覆盖基类方法OnActionExecuted)。 exceptionfilter主要实现触发异常方法(覆盖基类方法OnException)。

        过滤器在实际项目中都是经常会使用到,例如日志、安全验证、全局错误处理等等。 

    2、实际使用中遇到的问题

       1)问题一  filter触发不了

       写了一个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 直接使用 } ........... }
    复制代码


    3、总结一下还有些需要注意

      1)在action执行前终止请求时,应该使用填充方法Response,将不返回action方法体。

    例如:当验证判断不合法时,返回错误信息而不再继续执行action代码。

    代码如下:

      actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, object(返回对象));
    object将会被系统直接按默认方式,序列化。
       
      2)在action,或filter中取得当前路径(物理/其他信息)
        使用 HttpRuntime 对象
     
    web api 的简单例子,网上不少,但是涉及深入开发和实际应用的少之又少,这方面的书籍好像也没有找到,解决问题只能靠msdn,枯燥呀!希望能和大家交流,共同进步。
     
     
     
    分类: .net
  • 相关阅读:
    (五)《Java编程思想》——final关键字
    eclipse与github建立版本关联、git使用说明
    (四)《Java编程思想》——可变参数列表
    (三)《Java编程思想》——构造函数初始化
    (二)《Java编程思想》——t h i s 关键字
    (一)《Java编程思想》学习——按位运算符、移位运算符
    (三)一个工作任务引起的乱战——udp通信
    (二)一个工作任务引起的乱战——C++程序编译为dll,让C#调用
    (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换
    如何反编译silverlight
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3496993.html
Copyright © 2020-2023  润新知