Problem z ogłaszaniem zwrotnym podczas używania przepisywania adresów URL i 404.aspx

Używam przepisywania adresów URL w mojej witrynie, aby uzyskać adresy URL takie jak:
http://mysite.com/users/john
zamiast
http://mysite.com/index.aspx?user=john

Aby osiągnąć to przepisywanie bez rozszerzeń z IIS6 i bez dostępu do serwera hostingowego, używam "podejścia 404". Gdy żądanie, którego serwer nie może znaleźć, zmapowana strona 404 jest wykonywana, ponieważ jest to strona aspx, którą można przepisać (mogę ustawić mapowanie 404 za pomocą panelu sterowania w usłudze hostingowej).

To jest kod w 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;
}

A w Page_Load na mojej stronie głównej ustawiłem poprawny adres URL w atrybucie akcji w tagu formularza.

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

Przepisanie działa dobrze, ale kiedy wykonuję postback na stronie, postback nie jest wykonywany, czy można to jakoś rozwiązać?

Wydaje się, że problem dotyczy podejścia 404, ponieważ gdy próbuję bez niego (i tracę funkcję bez rozszerzenia), postback działa. Wtedy żądam:
http://mysite.com/users/john.aspx

Czy można to rozwiązać, czy jest jakieś inne rozwiązanie, które spełnia moje wymagania (IIS6, bez dostępu do serwera/filtra ISAPI i bez rozszerzeń).


person salle55    schedule 04.01.2009    source źródło


Odpowiedzi (7)


form1.Action = Request.RawUrl

w połączeniu z

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

działa bardzo dobrze dla mnie.

ustawienie formularza Atrybut akcji był elementem, którego mi brakowało...

Dzięki za rozwiązanie!!!

person Simon Rückert    schedule 08.08.2010
comment
+1. Wiem, że pytanie jest teraz dość stare, ale ta odpowiedź działa z mojego doświadczenia. Nawiasem mówiąc, ta poprawka jest konieczna za każdym razem, gdy wykonujemy ogłaszanie zwrotne w połączeniu z RewritePath; Zetknąłem się z tym podczas korzystania z funkcji urlMapping w ASP.NET 2.0, gdzie ścieżka jest przepisywana przez framework. - person harpo; 28.09.2010
comment
Jesteś legendą! Od wieków staram się znaleźć rozwiązanie tego problemu! - person Flyingkiwi; 09.06.2015

Scott Guthrie omawia różne sposoby robienia tego tutaj bez dostępu do IIS:

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

Osobiście stworzyłem HTTPModules w przeszłości i jest to dość łatwe do złożenia.

person brendan    schedule 04.01.2009
comment
Tak, przeczytałem ten artykuł ScottGu, nie sądziłem, że można uruchomić HttpModules z adresów URL bez rozszerzeń za pomocą IIS6... Zajmę się tym. - person salle55; 04.01.2009
comment
Nie wydaje się to możliwe bez ISAPI, Scott pisze: IIS 5/6 utrudnia przepisywanie adresów URL na tego typu adresach URL (bez rozszerzeń) w rozszerzeniach ISAPI (w ten sposób implementowany jest ASP.NET). Zamiast tego należy wykonać przepisywanie wcześniej w potoku żądania usług IIS za pomocą filtra ISAPI - person salle55; 04.01.2009

form1.Action = Request.RawUrl jest też tak jak to jest napisane w C# umieść to w metodzie ładowania strony

person Paul    schedule 22.02.2010

Zacząłbym od zainstalowania nagłówków HTTP na żywo i zobaczenia, co się z tym dzieje żądania HTTP.

Ahh tutaj, w tym artykule, wyjaśnia to, wygląda na to, że atrybut akcji tagu formularza jest błędny:

Jeden problem, na który ludzie często napotykają podczas korzystania z ASP.NET i przepisywania adresów URL, ma związek z obsługą scenariuszy ogłaszania zwrotnego. W szczególności, gdy umieścisz kontrolkę <form runat="server"> na stronie, ASP.NET automatycznie domyślnie wyprowadzi atrybut akcji znacznika, aby wskazać stronę, na której się znajduje. Problem podczas używania przepisywania adresów URL polega na tym, że adres URL renderowany przez kontrolkę nie jest oryginalnym adresem URL żądania (na przykład: /products/books), ale raczej przepisanym adresem (na przykład: /products.aspx?category =książki). Oznacza to, że kiedy wykonasz postback do serwera, adres URL nie będzie Twoim ładnym, czystym adresem.

W przypadku ASP.NET 1.0 i 1.1 ludzie często uciekali się do podklasowania kontrolki <form> i tworzyli własną kontrolkę, która poprawnie wyświetla akcję do użycia. Chociaż to działa, kończy się to trochę bałaganem — ponieważ oznacza to, że musisz zaktualizować wszystkie strony, aby korzystać z tej alternatywnej kontrolki formularza, i czasami mogą wystąpić problemy z projektantem Visual Studio WYSIWYG.

Dobrą wiadomością jest to, że w przypadku ASP.NET 2.0 istnieje czystsza sztuczka, której można użyć do przepisania atrybutu akcji w kontrolce <form>. W szczególności można skorzystać z nowej architektury rozszerzalności adaptera sterowania ASP.NET 2,0, aby dostosować renderowanie formantu <form> i zastąpić jego wartość atrybutu akcji podaną wartością. Nie wymaga to zmiany żadnego kodu na stronach .aspx. Zamiast tego po prostu dodaj plik .browser do folderu /app_browsers, który rejestruje klasę adaptera sterowania, która będzie używana do wyprowadzania nowego atrybutu akcji...

person Shawn    schedule 04.01.2009
comment
Nie sądzę, że akcja jest problemem, jak widać w moim kodzie, aktualizuję atrybut akcji do virtualURL przy użyciu nowej funkcji w .NET 3.5 SP1. A kiedy uruchamiam bez podejścia 404 (użyj .aspx na końcu adresu URL), ogłaszanie zwrotne działa dobrze z tym samym kodem aktualizacji akcji. - person salle55; 04.01.2009

Możesz zamiast tego użyć poniższego:

formularz1.Akcja = Żądanie.RawUrl

Nie jestem pewien, co by to było w C#, ale tak jest w VB i działa świetnie

person Richard Wallace    schedule 23.11.2009

spróbuj czegoś takiego:

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

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

Tak więc, zapisujesz prawdziwy adres URL dla ogłaszania zwrotnego w zmiennej (tutaj: _postBackUrl) podczas przepisywania adresu URL, a następnie używasz go tylko podczas ogłaszania zwrotnego.

person Toma    schedule 19.04.2010

Problem tkwi w obsłudze 404. Twój formularz jest publikowany na nieistniejącej stronie, ASP.NET przekierowuje żądanie do strony 404 i w ten sposób traci wszystkie dane ogłaszania zwrotnego.

Jedynym rozwiązaniem jest ustawienie atrybutu akcji formularza na istniejącą stronę, dzięki czemu użytkownicy będą widzieć index.aspx?user=john podczas przesyłania formularza. Dla SEO nie stanowiłoby to problemu, ponieważ roboty indeksujące nie publikują postów i dlatego nie widzą brzydkiego adresu.

person Ronald    schedule 15.05.2009