你的位置:首页 > ASP.net教程

[ASP.net教程]WebApi传参总动员(填坑)


本以为系列文章已经Over,突然记起来前面留了个大坑还没填,真是自己给自己挖坑。

这个坑就是:

(body 只能被读取一次)Only one thing can read the bodyMVC和WebAPI之间的一个关键不同点在于MVC缓存请求主体(request body)。这意味着MVC的参数绑定可以反复从body中查找参数片断。然而,在WebAPI中,请求主体(HttpContent)只能被读取一次,不被缓存,只能向前读取的流。这意味着parameter binding需要谨慎对待stream,除非在需要绑定参数的情况下,否则stream不能被读取。以下的action方法想直接读取stream,因而导致WebAPI不能保证其拥有用于参数绑定的stream。
引自:

[译]WebAPI下的如何实现参数绑定


这也就意味着,凡是参数中含有实体类型的,这个实体只能获取一次。

话说园子里WebApi安全性的文章也不少了,可是这个坑少有人提,也不晓得为啥,只好自己走一个大弯路先。

本人所在公司目前用MVC开发,Api做安全验证的时候,是将验证的系统参数和数据一起打包成一个匿名类,在Attribute中做验证,是可行的。同样的方式,拿到WebApi中,就死活走不下去。因为在ActionFilterAttribute中用请求的输入流(貌似只能以此种办法)获取实体后,在Action中就拿不到真正的数据了。

经过调整后的验证代码:

    /// WebAPI防篡改签名验证抽象基类Attribute    /// </summary>    public override void OnActionExecuting(HttpActionContext actionContext)    {      //获取Asp.Net对应的Request      var request = ((HttpContextWrapper)actionContext.Request.Properties["MS_HttpContext"]).Request;      NameValueCollection getCollection = request.QueryString;//此签名要求client_id、token及timestamp均通过QueryString传递      string outMessage = "未经过验证的请求!";      if (getCollection != null && getCollection.Count > 0)      {        string client_id = getCollection["client_id"];        string timestamp = getCollection["timestamp"];        string token = getCollection["token"];        if (!string.IsNullOrWhiteSpace(client_id)//必须包含client_id          && !string.IsNullOrWhiteSpace(timestamp)//必须包换时间戳          && !string.IsNullOrWhiteSpace(token))        //&& Regex.IsMatch(client_key, "^[0-9A-Za-z]{32}$"))//sign必须为32位Md5摘要        {          Config.Service.SignCalculation sc = new Config.Service.SignCalculation();          if (sc.VerifyClientParam(client_id, token, timestamp, out outMessage))          {//验证通过,执行基类方法            base.OnActionExecuting(actionContext);            return;          }        }        var html = "<p>" + outMessage + "</p>";                //此处暂时以401返回,可调整为其它返回        actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized,"验证失败");        actionContext.Response.Content = new StringContent(html, Encoding.UTF8, "text/html");      }    }

View Code

调整后,验证参数从请求QueryString中获得,Action可以用本系列的几种办法均可以顺利获取实际的数据。

填坑完毕。

本系列为本人原创,解决了本人实际工作中碰到的问题。

写文章不易,欢迎转载。但转载的时候,带上原文链接,可好?