2013-03-04 13 views
8

Sto avvolgendo un HttpRequestBase come HttpRequestMessage, che richiede la copia di tutte le intestazioni. Ma dal momento che il numero HttpRequestMessage è specifico riguardo a quali intestazioni si applicano all'oggetto richiesta rispetto all'oggetto Contenuto, la riga httpRequest.Headers.Add in basso genera talvolta InvalidOperationException.Come convertire HttpRequestBase in HttpRequestMessage, considerando i nomi delle intestazioni?

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

Ovviamente mi piacerebbe il mio codice di non generare eccezioni, ma si applicano invece in modo appropriato ogni intestazione all'oggetto appropriato. Come posso prevederlo? Esiste un metodo che possa essere utilizzato per testare l'applicabilità di un'intestazione inferiore a quella che genera e cattura le eccezioni?

+0

In realtà sto scoprendo che è più difficile persino del semplice posizionamento dell'intestazione. Alcune intestazioni (come Content-Type) non possono essere 'Add'ed affatto, ma possono essere impostate solo usando la proprietà ContentType. 'Accept' è un'altra intestazione che apparentemente devo analizzare e passare usando oggetti più ricchi. Sicuramente questo lavoro è già stato fatto e non devo rifarlo qui? –

+0

Nel tuo codice ho visto che hai letto request.Form o request.Content. Sono curioso di sapere se un oggetto HttpRequestBase potrebbe avere entrambi i contenuti importanti – StackOverflowVeryHelpful

+0

@StackOverflowVeryHelpful: No. I dati del modulo provengono nel contenuto. Quindi, se Form non è nullo, significa che la richiesta portava un'intestazione HTTP che indica che il flusso di input della richiesta trasportava i dati e ASP.NET lo analizzava, nel qual caso non è rimasto nulla di InputStream. –

risposta

13

Si scopre che è piuttosto semplice. Questo frammento viene fortemente ispirato da 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); 
     } 
    } 
} 
Problemi correlati