2013-03-04 93 views
8

我打包HttpRequestBase作爲HttpRequestMessage,這需要複製所有頭。但是由於HttpRequestMessage特別關於哪些頭應用於請求對象與Content對象,因此下面的httpRequest.Headers.Add行有時會引發InvalidOperationException。如何將HttpRequestBase轉換爲HttpRequestMessage,考慮標題名稱?

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

顯然我希望我的代碼不會拋出異常,而是適當地將每個頭應用到適當的對象。我如何預測這一點?有沒有什麼方法可以用來測試一個標題的適用性,它不足以產生和捕捉異常?

+0

我實際上發現它比標題放置更困難。某些標題(如Content-Type)根本無法添加,但只能使用ContentType屬性進行設置。 「接受」是另一個標題,顯然我必須使用更豐富的對象進行解析和傳遞。這項工作肯定已經完成,我不需要在這裏重做呢? – 2013-03-04 19:36:34

+0

在你的代碼中,我看到你要麼讀取request.Form或request.Content。我很想知道一個HttpRequestBase對象是否可以擁有重要的內容 – StackOverflowVeryHelpful 2016-02-11 19:25:03

+0

@StackOverflowVeryHelpful:否。表單數據進入內容。因此,如果Form不爲null,則表示該請求攜帶一個HTTP標頭,該標頭指示請求輸入流攜帶了表單數據,並由ASP.NET爲我們進行解析,在這種情況下,InputStream沒有任何內容。 – 2016-02-12 01:55:41

回答

13

事實證明這很簡單。這段代碼深受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); 
     } 
    } 
}