2012-08-17 60 views
14

我想從新的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

回答

20

問題是,與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

0

我有同樣的問題,最後選擇不寫入日誌中的內容。 我與記錄Content-Type和Content-Length一起生活。

但是,儘可能將所有內容寫入日誌總是一個好主意。

但是現在看起來和WebApi一樣,我們無法做到這一點。

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

我不知道這是否是好形式或壞的(壞疑),但是......它似乎能夠工作,遵循我見過的模型,推薦給那些需要使用DelegatingHandler「在途中」修改請求標頭和內容的人。

您的里程可能差別很大。

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

可以先創建一個提供安全的閱讀內容。 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); 
    } 
} 
2

這適用於我。

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