我可以修改Request.Headers收藏?(Can I modify the Request.H

2019-08-17 08:25发布

我有一个使用第三方报告组件的ASP.NET网站。 该组件通过投掷行为不端NullReferenceException每当客户端浏览器未指定User-Agent在请求报头。

这基本上是我只是想拿出的解决方法,一个奇怪的场景。 我不知道是谁/什么客户端没有指定一个用户代理,这似乎是不好的形式IMO,但我们必须处理它产生的例外。 我已经登录有关于他们的报告组件的bug的第三方支持票,但我有我的这条路线是如何卓有成效的将是疑惑。 所以我的想法是只检测当User-Agent是空白,它默认的东西只是为了安抚报告组件。 不过,我似乎无法更改Request.Headers收集任何东西。 我得到以下异常:

Operation is not supported on this platform.

我开始相信我不会是能够做到这一点。 我明白为什么 ASP.NET不会允许这样做,但我还没有想出任何其他的解决办法。

更新:彭福公的建议下,我试图添加User-AgentRequest.Headers集合使用HttpModule 。 这得到它添加到Headers集合,但没有采取任何行动来更新Request.UserAgent属性,这是什么原因造成的报表组件失败。 我一直在寻找通过.net反射,以确定该属性是如何设置的,这样我就可以更新了,但我还没有想出什么,但(不仅仅有驱动,我可以找物业的私人领域)。

Answer 1:

我认为处理这个最好的办法是使用HTTP模块将检查头,必要时注入用户代理。

正如你已经发现了,你不能使用标头对象的设置方法。 相反,你将不得不通过可通过反射来访问作为答案概述保护性注入用户代理字符串到页眉这一问题 。

UPDATE

不幸的是Request.UserAgent不使用保存的信息Request.Headers ,而是调用该方法GetKnownRequestHeader中的HttpWorkerRequest 。 这是一个抽象类,从看反编译库代码的实际执行取决于主机环境不同而不同。 因此,我不能看到的方式通过反射来代替以可靠的方式的用户代理字符串。 你可以推出自己的WorkerRequest类,但为的工作量,我不认为回报将是值得的。

对不起,是阴性,但我认为它只是无法设置Web应用程序中的用户代理以简单的方式。 此刻的你最好的选择是为用户代理进行预检查,如果该请求没有一个返回不支持错误消息的浏览器。

你也可以调查,如果你使用一个早前注入的东西,也就是在IIS或您的代理服务器。

此外,我建议,这个问题被报告给SAP。 我知道他们正在积极对观众的那一刻,谁知道他们会解决它,甚至添加了对Opera的支持!



Answer 2:

最近,我也面临着类似的问题和你一样。 我用一个模拟的HttpWorkerRequest克服Request.UserAgent的问题。

(假设你已经解决了自定义的HttpModule Request.Headers代理字符串)

下面是示例代码:

Friend Class MockedRequestWorker
    Inherits HttpWorkerRequest

    Private ReadOnly _BaseHttpWorkerRequest As HttpWorkerRequest
    Private ReadOnly _UserAgent As String

    Friend Sub New(ByVal base As HttpWorkerRequest, 
        ByVal UserAgent As String)
        _BaseHttpWorkerRequest = base
        _UserAgent = UserAgent
    End Sub

    Public Overrides Sub EndOfRequest()
        _BaseHttpWorkerRequest.EndOfRequest()
    End Sub

    Public Overrides Sub FlushResponse(ByVal finalFlush As Boolean)
        _BaseHttpWorkerRequest.FlushResponse(finalFlush)
    End Sub

    'Note: remember to override all other virtual functions by direct invoke functions
    'from _BaseHttpWorkerRequest, except the following function

    Public Overrides Function GetKnownRequestHeader(ByVal index As Integer) As String

        'if user is requesting the user agent value, we return the 
        'override user agent string
        If index = HttpWorkerRequest.HeaderUserAgent Then
            Return _UserAgent
        End If

        Return _BaseHttpWorkerRequest.GetKnownRequestHeader(index)
    End Function

End Class

然后,在自定义HttpApplication.BeginRequest处理程序,做到这一点

Private Sub BeginRequestHandler(ByVal sender As Object, ByVal e As EventArgs)

    Dim request As HttpRequest = HttpRequest.Current.Request
    Dim HttpRequest_wrField As FieldInfo = GetType(HttpRequest).GetField("_wr", BindingFlags.Instance Or BindingFlags.NonPublic)

    Dim ua As String = "your agent string here"
    Dim _wr As HttpWorkerRequest = HttpRequest_wrField.GetValue(request)
    Dim mock As New MockedRequestWorker(_wr, ua)

    'Replace the internal field with our mocked instance
    HttpRequest_wrField.SetValue(request, mock)

End Sub

注意:此方法仍不能取代ServerVariables用户代理值,但它应该能够解决你所需要的(和我的问题太)

希望这有助于:)



Answer 3:

protected void Application_BeginRequest(Object sender, EventArgs e) {
    const string ua = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
    Request.Headers["User-Agent"] = ua;
    var httpWorkerRequestField = Request.GetType().GetField("_wr", BindingFlags.Instance | BindingFlags.NonPublic);
    if (httpWorkerRequestField != null) {
        var httpWorkerRequest = httpWorkerRequestField.GetValue(Request);
        var knownRequestHeadersField = httpWorkerRequest.GetType().GetField("_knownRequestHeaders", BindingFlags.Instance | BindingFlags.NonPublic);
        if (knownRequestHeadersField != null) {
            string[] knownRequestHeaders = (string[])knownRequestHeadersField.GetValue(httpWorkerRequest);
            knownRequestHeaders[39] = ua;
        }
    }
}


文章来源: Can I modify the Request.Headers collection?