无法从web api POST读取正文数据

Mic*_*cah 13 .net c# asp.net asp.net-web-api

我正在尝试从新的Asp.Net Web Api中的请求中提取一些数据.我有这样的处理程序设置:

public class MyTestHandler : DelegatingHandler
{
    protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        if (request.Content.IsFormData())
        {
            request.Content.ReadAsStreamAsync().ContinueWith(x => {
                var result = "";
                using (var sr = new StreamReader(x.Result))
                {
                    result = sr.ReadToEnd();
                }
                Console.Write(result);
            });
        }

        return base.SendAsync(request, cancellationToken);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的http请求:

POST http://127.0.0.1/test HTTP/1.1
Connection: Keep-Alive
Content-Length: 29
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue
Host: 127.0.0.1

my_property=my_value
Run Code Online (Sandbox Code Playgroud)

问题是无论我如何尝试从中读取信息request.Content总是空的.我试过了

request.Content.ReadAsStreamAsync
request.Content.ReadAsFormDataAsync
request.Content.ReadAs<FormDataCollection>
Run Code Online (Sandbox Code Playgroud)

以及

    [HttpGet,HttpPost]
    public string Index([FromBody]string my_property)
    {
        //my_property == null
        return "Test";
    }
Run Code Online (Sandbox Code Playgroud)

没有,如果它的工作.我无法将数据从身体中取出.我在Windows 7上的IIS内部托管并使用Fiddler提交请求.我究竟做错了什么?

Mic*_*cah 20

问题是,使用Web Api,主体只能读取一次.我有一个HTTP模块正在运行,它记录了请求的所有细节,并正在读取正文.

  • 有可能,首先需要使用LoadIntoBufferAsync()方法将其读入缓冲区.这使得内容仍可用于基本方法.更多来自这里https://weblogs.asp.net/fredriknormen/log-message-request-and-response-in-asp-net-webapi (2认同)

brm*_*ore 7

这很难看,但是从最初的修补看来,你可以实际上替换DelegatingHandler中的内容......

protected override Task SendAsync(
          HttpRequestMessage request,
          CancellationToken cancellationToken)
      {                    
          Stream stream = new MemoryStream();

          request.Content.ReadAsStreamAsync().Result.CopyTo(stream);
          stream.Seek(0,SeekOrigin.Begin);

          // copy off the content "for later"
          string query = new StreamReader(stream).ReadToEnd();
          stream.Seek(0,SeekOrigin.Begin);

          // if further processing depends on content type
          // go ahead and grab current value
          var contentType = request.Content.Headers.ContentType;

          request.Content = new StreamContent(stream);
          request.Content.Headers.ContentType = contentType;

          return base.SendAsync(request, cancellationToken);
     }
Run Code Online (Sandbox Code Playgroud)

我不知道这是好形式还是坏(可疑坏),但....它似乎工作并遵循模型我已经看到建议那些需要修改请求标题和内容"在路上"与DelegatingHandler.

您的里程可能会有很大差异


ulm*_*zov 6

我的答案基于brmore的代码;

此函数可以安全地读取任何处理程序中的内容

private string SafeReadContentFrom(HttpRequestMessage request)
{
     var contentType = request.Content.Headers.ContentType;
     var contentInString = request.Content.ReadAsStringAsync().Result;
     request.Content = new StringContent(contentInString);
     request.Content.Headers.ContentType = contentType;
     return contentInString;
}
Run Code Online (Sandbox Code Playgroud)