2012-04-12 118 views
22

我在TransferMode.Streamed HttpSelfHostConfiguration EXE使用的WebAPI写一个代理读取Request.Content。不能在ASP.NET的WebAPI控制器

当我使用Fiddler张贴到我ApiController,由于某种原因,我无法读取Request.Content - 它返回“”即使我已经发布的数据

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) 
    { 
     ... 
    } 
} 

这里是我的web请求

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"} 

我做错了吗?为什么s.Result以空字符串而不是原始json的形式返回?

回答

4

我到底该工作由底座接口而不是ApiController继承 - 我认为ApiController是modelbinding这是吃的响应

编辑:正确的做法建立一个代理是的MessageHandler,不一个ApiController

+0

MSDN指示MessageHandlers应该用于横切关注。对于构建代理,标准的MVC控制器应该工作正常。 – arviman 2014-06-23 10:28:25

+0

如果您正在构建流式代理服务器,则不适用。 – mcintyre321 2014-06-23 10:34:32

+0

我的意思是,在转发给代理之前,您可以使用阻止的想法,直到您获得JeffR建议的结果。 (我现在正在构建类似的东西,而且工作起来很棒)。 – arviman 2014-06-23 10:41:06

0

尝试ReadAsAsync<string>()更换ReadAsStringAsync()

34

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

例子:

string str = response.Content.ReadAsStringAsync().Result; 
+0

这可能会锁定API调用取决于环境... – LPains 2016-09-02 16:03:05

+1

使用等待,而不是.Reseult – victor 2017-10-19 20:43:57

0

你应该使用一个复杂类型的参数,然后以身体使用一些JSON像

{路径: “C:...”}

阿尔斯使用

内容类型:应用程序/ JSON的;字符集= UTF-8

头在你的POST请求,以便Web API知道JSON是体内所含

5

我相信你是正确的关于ApiController吃Request.Content。您在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

我不知道,如果寻求倒带是必要的,但我把它放在以防万一。

+0

原来的ApiController是构建代理的错误。最后我用了一个MessageHandler,一切都很好。 – mcintyre321 2013-05-09 10:25:15

+0

这很好。我只需要它进行调试,所以这真棒。 – BradLaney 2013-05-13 19:47:05

15

此签名后吃后数据:

public HttpResponseMessage Post([FromBody]string postdata) 

将其更改为:

public HttpResponseMessage Post() 

,则此调用正常工作获得那个职位数据:

string str = response.Content.ReadAsStringAsync().Result; 

测试这是我的自我。使用第一个签名,str是空的,使用第二个str有post数据!

+0

但是你怎么能得到postdata的方法? – 2015-11-18 10:00:11

+0

var request = await Request.Content.ReadAsStringAsync(); – War 2015-12-03 14:08:24

+0

这也适用于MVC中的控制器。使用'FormCollection窗体'将会吃掉一个请求的内容。 – jahu 2016-04-11 15:00:25

13

我意识到这是旧的,并已得到回答,但对于它的价值,不能使用ReadAsStringAsync()的原因不是因为它'按照建议吃'数据',这是因为内容正在作为一个流处理,并且由于数据已被消息格式化器使用,流的位置已经在最后。

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

我不喜欢这样写道:response.RequestMessage.Content.ReadAsStreamAsync().Result.Seek(0, System.IO.SeekOrigin.Begin),因为我只有HttpResponseMessage,但如果你有到HttpRequestMessage直接访问(如你的控制器里面做),你可以使用Request.Content.ReadAsStreamAsync().Result.Seek(0, System.IO.SeekOrigin.Begin)其在功能上等同我想。

+1

我相信,如果你与流请求模式(如果写一个代理,你不想占用大量内存这一点很重要)的工作,你无法重置流的位置。 此外,有那么可怕用“吃”来代替“消费”?我怀疑有人认为生物体正在发生。 :) – mcintyre321 2016-01-15 11:52:44

+1

@ mcintyre321大声笑。好吧,'消费'要这样一个伟大的选择是它。我想'吃过'意味着我无法取回它。 FWIW我可以重置流l位置(缓冲区不会直接从远程流读取)。就你而言,我想知道在数据超过缓冲区大小的非常大的请求流中会发生什么情况?我在重新阅读多部分流时遇到了问题,因为它一直在处理自己。最终将其读入内存流第一,他们解析出来到'ReadAsMultipartAsnc()' – 2016-01-16 20:23:52

1
  1. Request.Content.ReadAsStreamAsync()。Result.Seek(0,System.IO.SeekOrigin.Begin)
  2. 新就是System.IO.StreamReader(Request.Content.ReadAsStreamAsync()。结果).ReadToEnd ()
+0

,谢谢,我只需要1行。 – user2972061 2018-03-04 16:06:20

相关问题