Ошибка ASP.NET Response.Redirect()

Вот мой код:

try
{
    Session["CuponeNO"] = txtCode.Text;
    txtCode.Text = string.Empty;
    Response.Redirect("~/Membership/UserRegistration.aspx");
}
catch(Exception ex)
{
   string s = ex.ToString();
   lblMessage1.Text = "Error Occured!";
}

Я получаю сообщение об ошибке, даже если оно перенаправляется после catch.

Вот ошибка:

"System.Threading.ThreadAbortException: Поток прерывался. System.Threading.Thread.AbortInternal()\г\п в System.Threading.Thread.Abort(Объект stateInfo)\r\n at System.Web.HttpResponse.End()\r\n at System.Web.HttpResponse.Redirect(String url, Boolean endResponse)\r\n at System.Web.HttpResponse.Redirect(String URL)\г\п

Может ли кто-нибудь сказать мне, почему эта ошибка происходит?

Ответ 1

Вы можете просто переместить....

Response.Redirect("~/Membership/UserRegistration.aspx");

... вне блока Try/Catch или вы можете попробовать новое решение John S. Reid:

Response.Redirect(url) ThreadAbortException Solution


Джон С. Рид
31 марта 2004 г.
(отредактировано 28 октября 2006 г., чтобы включить более подробные сведения и исправить некоторые неточности в моем анализе, хотя решение на нем ядро остается тем же самым)

... пропустить вниз...

ThreadAbortException генерируется при выполнении вызова Response.Redirect(url), поскольку система прерывает обработку текущего потока веб-страниц после отправки перенаправления на поток ответов. Response.Redirect(url) на самом деле делает вызов Response.End() внутренне, и он Response.End(), который вызывает Thread.Abort(), который пузырится вверх по стеку, чтобы завершить поток. В редких случаях вызов Response.End() на самом деле не вызывает Thread.Abort(), но вместо этого вызывает HttpApplication.CompleteRequest(). (См. Эту статью поддержки Microsoft для получения подробной информации и намек на решение.)

... пропустить вниз...

Решения PostBack и Render? Overrides.

Идея состоит в том, чтобы создать переменную уровня класса, которая указывает, должна ли страница заканчиваться, а затем проверять переменную до обработки ваших событий или отображения вашей страницы. Этот флаг должен быть установлен после вызова HttpApplication.CompleteRequest(). Вы можете поместить проверку этого значения в каждое событие PostBack или блок рендеринга, но это может быть утомительным и подверженным ошибкам, поэтому я бы рекомендовал просто переопределить методы RaisePostBackEvent и Render, как в примере кода 1 ниже

private bool m_bIsTerminating = false;

protected void Page_Load(object sender, EventArgs e)
{
    if (WeNeedToRedirect == true)
    {
        Response.Redirect(url, false);
        HttpContext.Current.ApplicationInstance.CompleteRequest();
        m_bIsTerminating = true;

        // Remember to end the method here if there is more code in it.
        return;
    }
}

protected override void RaisePostBackEvent
(
    IPostBackEventHandler sourceControl, 
    string eventArgument
)
{
    if (m_bIsTerminating == false)
    base.RaisePostBackEvent(sourceControl, eventArgument);
}

protected override void Render(HtmlTextWriter writer)
{
    if (m_bIsTerminating == false)
    base.Render(writer);
}

Заключительный анализ

Вначале я рекомендовал вам просто заменить все ваши вызовы на Response.Redirect(url) с вызовами Response.Redirect(url, false) и CompleteRequest(), но если вы хотите избежать обработки обратной передачи и рендеринга html вам также нужно будет добавить переопределения. Из моего недавнего углубленного анализа кода я вижу, что наиболее эффективным способом переадресации и завершения обработки является использование метода Response.Redirect(url) и предотвращение прерывания потока вплоть до стека, но если это исключение вызывает у вас горе, как во многих случаях, тогда решение здесь является следующим лучшим.

Следует также отметить, что метод Server.Transfer() страдает от той же проблемы, поскольку он вызывает Response.End() внутренне. Хорошей новостью является то, что ее можно решить так же, используя вышеприведенное решение и заменив вызов Response.Redirect() на Server.Execute().

1 - Я изменил форматирование кода, чтобы он соответствовал границам SO, чтобы он не прокручивался.