2013-03-04 10 views
8

Pakuję plik HttpRequestBase jako HttpRequestMessage, który wymaga skopiowania wszystkich nagłówków. Ale ponieważ HttpRequestMessage jest szczególny o to, które nagłówki mają zastosowanie do obiektu żądania względem obiektu Content, linia httpRequest.Headers.Add poniżej czasami wywołuje wyjątek InvalidOperationException.Jak przekonwertować HttpRequestBase na HttpRequestMessage, biorąc pod uwagę nazwy nagłówków?

public static HttpRequestMessage AsHttpRequestMessage(this HttpRequestBase request) { 
    Requires.NotNull(request, "request"); 

    var httpRequest = new HttpRequestMessage(new HttpMethod(request.HttpMethod), request.Url); 
    foreach (string header in request.Headers) { 
     httpRequest.Headers.Add(header, request.Headers.GetValues(header)); 
    } 

    if (request.Form != null) { 
     // Avoid a request message that will try to read the request stream twice for already parsed data. 
     httpRequest.Content = new FormUrlEncodedContent(request.Form.AsKeyValuePairs()); 
    } else if (request.InputStream != null) { 
     httpRequest.Content = new StreamContent(request.InputStream); 
    } 

    return httpRequest; 
} 

Oczywiście chciałbym, aby mój kod nie generują wyjątki, ale odpowiednio zastosować każdy nagłówek do odpowiedniego obiektu. Jak mogę to przewidzieć? Czy istnieje jakaś metoda, której można użyć do przetestowania możliwości zastosowania nagłówka krótszego niż ten, który generuje i przechwytuje wyjątki?

+0

W rzeczywistości stwierdzam, że jest trudniejsze niż umieszczenie nagłówka. Niektóre nagłówki (takie jak Content-Type) nie mogą być w ogóle "dodawane", ale można je ustawić tylko za pomocą właściwości ContentType. "Accept" to kolejny nagłówek, który najwyraźniej muszę przeanalizować i przekazać przy użyciu bogatszych obiektów. Z pewnością ta praca została już wykonana i nie muszę jej tu ponownie edytować? –

+0

W twoim kodzie widziałem, że przeczytałeś request.Form lub request.Content. Jestem ciekawy, czy obiekt HttpRequestBase może mieć obu mających ważną treść – StackOverflowVeryHelpful

+0

@StackOverflowVeryHelpful: No. Dane formularza są w treści. Jeśli więc Form nie ma wartości NULL, oznacza to, że żądanie zawierało nagłówek HTTP wskazujący, że strumień wejściowy żądania zawiera dane, a ASP.NET przeanalizował je dla nas, w takim przypadku nie pozostało nic z InputStream. –

Odpowiedz

13

Okazuje się, że jest to dość proste. Ten fragment jest w dużym stopniu inspirowany przez ASP.NET's own open sourced source code.

/// <summary> 
/// Clones an <see cref="HttpWebRequest" /> in order to send it again. 
/// </summary> 
/// <param name="message">The message to set headers on.</param> 
/// <param name="request">The request with headers to clone.</param> 
internal static void CopyHeadersFrom(this HttpRequestMessage message, HttpRequestBase request) { 
    Requires.NotNull(request, "request"); 
    Requires.NotNull(message, "message"); 

    foreach (string headerName in request.Headers) { 
     string[] headerValues = request.Headers.GetValues(headerName); 
     if (!message.Headers.TryAddWithoutValidation(headerName, headerValues)) { 
      message.Content.Headers.TryAddWithoutValidation(headerName, headerValues); 
     } 
    } 
} 
Powiązane problemy