2012-08-17 27 views
14

Tôi đang cố gắng trích xuất một số dữ liệu trong yêu cầu trong Web Api Asp.Net mới. Tôi có một thiết lập xử lý như thế này:Không thể đọc dữ liệu nội dung từ trang 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); 
    } 
} 

Đây là yêu cầu http tôi:

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 

vấn đề là không có vấn đề làm thế nào tôi cố gắng đọc các thông tin từ request.Content nó luôn luôn có sản phẩm nào. Tôi đã thử

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

cũng như

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

None nếu nó hoạt động. Tôi không thể lấy dữ liệu ra khỏi cơ thể. Tôi đang lưu trữ bên trong IIS trên Windows 7 và sử dụng Fiddler để gửi yêu cầu. Tôi đang làm gì sai?

+0

Sẽ rất hữu ích nếu bạn biết một khách hàng độc lập giống như wcftestclient.exe tạo ra kết quả tương tự. –

+0

Đã cố gắng để chạy điều đó nhưng nó sẽ không bởi vì nó nói rằng điểm cuối của tôi không có bất kỳ siêu dữ liệu nào. – Micah

+0

Điều đó có vẻ kỳ lạ. Có một số lý do bạn chọn phương thức truyền dữ liệu này qua phương pháp [HttpGet] và [HttpPost] được cung cấp không? –

Trả lời

20

Vấn đề là với Web Api cơ thể chỉ có thể đọc một lần. Tôi đã chạy mô-đun HTTP đang ghi nhật ký tất cả các chi tiết của yêu cầu và đọc qua cơ thể.

+0

vậy, việc sắp xếp này đăng nhập không thể, đúng không ?? – kooldave98

+1

Có thể, trước tiên bạn cần phải đọc nó vào bộ đệm, trước tiên sử dụng phương thức LoadIntoBufferAsync(). Điều này làm cho nội dung vẫn có sẵn cho phương thức cơ sở. Thêm từ đây https://weblogs.asp.net/fredriknormen/log-message-request-and-response-in-asp-net-webapi – Tom

0

Tôi đã gặp vấn đề tương tự và cuối cùng đã chọn không viết nội dung trong nhật ký. Tôi đang sống với việc ghi nhật ký Nội dung và Loại nội dung.

Nhưng bạn nên viết tất cả nội dung trong nhật ký càng nhiều càng tốt.

Nhưng có vẻ như với WebApi hiện tại chúng tôi không thể đạt được điều này.

7

Nó xấu xí, nhưng bạn có vẻ như từ mày mò ban đầu mà bạn có thể, trên thực tế, thay thế các nội dung trong 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); 
    } 

Tôi không có ý tưởng nếu điều này là hình thức tốt hay xấu (nghi ngờ xấu), nhưng .... nó dường như làm việc và theo mô hình tôi đã nhìn thấy đề nghị cho những người cần phải sửa đổi các tiêu đề yêu cầu và nội dung "trên đường" với một DelegatingHandler.

Số dặm của bạn có thể thay đổi đáng kể.

6

Tôi dựa trên câu trả lời của tôi về mã của brmore;

Chức năng này an toàn có thể đọc nội dung trong bất kỳ xử lý

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

Bạn có thể tạo một nhà cung cấp đầu tiên. MultipartMemoryStreamProvider() rồi Request.Content.ReadAsMultipartAsync(provider); sau đó đọc nội dung

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

Điều này phù hợp với tôi.

[HttpPost] 
public IHttpActionResult Index(HttpRequestMessage request) 
{ 
    var form = request.Content.ReadAsFormDataAsync().Result; 
    return Ok(); 
} 
Các vấn đề liên quan