zoukankan      html  css  js  c++  java
  • Web API Request Content多次读取问题

    如题:

    .net webapi 采用了Owin的验证机制,另外在Action层之外设置了两次验证

    第一次是重写了AuthorizeAttribute,用来验证身份的类,类名为ProtalApiAuth【这个是直接作用于action的,如下图】

    第二次是重写了ActionFilterAttribute, 在OnActionExecuting和OnActionExecuted的时候分别记录webapi请求和返回的内容 ,类名为:AppRequestActionFilter 【这个是注册到全局的,见图3】

     

    前两层具体读取body的代码

    //读取请求的内容流
    var task = context.Request.Content.ReadAsStreamAsync();
    string content = "";
    using (System.IO.Stream sm = task.Result)
                    {
                        if (sm != null)
                        {
                            sm.Seek(0, SeekOrigin.Begin);
                            int len = (int)sm.Length;
                            byte[] inputByts = new byte[len];
                            sm.Read(inputByts, 0, len);
                            sm.Close();
                            content = Encoding.UTF8.GetString(inputByts);
                        }
                    }
    View Code

    以上这两步操作完之后,才到了action这里,背景交代完毕。

    遇到的问题是:

      第一层和第二层都需要解析body值,做一些操作,但是在解析完之后,走到ActionFilterAttribute的时候就拿不到body了,提示为null,百度了很久前辈很多都说是因为引用了owin导致流只能读取一次。而且我发现个问题,如果不写AuthorizeAttribute,把逻辑都放到ActionFilterAttribute里面实现的话,ActionFilterAttribute和Action里都还是可以拿到body的。只要加入了AuthorizeAttribute,那么在ActionFilterAttribute和Action里都是空的。这个原因现在还没弄明白

    解决方法:

      1、采用以下方式读取post,至少写法简单一些了。但是只能传递到ActionFilterAttribute,Action也是拿不到

    //获取Post请求的内容
      context.Request.Content.ReadAsStreamAsync().Result.Seek(0, System.IO.SeekOrigin.Begin);
      dynamic content = await actionContext.Request.Content.ReadAsStringAsync().Result;

      2、 在ActionFilterAttribute类当中,可以用context.ActionArguments来获取body内容

    var task = context.ActionArguments;
                    foreach (var b in task)
                    {
                        var post = context.ActionArguments[b.Key];
    
                        if (null != post)
                        {
                            Type t = post.GetType();
                            var typeArr = t.GetProperties();
                            var str = "";
                            foreach (var a in typeArr.OrderBy(x => x.Name))
                            {
                                var n = a.Name;
                                var v = a.GetValue(post, null);
                                if (null != v && v.ToString() != "")
                                {
                                    str += @"""" + n + @""":" + @"""" + v + @""",";
                                }
                            }
                            str = str.TrimEnd(',');
                            str = @"{" + str + "}";
                            content += str + ",";
                        }
                    }
                    content = content.TrimEnd(',');
    View Code

            3、终极方案:用这种方式避免读流,ActionFilterAttribute和Action都能拿到body值  【注意异步读取时await】

    dynamic content = await context.Request.Content.ReadAsStringAsync();

    附Asp.net Core碰到此类问题的解决方法     https://blog.csdn.net/weixin_34126215/article/details/93605418

    微软官网对ReadAsStringAsync的解释:https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.httpcontent.readasstringasync?view=netframework-4.6.2

  • 相关阅读:
    linux 信号处理 二 (信号的默认处理)
    linux 信号处理 一 (基本概念)
    POSIX 消息队列 之 参数说明
    System V 消息队列 实例
    KDB支持单步调试功能(ARM架构)
    找工作笔试面试那些事儿(16)---linux相关知识点(1)
    Central Europe Regional Contest 2012 Problem H: Darts
    计算机数据结构之——什么是艺术品?
    老罗android开发视频教程 下载地址
    HTML5 实现拖拽
  • 原文地址:https://www.cnblogs.com/yhnet/p/13671799.html
Copyright © 2011-2022 走看看