【问题标题】:How to convert HttpRequestBase to HttpRequestMessage, considering header names?考虑到标头名称,如何将 HttpRequestBase 转换为 HttpRequestMessage?
【发布时间】:2013-03-04 19:17:04
【问题描述】:

我将HttpRequestBase 包装为HttpRequestMessage,这需要复制所有标题。但是由于HttpRequestMessage 对哪些标头适用于请求对象和内容对象比较特别,所以下面的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;
}

显然,我希望我的代码不抛出异常,而是将每个标头适当地应用于适当的对象。我怎么能预测这个?有没有什么方法可以用来测试没有生成和捕获异常的标头的适用性?

【问题讨论】:

  • 我实际上发现它甚至比标题放置更难。某些标头(如 Content-Type)根本不能是 Added,但只能使用 ContentType 属性进行设置。 Accept 是另一个标题,显然我必须使用更丰富的对象解析和传递。确定这项工作已经完成了,我不必在这里重做?
  • 在您的代码中,我看到您阅读 request.Form 或 request.Content 。我很想知道 HttpRequestBase 对象是否可以同时具有重要内容
  • @StackOverflowVeryHelpful:不。表单数据来自内容。所以如果Form不为null,则表示请求携带了一个HTTP头,表示请求输入流携带了表单数据,ASP.NET为我们解析了,此时InputStream就没有了。

标签: asp.net httpclient


【解决方案1】:

事实证明这很简单。这个 sn-p 的灵感来自 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);
        }
    }
}

【讨论】:

    【解决方案2】:

    您应该能够使用 TryAddWithoutValidation 而不是 Add 来避免抛出。您需要注意是否调用 GetBufferlessStream 取决于您是否要缓冲请求。请参阅以下类中的 ConvertRequest 方法:http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/4764b0111b91#src/System.Web.Http.WebHost/HttpControllerHandler.cs

    【讨论】:

      猜你喜欢
      • 2013-03-21
      • 2013-02-22
      • 2010-11-29
      • 1970-01-01
      • 2018-01-27
      • 2013-04-22
      • 2014-11-26
      • 2012-07-21
      相关资源
      最近更新 更多