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

问题描述:

我想从新的Asp.Net Web Api中的请求中提取一些数据。我有一个处理程序设置是这样的:无法从web api读取正文数据POST

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); 
    } 
} 

这是我的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 

的问题是,无论我如何努力从request.Content读取信息,它总是空的。我试过

request.Content.ReadAsStreamAsync 
request.Content.ReadAsFormDataAsync 
request.Content.ReadAs<FormDataCollection> 

以及

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

无它是否工作。我无法从身体中获取数据。我在Windows 7的IIS内托管并使用Fiddler提交请求。我究竟做错了什么?

+0

如果知道类似于wcftestclient.exe的独立客户端是否产生类似结果将会有所帮助。 – 2012-08-17 14:31:13

+0

试图运行,但它不会,因为它说我的端点没有任何元数据。 – Micah 2012-08-17 14:43:29

+0

这看起来很奇怪。您是否有理由选择通过提供的[HttpGet]和[HttpPost]方法进行数据传输的方法? – 2012-08-17 14:46:49

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

+0

所以,做这样登录不可能,对吗? – kooldave98 2015-05-06 11:30:14

+1

有可能,您需要首先使用LoadIntoBufferAsync()方法将其读入缓冲区。这使内容仍可用于基本方法。更多从这里https://weblogs.asp.net/fredriknormen/log-message-request-and-response-in-asp-net-webapi – Tom 2016-10-14 12:46:41

我有同样的问题,最后选择不写入日志中的内容。 我与记录Content-Type和Content-Length一起生活。

但是,尽可能将所有内容写入日志总是一个好主意。

但是现在看起来和WebApi一样,我们无法做到这一点。

这是丑陋的,但是你把它从最初的修修补补,你可以,事实上,更换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); 
    } 

我不知道这是否是好形式或坏的(坏疑),但是......它似乎能够工作,遵循我见过的模型,推荐给那些需要使用DelegatingHandler“在途中”修改请求标头和内容的人。

您的里程可能差别很大。

我根据我对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; 
} 

可以先创建一个提供安全的阅读内容。 MultipartMemoryStreamProvider() 然后Request.Content.ReadAsMultipartAsync(provider); 然后阅读内容

public async Task<IHttpActionResult> Post(int id, string type) 
{ 
    // Check if the request contains multipart/form-data. 
    if(!Request.Content.IsMimeMultipartContent("form-data")) 
     return BadRequest("Unsupported media type"); 

    try 
    { 
     var azureManager = new AzureManager(); 
     var imageManager = new ImageManager(); 
     var provider = new MultipartMemoryStreamProvider(); 

     await Request.Content.ReadAsMultipartAsync(provider); 

     var assets = new List<Asset>(); 
     foreach (var file in provider.Contents) 
     { 
      var stream = await file.ReadAsStreamAsync(); 
      var guid = Guid.NewGuid(); 
      string blobName = guid.ToString(); 

      await azureManager.UploadAsync(blobName, stream); 

      var asset = new Asset 
      { 
       PropertyId = id, 
       FileId = guid, 
       FileName = file.Headers.ContentDisposition.FileName.Trim('\"').ToLower(), 
       FileSize = file.Headers.ContentLength ?? 0, 
       MimeType = file.Headers.ContentType.MediaType.ToLower() 
      }; 

      if (type == "photos") 
      { 
       asset.Type = AssetType.Photo; 

       // Resize and crop copies to 16:9 
       using (MemoryStream thumb = imageManager.ResizeImage(stream, 320, 180)) 
       { 
        await azureManager.UploadAsync(blobName, thumb, BlobContainers.Thumbs); 
       } 
       using (MemoryStream photo = imageManager.ResizeImage(stream, 1024, 576)) 
       { 
        await azureManager.UploadAsync(blobName, photo, BlobContainers.Photos); 
       } 
      } 
      else 
       asset.AssumeType(); 

      assets.Add(asset); 
     } 

     db.Assets.AddRange(assets); 
     await db.SaveChangesAsync(); 

     return Ok(new { Message = "Assets uploaded ok", Assets = assets }); 
    } 
    catch (Exception ex) 
    { 
     return BadRequest(ex.GetBaseException().Message); 
    } 
} 

这适用于我。

[HttpPost] 
public IHttpActionResult Index(HttpRequestMessage request) 
{ 
    var form = request.Content.ReadAsFormDataAsync().Result; 
    return Ok(); 
}