2013-03-19 47 views
9

Tôi đang cố gắng đăng xuất Nội dung Yêu cầu API Web - tức là chuỗi json. Tôi đã triển khai một lớp ITraceWriter (example) và cấu hình nó để Web API gọi nó trong đường dẫn. Nhưng nếu tôi đọc request.Content hoặc sao chép vào một dòng để đọc nó không có sẵn cho phương thức dẫn đến một mô hình null. This post nói về vấn đề đó một chút. Bất kỳ ai có kinh nghiệm đăng xuất nội dung yêu cầu API Web trong nước và biết cách tiếp cận tốt nhất là gì?Đăng nhập API Web ASP.NET Đăng nhập Nội dung Yêu cầu Nội dung

Cảm ơn

Cập nhật Một

Tôi tạo ra một dự án Web API mẫu đơn giản để loại trừ bất cứ điều gì trong dự án của tôi và tôi vẫn thấy rằng mô hình sẽ được null vì khai thác gỗ. Tôi chỉ cần kiểm tra một vài lần liên tiếp bằng cách đăng thông qua Fidder và xem mô hình của tôi có giá trị rỗng. Với breakpoint tại chỗ, nó có thể làm việc đó là lý do tại sao tôi nghĩ rằng có một vấn đề đồng bộ/thời gian. Bất kỳ suy nghĩ về cách để có được điều này để làm việc?

Tiêu đề:

User-Agent: Fiddler 
Host: localhost:56824 
Content-Type: application/json 
Content-Length: 22 

Body:

{ 
"A":1,"B":"test" 
} 

Dưới đây là các mã:

Bộ điều khiển:

public class ValuesController : ApiController 
{ 
    [HttpPost] 
    public void Post(ValuesModel model) 
    { 
     if (model == null) 
     { 
      Debug.WriteLine("model was null!"); 
     } 
     else 
     { 
      Debug.WriteLine("model was NOT null!"); 
     } 
    } 
} 

mẫu:

public class ValuesModel 
{ 
    public int A { get; set; } 
    public string B { get; set; } 
} 

Logger:

public class APITraceLogger : DelegatingHandler 
    { 
     protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
     { 
      if (request.Content != null) 
      { 
       // This can cause model to be null 
       request.Content.ReadAsStringAsync().ContinueWith(s => 
       { 
        string requestText = s.Result; 
        Debug.WriteLine(requestText); 
       }); 

       // and so can this 
       //request.Content.ReadAsByteArrayAsync() 
       // .ContinueWith((task) => 
       // { 
       //  string requestText = System.Text.UTF8Encoding.UTF8.GetString(task.Result); 
       //  Debug.WriteLine(requestText); 
       // }); 
      } 
      // Execute the request, this does not block 
      var response = base.SendAsync(request, cancellationToken); 

      // TODO: 
      // Once the response is processed asynchronously, log the response data 
      // to the database 


      return response; 
     } 


    } 

Dây lên logger trong lớp WebApiConfig:

config.MessageHandlers.Add(new APITraceLogger()); 

Cập nhật B

Nó có vẻ như nó đang làm việc nếu tôi thay đổi logger đến đoạn mã sau thêm sự chờ đợi, không đồng bộ và trả về kết quả. Có vẻ như một cái gì đó tôi không hiểu trong mã async hoặc thực sự là một vấn đề thời gian hoặc một cái gì đó.

public class APITraceLogger : DelegatingHandler 
{ 
    protected async override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
    { 
     if (request.Content != null) 
     { 

      // This does seem to work - is it because it is synchronous? Is this a potential problem? 
      var requestText = await request.Content.ReadAsStringAsync(); 
      Debug.WriteLine(requestText); 
     } 
     // Execute the request, this does not block 
     var response = base.SendAsync(request, cancellationToken); 

     // TODO: 
     // Once the response is processed asynchronously, log the response data 
     // to the database 


     return response.Result; 
    } 


} 

Trả lời

5

Như Filip đề cập trong bài đăng đó ReadAsStringAsync hoặc ReadAsByteArrayCác phương pháp đồng bộ đệm nội dung yêu cầu nội bộ. Điều này có nghĩa là ngay cả khi loại luồng yêu cầu gửi đến của bạn là luồng không đệm, bạn cũng có thể thực hiện một cách an toàn ReadAsStringAsync/ReadAsByteArrayAsync ở trình xử lý tin nhắn và cũng mong đợi mô hình ràng buộc để hoạt động tốt.

Theo mặc định, luồng của yêu cầu được đệm trong cả máy chủ web và các trường hợp tự lưu trữ. Nhưng nếu bạn muốn kiểm tra nếu sử dụng ReadAsStringAsync/ReadAsByteArrayAsync và mô hình đấu thầu hoạt động tốt ngay cả trong chế độ không đệm, bạn có thể làm như sau để buộc phi đệm chế độ:

public class CustomBufferPolicySelector : WebHostBufferPolicySelector 
{ 
    public override bool UseBufferedInputStream(object hostContext) 
    { 
     //NOTE: by default, the request stream is always in buffered mode. 
     //return base.UseBufferedInputStream(hostContext); 

     return false; 
    } 
} 

config.Services.Replace(typeof(IHostBufferPolicySelector), new CustomBufferPolicySelector()); 

Just FYI ... trên bộ chọn chính sách chỉ hoạt động đối với Máy chủ web hiện tại.Nếu bạn muốn làm một thử nghiệm tương tự trong SelfHost, sau đó làm như sau:

//NOTE: by default, the transfer mode is TransferMode.Buffered 
config.TransferMode = System.ServiceModel.TransferMode.StreamedRequest; 

Sau Cập nhật B của bài trên:

Bạn có thể sửa đổi xử lý của bạn như dưới đây:

public class LoggingHandler : DelegatingHandler 
{ 
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     if (request.Content != null) 
     { 
      string requestContent = await request.Content.ReadAsStringAsync(); 
     } 

     HttpResponseMessage response = await base.SendAsync(request, cancellationToken); 

     if (response.Content != null) 
     { 
      string responseContent = await response.Content.ReadAsStringAsync(); 
     } 

     return response; 
    } 
} 
+0

Tôi bị Filip đưa ra nhận xét đó. Tôi đã sử dụng ReadAsStringAsync và mô hình của tôi sẽ là rỗng. Đây là mã cơ bản tôi đã sử dụng trong triển khai ITraceWriter: request.Content.ReadAsStringAsync(). ContinueWith (s => { chuỗi requestText = s.Result; Logger.Log (requestText); }); – Bryan

+0

Tôi không thể repro vấn đề bạn đang đề cập đến. Ví dụ (không phải cách tốt nhất để làm điều đó), tôi có đoạn mã sau trong phương thức WriteTrace của SimpleTracer từ mẫu của Mike Wasson: if (rec.Request! = Null) {Console.WriteLine (rec.Category + "," + rec.Request.Content.ReadAsStringAsync(). Kết quả); } –

+0

Cảm ơn bạn đã cố gắng để repro. Cố gắng tìm ra những gì khác biệt. Tôi đang sử dụng MVC 4 và chạy trong IIS Express cho dev địa phương của tôi. Có lẽ IIS Express là sự khác biệt. Tôi đang thử một thứ khác và sẽ đăng lại. – Bryan

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