Gdy używam Response.Redirect (...) do przekierowania formularza na nową stronę, pojawia się błąd:
Wystąpił wyjątek pierwszej szansy typu „System.Threading.ThreadAbortException” w mscorlib.dll
Wyjątek typu „System.Threading.ThreadAbortException” wystąpił w mscorlib.dll, ale nie został obsłużony w kodzie użytkownika
Rozumiem to, że błąd jest spowodowany przez serwer internetowy przerywający pozostałą część strony, w której wywołano odpowiedź.redirect.
Wiem, że mogę dodać do tego drugi parametr o Response.Redirect
nazwie endResponse. Jeśli ustawię parametr endResponse na wartość True, nadal pojawia się błąd, ale jeśli ustawię wartość False, nie otrzymam. Jestem jednak całkiem pewien, że oznacza to, że serwer internetowy wyświetla resztę strony, z której przekierowałem. Co wydaje się co najmniej nieefektywne. Czy jest na to lepszy sposób? Coś innego niż Response.Redirect
lub czy istnieje sposób, aby zmusić starą stronę do zaprzestania ładowania tam, gdzie jej nie dostanę ThreadAbortException
?
Context.ApplicationInstance.CompleteRequest();
. Czemu? Czy będę musiałreturn
warunkowo skorzystać z modułu obsługi zdarzeń?The old version of Redirect
frazę, której używasz w komentarzu, to nie tak, że MS zmieniło implementację, to tylko kolejne przeciążenie.W ASP.Net WebForms nie ma prostego i eleganckiego rozwiązania tego
Redirect
problemu. Możesz wybierać między brudnym rozwiązaniem a żmudnym rozwiązaniemBrudny :
Response.Redirect(url)
wysyła przekierowanie do przeglądarki, a następnie wyrzuca a,ThreadAbortedException
aby zakończyć bieżący wątek. Zatem żaden kod nie jest wykonywany po wywołaniu Redirect (). Wady: to zła praktyka i mieć wpływ na wydajność, aby zabijać takie wątki. PonadtoThreadAbortedExceptions
pojawi się w logowaniu wyjątków.Nużący : Zalecanym sposobem jest wywołanie,
Response.Redirect(url, false)
a następnieContext.ApplicationInstance.CompleteRequest()
wykonanie kodu będzie kontynuowane, a pozostałe procedury obsługi zdarzeń w cyklu życia strony będą nadal wykonywane. (Np. Jeśli wykonasz przekierowanie w Page_Load, nie tylko reszta programu obsługi zostanie wykonana, Page_PreRender itd. Nadal będzie wywoływana - renderowana strona po prostu nie zostanie wysłana do przeglądarki. Możesz uniknąć dodatkowego przetwarzania przez np. ustawiając flagę na stronie, a następnie pozwól kolejnym programom obsługi zdarzeń sprawdzić tę flagę przed rozpoczęciem przetwarzania.(Dokumentacja
CompleteRequest
stwierdza, że „ powoduje, że ASP.NET pomija wszystkie zdarzenia i filtruje w łańcuchu wykonawczym potoku HTTP ”. Można to łatwo zrozumieć. Pomija kolejne filtry i moduły HTTP, ale nie pomija dalszych zdarzeń w bieżącym cyklu życia strony ).Głębszy problem polega na tym, że WebFormom brakuje poziomu abstrakcji. Gdy jesteś w module obsługi zdarzeń, jesteś już w trakcie tworzenia strony do wydrukowania. Przekierowywanie w module obsługi zdarzeń jest brzydkie, ponieważ kończysz częściowo wygenerowaną stronę w celu wygenerowania innej strony. MVC nie ma tego problemu, ponieważ przepływ sterowania jest oddzielny od renderowania widoków, więc możesz zrobić czyste przekierowanie po prostu zwracając
RedirectAction
w kontrolerze, bez generowania widoku.źródło
Wiem, że się spóźniam, ale kiedykolwiek miałem ten błąd, jeśli mój
Response.Redirect
jest wTry...Catch
bloku.Nigdy nie umieszczaj Response.Redirect w bloku Try ... Catch. To zła praktyka
Edytować
W odpowiedzi na komentarz @ Kiquenet, oto co zrobiłbym jako alternatywę dla umieszczenia Response.Redirect w bloku Try ... Catch.
Podzielę metodę / funkcję na dwa etapy.
Krok pierwszy w bloku Try ... Catch wykonuje żądane akcje i ustawia wartość „wynik”, aby wskazać powodzenie lub niepowodzenie akcji.
Krok drugi poza blokiem Try ... Catch dokonuje przekierowania (lub nie) w zależności od wartości „wynik”.
Ten kod jest daleki od ideału i prawdopodobnie nie powinien być kopiowany, ponieważ go nie testowałem
źródło
Response.Redirect()
zgłasza wyjątek, aby przerwać bieżące żądanie.To artykule bazy wiedzy opisano to zachowanie (także dla metod
Request.End()
iServer.Transfer()
).Dla
Response.Redirect()
istnieje przeciążenie:Jeśli podasz parametr endResponse = false , wyjątek nie zostanie zgłoszony (ale środowisko wykonawcze będzie kontynuowało przetwarzanie bieżącego żądania).
Jeśli endResponse = true (lub jeśli używane jest inne przeciążenie), wyjątek zostanie zgłoszony i bieżące żądanie zostanie natychmiast zakończone.
źródło
Oto oficjalne zdanie na temat problemu (nie mogłem znaleźć najnowszego, ale nie sądzę, że sytuacja uległa zmianie w późniejszych wersjach .net)
źródło
I think that links are fantastic, but they should never be the only piece of information in your answer.
Właśnie tak
Response.Redirect(url, true)
działa. RzucaThreadAbortException
by przerwać wątek. Zignoruj ten wyjątek. (Zakładam, że jest to globalny moduł obsługi / rejestrowania błędów, w którym go widzisz?)Ciekawa powiązana dyskusja Czy jest
Response.End()
uważana za szkodliwą? .źródło
Próbowałem też innego rozwiązania, ale część kodu została wykonana po przekierowaniu.
Więc jeśli chcesz zapobiec wykonaniu kodu po przekierowaniu
źródło
nawet próbowałem tego uniknąć, na wszelki wypadek ręcznie przerywając wątek, ale raczej zostawiam to z „CompleteRequest” i kontynuuję - mój kod i tak zwraca polecenia po przekierowaniach. Można to zrobić
źródło
To, co robię, to złapanie tego wyjątku wraz z innymi możliwymi wyjątkami. Mam nadzieję, że komuś to pomoże.
źródło
Też miałem ten problem.
Spróbuj użyć
Server.Transfer
zamiastResponse.Redirect
Pracował dla mnie.
źródło