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

时间:2015-08-19 15:58:37

标签: asp.net-mvc tempdata

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

2 个答案:

答案 0 :(得分:1)

我发现会话在顶级throw块中执行catch时被销毁,因为对错误控制器的请求。 但是我确实发现返回的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>
}

答案 1 :(得分:0)

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