2013-03-19 23 views
9

Web API İsteği İçeriği - yani json dizesini günlüğe kaydetmeye çalışıyorum. Bir ITraceWriter sınıfı (example) uyguladı ve Web API'sinin bunu boru hattında çağırması için yapılandırdım. Ama eğer request.Content'i okursaydım veya okumak için bir akıma kopyalamak, null modeliyle sonuçlanan yöntem için mevcut değildir. This post, bu konu hakkında biraz konuşuyor. Herkes, gelen Web API istek içeriğinin kaydını kapatarak en iyi yaklaşımın ne olduğunu biliyor mu?ASP.NET Web API Gelen İstek İsteğini Kaydetme

Teşekkür

Güncelleme A

Projemde şeyi göz ardı etmek için basit örnek Web API projesi oluşturdu ve hala modeli nedeniyle günlük sıfır olacağını görüyoruz. Fidder ile sırayla birkaç kez test ediyorum ve modelimin boş olduğunu görüyorum. Nokta kesme noktaları ile çalışabilir, bu yüzden bir senkronizasyon/zamanlama sorunu olduğunu düşünüyorum. Bunu nasıl çalıştıracağınıza dair herhangi bir düşünce var mı?

Başlık:

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

Gövde:

Kontrolör:

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

Modeli:

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

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

Kaydedici:

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


    } 

WebApiConfig sınıfında Kablolama yukarı logger:

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

Güncelleme B ben logger değiştirmek eğer şimdi çalışıyor gibi görünüyor

kodu bekletme, uyumsuzluk ve sonuca geri dönme. Async kodunda ya da gerçekten bir zamanlama sorunu veya bir şey anlamıyorum bir şey gibi görünüyor.

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


} 

cevap

5

Filip post ReadAsStringAsync bahseder veya ReadAsByteArrayAsync yöntemleri dahili talebi içeriği tampon olarak. Bu, gelen isteğinizin akış türünün tamponlu olmayan bir akış olsa bile, bir ileti işleyicisinde bir ReadAsStringAsync/ReadAsByteArrayAsync güvenli bir şekilde yapabileceğiniz ve modelin düzgün çalışmasını bekleyebilirsiniz anlamına gelir.

Varsayılan olarak, bir isteğin akışı hem webhost hem de selfhost durumlarında arabelleğe alınır. Yukarıda ... Bilginize

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

: Ama ReadAsStringAsync/ReadAsByteArrayAsync ve model bekliyorumdur bile olmayan tamponlu modda çalışıyor kullanarak kontrol etmek istiyorsanız, olmayan tamponlu modu zorlamak için aşağıdakileri yapabilirsiniz politika seçici şu anda yalnızca Web Ana Bilgisayarı için çalışır.Eğer SelfHost benzer bir testi yapmak istiyorsanız, şunları yapın:

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

Yukarıdaki yazının Güncelleme B sonra:

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; 
    } 
} 
: Aşağıdaki gibi

Sen işleyicisi değiştirebilir

+0

Filip tarafından bu yoruma atıldım. ReadAsStringAsync'i kullandım ve modelim boş olacaktı. İşte ITraceWriter uygulamasında kullandığım temel kod: request.Content.ReadAsStringAsync(). ContinueWith (s => { string requestText = s.Result; Logger.Log (requestText); }); – Bryan

+0

İstediğiniz konuyu yeniden sunamıyorum. Örneğin (bunu yapmanın en iyi yolu değil), Mike Wasson örneğinden SimpleTracer'ın WriteTrace yönteminde aşağıdaki kodu kullanıyorum: if (rec.Request! = Null) {Console.WriteLine (rec.Category + "," + rec.Request.Content.ReadAsStringAsync() Sonuç.); } –

+0

Tekrar denenmeye çalıştığınız için teşekkürler. Neyin farklı olduğunu anlamaya çalışıyorum. MVC 4 kullanıyorum ve yerel dev için IIS Express'te çalışıyorum. Belki de IIS Express farkıdır. Farklı bir şey deniyorum ve geri göndereceğim. – Bryan