2012-08-24 18 views
12

Khi cố gắng để một đối tượng trong một hành động trong một điều khiển nó lẻ tẻ có vẻ là null. Tôi phát hiện ra rằng đó là do số ReadAsStringAsync() trong ghi đè SendAsync() của số DelegatingHandler. Vấn đề là với nội dung. Khi khách hàng của tôi gửi một nội dung nội dung và nó được đọc trong trình ghi nhật ký, nó không bao giờ được đọc bởi Trình điều khiển tác vụ điều khiển (hoặc có thể ở đâu đó trong số JsonFormatter). Tôi nghi ngờ các cuộc gọi tiếp theo để Content.ReadAsStringAsync() không ném một ngoại lệ nhưng cũng không trả lại cơ thể nội dung dự kiến ​​(một số thông tin được trả lại nói rằng đọc async được hoàn thành).HttpRequestMessage.Content bị mất khi nó được đọc trong một DelegatingHandler đăng nhập trong ASP.Net Web API

Nhưng vấn đề của tôi vẫn còn kể từ khi tôi muốn đọc một tham số [FromBody] trong một hành động và nó là vô giá trị khi RaceCondition Content.ReadStringAsync được thắng bởi DelegatingHandler. Khi JsonFormatter thắng nó mặc dù, tôi nhận được đối tượng nhưng đó là hiếm (chỉ khi khởi động dịch vụ).

Đây là mã DelegatingHandler tôi:

public class LogHandler : DelegatingHandler 
{ 

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     var apiRequest = new WebApiUsageRequest(request); 
     WriteLog(apiRequest); 
     request.Content.ReadAsStringAsync().ContinueWith(t => 
     { 
      apiRequest.Content = t.Result; 
      WriteLog(apiRequest); 
     }); 

     return base.SendAsync(request, cancellationToken).ContinueWith(task => 
     { 
      var apiResponse = new WebApiUsageResponse(task.Result); 
      apiResponse.Content = task.Result.Content != null ? task.Result.Content.ReadAsStringAsync().Result : null; 
      WriteLog(apiResponse); 
      return task.Result; 
     }); 
    } 
} 

Có ai có một đầu mối để các giải pháp của vấn đề này?

+0

Quên đề cập đến đây là RC. Tôi nghi ngờ quan sát vẫn giữ nguyên trong RTM quá – Sando

Trả lời

9

Đây là theo thiết kế. Trong ASP.NET Web API, nội dung nội dung được xử lý luồng chỉ chuyển tiếp chỉ có thể đọc một lần.

Bạn có thể thử sử dụng ASP.NET Web API Tracing nhưng tôi chưa thử nghiệm với yêu cầu POST, vì vậy tôi không chắc cách/nếu nó truy tìm phần thân yêu cầu. chắc chắn). Bạn có thể đọc thêm ở đây:

+2

Cảm ơn.Tôi nghĩ cho các yêu cầu của tôi, tôi có thể sống với việc không viết nội dung để đăng nhập. Tuy nhiên, điều này nên là 'Điểm cần lưu ý' đối với tất cả các nhà phát triển api trên web đang cố đăng nhập nội dung và cũng sử dụng [FromBody] trong Tác vụ POST – Sando

2

nhưng nếu bạn sử dụng mã dưới đây vào SendAsync nó hoạt động đúng

 if (request.Content != null) 
     { 
      request.Content.ReadAsByteArrayAsync().ContinueWith 
       (
        (task) => 
        { 

          var xxx = System.Text.UTF8Encoding.UTF8.GetString(task.Result); 
        }); 
     } 
     return base.SendAsync(request, cancellationToken) //than call the base 

. . .

+0

Nhưng tại sao nó hoạt động khi thực hiện việc này? –

+0

Đó không phải là điều tương tự. Bạn đang đọc nội dung yêu cầu chứ không phải nội dung phản hồi, điều này cũng là lý do tại sao nó hoạt động – Adam

5

Phương thức ReadAsStreamAsync trả về nội dung nội dung.

var body = string.Empty; 
using (var reader = new StreamReader(request.Content.ReadAsStreamAsync().Result)) 
{ 
    reader.BaseStream.Seek(0, SeekOrigin.Begin); 
    body = reader.ReadToEnd(); 
} 
+0

Hãy coi chừng khối sử dụng sẽ đóng hơi nước bên dưới. – ivanmartinvalle

1

này đã làm việc cho tôi:

using (var stream = new MemoryStream()) 
{ 
    var context = (HttpContextBase)Request.Properties["MS_HttpContext"]; 
    context.Request.InputStream.Seek(0, SeekOrigin.Begin); 
    context.Request.InputStream.CopyTo(stream); 
    string requestBody = Encoding.UTF8.GetString(stream.ToArray()); 
} 

Returned cho tôi đại diện json của đối tượng tham số của tôi, vì vậy tôi có thể sử dụng nó để xử lý ngoại lệ và khai thác gỗ.

Tìm thấy là câu trả lời chấp nhận here

+0

Nhưng ở đây chúng tôi không thể nhận được tiêu đề yêu cầu –

1

Đây là những gì tôi đã kết thúc thực hiện:

public string SafelyReadContent(HttpRequestMessage request) 
{ 
    var stream = request.Content.ReadAsStreamAsync().Result; 
    var reader = new StreamReader(stream); 
    var result = reader.ReadToEnd(); 
    stream.Seek(0, SeekOrigin.Begin); 

    return result; 
} 

@ câu trả lời pirimoglu của của việc sử dụng một "sử dụng" khối không làm việc cho tôi, vì khi người đọc đã được xử lý , dòng cơ bản cũng đã bị đóng.

+0

nó không hoạt động :( –

Các vấn đề liên quan