为什么HttpWorkerRequest在HttpRuntime期间失败?在.net 2.0到.net 4.0升级之后



我正在升级我们的应用程序,它有一个内部web服务器,从。net 2.0到。net 4.0。

我正在处理一个对象HttpListenerWorkerRequest的请求,它扩展了HttpWorkerRequest类,并创建了一个请求,其中GetRawUrl()返回http://localhost:82/Default.aspx格式的Url。

在。net 2.0中,将此发送到HttpRuntime.ProcessRequest(httpListenerWorkerRequest)没有问题,但是在。net 4.0中,我得到一个网页,上面只有文本"错误请求"。

打开HttpRuntime,我可以看到从ProcessRequestInternal(HttpWorkerRequest wr)抛出的错误请求,这是一个试图构建HttpContext的私有方法。

我自己试过了:

try
{
    //what's going on?
    hcontext = new HttpContext(workerRequest);
}
catch(Exception e)
{
    //Debugging break point here
}

Pre-update(。. NET 2.0),它构建良好,更新后(。. NET 4.0),我得到了一个系统。ArgumentException声明

The relative virtual path 'http:/localhost:82/Default.aspx' is not allowed here,抛出

at System.Web.VirtualPath.Create(String virtualPath, VirtualPathOptions options)
   at System.Web.HttpRequest.get_ClientFilePath()
   at System.Web.Security.CookielessHelperClass.RemoveCookielessValuesFromPath()
   at System.Web.HttpContext.Init(HttpRequest request, HttpResponse response)
   at System.Web.HttpContext..ctor(HttpWorkerRequest wr)
   at Talcasoft.Web.Hosting.HttpWorkerThread.Run(Object request) in      
   C:[OurLibrary].WebHostingHttpWorkerThread.cs:line 51

.NET中发生了什么变化导致了这个问题,我能做些什么来解决这个问题?

EDIT我刚刚注意到,不允许的http:后面跟着一个斜杠,而不是双精度,尽管请求中的GetRawUrl()肯定返回双精度。

我不是100%确定这是"确切的答案",但看起来很接近我-还有一些要写…

似乎在VirtualPath类中有一种breaking change -并且它证实了他们如何检查illegal characters。(顺便说一句。你可以谷歌一下"VirtualPath源代码",它似乎是。net 4版本)。

VirtualPath.Create内部调用了一个检查'非法虚拟路径字符'。

它首先进入注册表("HKEY_LOCAL_MACHINESOFTWAREMicrosoftASP")。. NET", "VerificationCompatibility") -查看是否应该使用compatibility模式的'非法字符'。

基于此,我猜(我没有办法检查这个)如果您将上述注册表值(int)设置为1 -,则你应该让你的方法工作the old way 和w/o任何额外的努力。注意:可能需要重新启动IIS(或主机进程),如其中一个链接

所示。

然后根据注册表标志,它使用了这两个…

':', '?', '*', '' // .NET 4.0 - the default
'' // the 'compatibility' mode  

这似乎很好地描述了你的故事,因为你的路径与'port'指定实际上是illegal


最终编辑/解释:

(基于注释和解决方案更新)
这是我对里面发生的事情的理解:

1) . net 4.0之前的解决方案是VerificationCompatibility密钥(见上文)。

在。net 4.0中,url路径的内部处理和修复变得更加健壮。在大多数情况下都很有效。简而言之,在输入 VirtualPath.Create之前,所有路径都是固定和规范化的-并且您的http://...成为预期的绝对路径/Default.aspx

然而,当您提供HttpWorkerRequest(而不是请求/响应等)时,raw Url直接从worker - 中获取,并且提供正确和规范化路径的责任取决于您的工作请求。(这仍然有点不确定,看起来像是一个错误或内部处理不当)。

重现问题:

internal class MyRequest : SimpleWorkerRequest
{
    public MyRequest() : base("", "", String.Empty, String.Empty, null) { }
    public override String GetRawUrl() { return "http://localhost:82/Default.aspx"; }
}
// ...
var wr = new MyRequest();
var context1 = new HttpContext(wr);

给出错误The relative virtual path 'http:/localhost:82/Default.aspx' is not allowed here.

修复:

public override String GetRawUrl() 
{ return new Uri(url, UriKind.RelativeOrAbsolute).AbsolutePath; }


一些关于这个主题的研究基于注册表中的VerificationCompatibility关键字这似乎是它的关键。

URL文件名=错误请求

配置IIS接受带有特殊字符的URL

在注册表

这是一个类似的东西从微软-但似乎是一个'hotfix'的'2.0',也就是说,并不适用于你-但只是附加它作为官方的东西在这一行。

修复。net Framework 1.1中的"HTTP 400 - Bad request"错误信息
修复:当你试图访问ASP时出现错误信息。基于。NET 2.0的Web页面:"HttpException (0x80004005): '/HandlerTest/WebForm1. "Aspx/a:b'不是有效的虚拟路径"
ASP。. NET 2.0 x64 -您可能会收到KB 932552或826437中提到的HTTP 400错误请求或错误

HKEY_LOCAL_MACHINE 微软软件 ASP。净

DWord值名称:VerificationCompatibility值数据:1

以下是我的看法。它仍然包含一些猜测,但我将包括一个测试,你可以证明或反驳这个假设。

堆栈跟踪显示ClientFilePath.get是异常的起源。它看起来像这样:

    if (this._clientFilePath == null)
    {
        string rawUrl = this.RawUrl;
        int index = rawUrl.IndexOf('?');
        if (index > -1)
        {
            rawUrl = rawUrl.Substring(0, index);
        }
        this._clientFilePath
     = VirtualPath.Create(rawUrl, VirtualPathOptions.AllowAbsolutePath); //here!
    }
    return this._clientFilePath;

它创建一个VirtualPath并且只允许绝对值。http://localhost:82/Default.aspx是一个相对路径,因为它不以斜杠开头。在这个上下文中,不是 URL,因为它没有被这样解释。

因此VirtualPath.Create可以理解地拒绝这条路径。我不知道为什么。net 2.0允许这样做,但是。net 4.0需要一个绝对路径,根据代码,这是不可配置的。

实际上,我以前从未见过HttpRequest.RawUrl返回URL。根据我的经验,它应该返回一个绝对路径,如/Default.aspx。如果你想设置主机和端口,你必须找到其他方法。

所以修复是不使用http://localhost:82/Default.aspx,但/Default.aspx。这样行吗?

最新更新