【问题标题】:TempData is empty when set in a catch block and we rethrow在 catch 块中设置时 TempData 为空,我们重新抛出
【发布时间】:2016-09-29 03:26:11
【问题描述】:

我正在使用自定义错误 (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>

【问题讨论】:

  • @ScottWeldon 这只是我的偏好,但代码中的标题(ErrorController、Web.config)不需要在代码块中,它只是看起来有点奇怪。

标签: asp.net-mvc tempdata


【解决方案1】:

我发现在顶级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>
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 当我“抛出”时,它会重定向到错误控制器(参见上面的 web.config 代码)。两个控制器之间没有传递异常对象。
    • codeproject.com/Articles/1002109/… 中查看 Lab29,也许有用
    • 你说得对,我的解决方案不一样!
    猜你喜欢
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多