无法在ASP.NET WebApi控制器中读取Request.Content

mci*_*321 23 c# asynchronous asp.net-web-api

我在TransferMode.Streamed HttpSelfHostConfiguration exe中使用WebApi编写代理.

当我使用fiddler发布到我的ApiController时,出于某种原因我无法读取Request.Content - 即使我有POSTed数据它也返回""

public class ApiProxyController : ApiController
{

    public Task<HttpResponseMessage> Post(string path)
    {
        return Request.Content.ReadAsStringAsync().ContinueWith(s =>
        {
            var content = new StringContent(s.Result); //s.Result is ""
                CopyHeaders(Request.Content.Headers, content.Headers);
            return Proxy(path, content);
        }).Unwrap();
    }

    private Task<HttpResponseMessage> Proxy(string path, HttpContent content)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的网络请求

POST http://localhost:3001/api/values HTTP/1.1
Host: localhost:3001
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Content-Type: application/json
Content-Length: 26

{ "text":"dfsadfsadfsadf"}
Run Code Online (Sandbox Code Playgroud)

我做错了什么?为什么s.Result作为空字符串而不是原始json返回?

小智 35

我也很挣扎.ReadAsStringAsyncReadAsAsync返回一个任务对象.引用该Result属性将返回内容.它可能是引用Result属性导致异步读取请求被阻止.

例:

string str = response.Content.ReadAsStringAsync().Result;
Run Code Online (Sandbox Code Playgroud)

  • 使用await而不是.Reseult (3认同)

Ric*_*uer 18

我意识到这已经过时了,并且已经得到了解答,但是对于它的价值,你不能使用的原因ReadAsStringAsync()并不是因为它"按照建议的那样"来处理数据,而是因为内容正在作为流处理而且由于数据已由消息格式化程序使用,因此流的位置已经在最后.

为了使用ReadAsStringAsync()您首先需要将内容流位置重置为开头.

我是这样做的:response.RequestMessage.Content.ReadAsStreamAsync().Result.Seek( 0, System.IO.SeekOrigin.Begin )因为我只有HttpResponseMessage,但是如果你可以直接访问HttpRequestMessage(就像你在Controller里面那样),你可以使用Request.Content.ReadAsStreamAsync().Result.Seek( 0, System.IO.SeekOrigin.Begin )哪个在功能上等同于我想的.


JJ_*_*ire 17

这个帖子的签名吃了帖子数据:

public HttpResponseMessage Post([FromBody]string postdata)
Run Code Online (Sandbox Code Playgroud)

将其更改为:

public HttpResponseMessage Post()
Run Code Online (Sandbox Code Playgroud)

然后这个调用工作正常,以获取发布数据:

string str = response.Content.ReadAsStringAsync().Result;
Run Code Online (Sandbox Code Playgroud)

我自己测试过.使用第一个签名,str为空,使用第二个str有帖子数据!


Eve*_*ent 5

我相信你对使用Request.Content的ApiController说得对.您在ApiController中看到的"Request"对象实际上是System.Net.Http.HttpRequestMessage类型.我能够解决这个问题,但备份到System.Web.HttpRequest对象,如下所示:

Dim content as string
If HttpContext.Current.Request.InputStream.CanSeek Then
    HttpContext.Current.Request.InputStream.Seek(0, IO.SeekOrigin.Begin)
End If
Using reader As New System.IO.StreamReader(HttpContext.Current.Request.InputStream)
    content = reader.ReadToEnd()
End Using
Run Code Online (Sandbox Code Playgroud)

我不知道寻求倒带是否有必要,但我把它放在以防万一.


mci*_*321 4

我最终通过从基本接口而不是 ApiController 继承来实现这个工作 - 我认为 ApiController 是模型绑定,它正在吃掉响应

编辑:构建代理的正确方法是 MessageHandler,而不是 ApiController