我将HttpRequestBase包装为HttpRequestMessage,它需要复制所有标头.但由于HttpRequestMessage特别关于哪些头应用于请求对象与Content对象,因此下面的httpRequest.Headers.Add行有时会抛出InvalidOperationException.
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; }
显然,我希望我的代码不会抛出异常,而是将每个标头适当地应用于适当的对象.我怎么预测呢?我是否可以使用任何方法来测试标题的适用性,而不是生成和捕获异常的标题?
解决方法
事实证明这很简单.这个片段的灵感源自
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); } } }