我正在将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;
}
显然,我希望我的代码不会抛出异常,而是将每个标头适当地应用到适当的对象。我怎么预测呢?我是否可以使用任何方法来测试标题的适用性,而不是生成和捕获异常的标题?
答案 0 :(得分: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);
}
}
}
答案 1 :(得分:1)
您应该可以使用TryAddWithoutValidation而不是Add来避免抛出。根据是否要缓冲请求,您需要注意是否调用GetBufferlessStream。请参阅以下类中的ConvertRequest方法:http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/4764b0111b91#src/System.Web.Http.WebHost/HttpControllerHandler.cs