Почему HttpWorkerRequest терпит неудачу во время HttpRuntime.ProcessRequest после a.NET 2.0 to.NET обновление 4.0?

Я обновляю наше приложение, которое имеет внутренний веб-сервер, с .NET 2.0 до .NET 4.0.

я обрабатываю запрос с объектом HttpListenerWorkerRequest, который расширяет HttpWorkerRequest класса, и создает запрос, который GetRawUrl() возвращает URL-адрес в формате http://localhost:82/Default.aspx.

в .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), он отлично строит, post-update (.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, чтобы вызвать это, и что я могу сделать, чтобы обойти это?

редактировать я только что заметил, что за запрещенным http: следует одна косая черта, а не двойная, хотя GetRawUrl() в запросе, безусловно, возвращает double.

2 ответов


я не 100% уверен, что это точный ответ, но выглядит довольно близко ко мне - и есть еще кое-что написать...

кажется breaking change рода внутри VirtualPath класс-и это подтверждается тем, как они проверяют illegal characters. (кстати. вы можете google "источник VirtualPath" для того, что кажется версией .NET 4).

внутри VirtualPath.Create проверка вызывается для "незаконных символов виртуального пути".

это первый заходит в реестр ("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET", "VerificationCompatibility") - чтобы увидеть, если compatibility следует использовать режим "незаконные символы".

основываясь на этом-я предполагаю (у меня нет способа проверить это прямо сейчас) - это если вы установите вышеуказанное значение реестра (int) в 1 - вы должны заставить свои методы работать the old way и W/O любой дополнительное усилие. Примечание: в IIS (или хост-процесс) перезагрузка может потребоваться как указано в одной из ссылок

а затем на основе этого флага реестра он использовал любой из этих двух...

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

это, кажется, на самом деле описывает вашу историю довольно хорошо, так как ваш путь с обозначением "порт" на самом деле illegal по новому умолчанию.


ОКОНЧАТЕЛЬНОЕ РЕДАКТИРОВАНИЕ / ОБЪЯСНЕНИЕ:

(обновление на основе комментариев и решения, которое решено)
Вот мое понимание того, что происходит внутри:--21-->

1) решение для до .NET 4.0 было VerificationCompatibility ключ (см. выше).

2) с .NET 4.0 внутренняя обработка и фиксация url-путей сделаны более надежными. И работает отлично в большинстве случаев. Короче говоря,все пути фиксированы и нормализованы перед входом the VirtualPath.Create - и ваш http://... становится ожидаемым абсолютным путем /Default.aspx.

однако, когда вы поставляете HttpWorkerRequest (вместо запроса / ответа и т. д.)- the 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 filename = плохой запрос

настройте IIS для приема URL-адреса со специальными символами...

для 32 против 64 разница в реестре

и вот аналогичная вещь от Microsoft-но то, что кажется "исправление" для "2.0", т. е. не относится к вам, но просто прикрепляет его как нечто официальное в этой строке.

исправить: сообщение об ошибке" HTTP 400 - плохой запрос " в .NET Framework 1.1
FIX: сообщение об ошибке при попытке посетить ASP.NET веб-страница на основе 2.0: "HttpException (0x80004005): '/HandlerTest/WebForm1.aspx/a:b 'не является допустимым виртуальным путем"
ASP.NET 2.0 x64 – вы можете получить http 400 плохой запрос или ошибку, как указано в КБ 932552 или 826437

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET

Имя Значения 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. Это работать на тебя?