Проблема с обратной передачей при использовании URL Rewrite и 404.aspx

Я использую перезапись URL-адресов на своем сайте, чтобы получить такие URL-адреса:
http://mysite.com/users/john
вместо
http://mysite.com/index.aspx?user=john

Чтобы добиться этой перезаписи без расширений с помощью IIS6 и без доступа к серверу хостинга, я использую «404-подход». Когда запрос, который сервер не может найти, выполняется сопоставленная 404-страница, поскольку это aspx-страница, перезапись может быть выполнена (я могу настроить 404-сопоставление с помощью панели управления на хостинг-сервисе).

Это код в Global.asax:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    string url = HttpContext.Current.Request.Url.AbsolutePath;
    if (url.Contains("404.aspx"))
    {
        string[] urlInfo404 = Request.Url.Query.ToString().Split(';');
        if (urlInfo404.Length > 1)
        {
            string requestURL = urlInfo404[1];
            if (requestURL.Contains("/users/"))
            {
                HttpContext.Current.RewritePath("~/index.aspx?user=" + GetPageID(requestURL));              
                StoreRequestURL(requestURL);
            }
            else if (requestURL.Contains("/picture/"))
            {
                HttpContext.Current.RewritePath("~/showPicture.aspx?pictureID=" + GetPageID(requestURL));
                StoreRequestURL(requestURL);
            }
        }
    }
}

private void StoreRequestURL(string url)
{
    url = url.Replace("http://", "");
    url = url.Substring(url.IndexOf("/"));
    HttpContext.Current.Items["VirtualUrl"] = url;
}

private string GetPageID(string requestURL)
{
    int idx = requestURL.LastIndexOf("/");
    string id = requestURL.Substring(idx + 1);
    id = id.Replace(".aspx", ""); //Only needed when testing without the 404-approach
    return id;
}

И в Page_Load на моей главной странице я установил правильный URL-адрес в атрибуте действия в теге формы.

protected void Page_Load(object sender, EventArgs e)
{
    string virtualURL = (string)HttpContext.Current.Items["VirtualUrl"];
    if (!String.IsNullOrEmpty(virtualURL))
    {
        form1.Action = virtualURL;
    }
}

Перезапись работает нормально, но когда я выполняю обратную передачу на странице, обратная передача не выполняется, можно ли это как-то решить?

Проблема, похоже, связана с подходом 404, потому что, когда я пытаюсь без него (и теряю функцию без расширения), обратная передача работает. Именно тогда я запрашиваю:
http://mysite.com/users/john.aspx

Можно ли это решить или есть какое-либо другое решение, которое удовлетворяет моим требованиям (IIS6, без serveraccess / ISAPI-filter и без расширений).


person salle55    schedule 04.01.2009    source источник


Ответы (7)


form1.Action = Request.RawUrl

в комбинации с

HttpContext.Current.RewritePath("/Default.aspx", true); 

у меня очень хорошо работает.

установка атрибута действия формы была той частью, которую я отсутствовал ...

Спасибо за решение !!!

person Simon Rückert    schedule 08.08.2010
comment
+1. Я знаю, что вопрос довольно старый, но, судя по моему опыту, этот ответ работает. Между прочим, это исправление необходимо каждый раз при выполнении обратной передачи в сочетании с RewritePath; Я столкнулся с этим при использовании функции urlMapping в ASP.NET 2.0, когда путь переписывается фреймворком. - person harpo; 28.09.2010
comment
Вы легенда! Я пытался найти решение этой проблемы целую вечность! - person Flyingkiwi; 09.06.2015

Скотт Гатри описывает различные способы сделать это здесь без доступа к IIS:

http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx

Лично я создавал HTTPModules в прошлом, и их довольно легко собрать.

person brendan    schedule 04.01.2009
comment
Да, я читал эту статью ScottGu, не думал, что вы можете заставить HttpModules выполнять из URL-адресов без расширений с использованием IIS6 ... Я изучу это. - person salle55; 04.01.2009
comment
Скотт пишет, что это невозможно без ISAPI: IIS 5/6 затрудняет выполнение перезаписи URL-адресов для этих типов URL-адресов (без расширений) в рамках расширений ISAPI (именно так реализован ASP.NET). Вместо этого вам нужно выполнить перезапись ранее в конвейере запросов IIS с помощью фильтра ISAPI. - person salle55; 04.01.2009

form1.Action = Request.RawUrl - это также то, как он написан на C #, поместите его в метод загрузки страницы

person Paul    schedule 22.02.2010

Я бы начал с установки Live Http Headers и посмотрел, что происходит HTTP-запросы.

Ах, здесь, в этой статье, это объясняется, похоже, что атрибут действия тега формы неправильный:

Одна проблема, с которой люди часто сталкиваются при использовании ASP.NET и URL-Rewriting, связана с обработкой сценариев обратной передачи. В частности, когда вы размещаете элемент управления <form runat="server"> на странице, ASP.NET автоматически по умолчанию выводит атрибут действия разметки, указывающий обратно на страницу, на которой он находится. Проблема при использовании URL-Rewriting заключается в том, что URL-адрес, отображаемый элементом управления, не является исходным URL-адресом запроса (например: / products / books), а скорее переписанным (например: /products.aspx?category) = книги). Это означает, что когда вы выполняете обратную передачу на сервер, URL-адрес не будет вашим хорошим чистым.

В ASP.NET 1.0 и 1.1 люди часто прибегали к подклассу элемента управления <form> и создавали свой собственный элемент управления, который правильно выводил действие для использования. Хотя это работает, в итоге получается немного беспорядка - так как это означает, что вам нужно обновить все свои страницы, чтобы использовать этот альтернативный элемент управления формой, и иногда могут возникать проблемы с дизайнером Visual Studio WYSIWYG.

Хорошая новость заключается в том, что в ASP.NET 2.0 есть более чистый прием, который можно использовать для перезаписи атрибута действия в элементе управления <form>. В частности, вы можете воспользоваться преимуществами новой архитектуры расширяемости адаптера управления ASP.NET 2.0, чтобы настроить отображение элемента управления <form> и переопределить значение его атрибута действия указанным вами значением. Это не требует от вас изменения кода на ваших страницах .aspx. Вместо этого просто добавьте файл .browser в папку / app_browsers, который регистрирует класс адаптера управления, который будет использоваться для вывода нового атрибута действия ...

person Shawn    schedule 04.01.2009
comment
Я не думаю, что проблема заключается в действии, поскольку в моем коде вы можете видеть, что я обновляю атрибут действия для virtualURL, используя новую функцию в .NET 3.5 SP1. И когда я работаю без подхода 404 (используйте .aspx в конце URL-адреса), обратная передача отлично работает с тем же кодом обновления действия. - person salle55; 04.01.2009

Вместо этого вы можете просто использовать следующее:

form1.Action = Request.RawUrl

Я не уверен, что это было бы в C #, но это то, что есть в VB, и это работает.

person Richard Wallace    schedule 23.11.2009

попробуйте что-нибудь вроде этого:

            if (Request.HttpMethod == "GET" && shouldChangeUrl)
            {
                urlRedirect = "REAL-URL-HERE";

                _postBackUrl = urlRedirect;
                Context.RewritePath(urlRedirect);
            }
            else
                //If Post Back (Request.HttpMethod="POST")
                Context.RewritePath(_postBackUrl);

Таким образом, вы сохраняете реальный URL-адрес для обратной передачи в переменной (здесь: _postBackUrl) при перезаписи URL-адреса, а затем используете ее только при обратной передаче.

person Toma    schedule 19.04.2010

Проблема в обработке 404. Ваша форма отправляется на несуществующую страницу, ASP.NET перенаправляет запрос на страницу 404 и поэтому теряет все данные обратной передачи.

Единственное решение - установить атрибут действия формы для существующей страницы, чтобы пользователи видели index.aspx? User = john при отправке формы. Для SEO это не будет проблемой, поскольку сканеры не публикуют сообщения и, следовательно, не видят уродливый адрес.

person Ronald    schedule 15.05.2009