在 catch 块中设置时 TempData 为空,我们重新抛出

TempData is empty when set in a catch block and we rethrow

我正在使用自定义错误 (web.config) 将未处理的异常发送到我的 ErrorController

在我的主控制器中,我抛出一个异常,在 catch 块中捕获它并设置 TempData 以显示一些用户友好的消息。我然后 throw 然后发送到 ErrorController.

当我在这里检查 TempData 时,它是空的(Session 也是空的,但应该是,不是吗?)。

我确定它不应该是空的,这是在控制器之间发送数据的正确方式...但它不起作用!我是不是理解错了?

HomeController:

catch (Exception ex)
{
    TempData["MsgForUser"] = "useful message to show";
    // Do some logging...

    throw;
}

ErrorController:

public ActionResult DisplayError(int id)
{
    ViewBag.MsgForUser = TempData["MsgForUser"];
    return View();
}

Web.config:

<system.web>
  <customErrors mode="On" defaultRedirect="~/ErrorPage/DisplayError">
    <error redirect="~/Error/DisplayError/403" statusCode="403" />
    <error redirect="~/Error/DisplayError/404" statusCode="404" />
    <error redirect="~/Error/DisplayError/500" statusCode="500" />
  </customErrors>

使用 RedirectToAction() 方法时 TempData 是稳定的,在异常处理中 ASP.net 是否使用此方法?也许不吧 !! 为什么不使用 Exception.Message 设置用户友好消息?在您的 catch 块中设置 ex.Message ,然后在您的错误视图中您可以访问它。您的错误视图模型必须是 @model HandleErrorInfo ,并且 @Model.Exception.Message 已设置您的消息!

我发现会话在顶层 catch 块中执行 throw 时被销毁,因为请求错误控制器。 但是我确实发现返回的 RedirectToAction() 保留了它。

所以,我创建了自己的异常类型:

public class MyApplicationException : Exception
{
    /// <summary>
    /// A message that can be shown to the user i.e. not technical
    /// </summary>
    public string MessageForUser { get; set; }

    public MyApplicationException()
    {
    }

    public MyApplicationException(string message, string messageForUser="")
        : base(message)
    {
        MessageForUser = messageForUser;
    }

    public MyApplicationException(string message, Exception inner, string messageForUser = "")
        : base(message, inner)
    {
        MessageForUser = messageForUser;
    }
}

然后,当我遇到预期的问题并最终将用户发送到一般错误页面时,我会这样使用它:

if (MyList.Count > 14)
{
      throw new MyApplicationException("More than 14 records received: " + MyList.Count.ToString(), "There is a maximum limit of 14 records that can be processed at a time. Please call us to discuss your requirement to process in greater quantities.");
}

捕捉到它后,我为用户挑选消息,记录错误,然后 return RedirectToAction() 转到错误页面而不丢失 TempData

catch (MyApplicationException myAppEx)
{
    // If there is a user-friendly message then store it for DisplayError to show
    if (String.IsNullOrEmpty(myAppEx.MessageForUser) == false)
    {
        TempData["MsgForUser"] = myAppEx.MessageForUser;
    }

    // Do some logging to elmah or a custom logger
    util.LogError(myAppEx, "MyFunc() threw an exception", args);

    //
    // We cannot throw here because we lose the Session & TempData. we have to do a manual redirect.
    //
    return RedirectToAction("DisplayError", "ErrorPage", new { id = 500 });
}

最后在我看来,我寻找它并显示它是否存在:

<p>
    An error occurred. Please check & try again later.
</p>
@if (String.IsNullOrEmpty(ViewBag.MsgForUser) == false)
{
    <p class="more-info">Details: @ViewBag.MsgForUser</p>
}