3

我有一个返回 PartialView 的操作:

[ChildActionOnly]
public ActionResult TabInfo(int id, string tab)
{

    ViewBag.Jobid = id;
    ViewBag.Tab = tab;

    var viewModel = _viewModelManager.GetViewModel(tab, id);

    return 
        PartialView(string.Format("~/Views/{0}/Index.cshtml", tab), viewModel);

}

从 Dictionary中_viewModelManager返回一个视图。如果用户请求一个不存在的选项卡,KeyNotFound则会引发异常,但是,在我看来,我得到以下异常:

Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'

@using MyApplication.UI.Helpers.Html
@model MyApplication.UI.Models.MyJobModel

@{
    ViewBag.Title = "Details";
}

<p>@Model.Blah</p>

...

*@ HttpException occurs here -- renders default error view *@
@Html.Action("TabInfo", new { id = ViewBag.Jobid, tab = ViewBag.Tab }) 

根据 MS...

如果子操作本身发生异常,则忽略子操作方法上的 HandleErrorAttribute 属性。因此,子动作应该处理自己的异常。如果子操作应用了 AuthorizeAttribute 属性,则该属性将执行并返回 HTTP Unauthorized 401 状态代码。

我不能使用它[HandleError(ExceptionType = typeof(KeyNotFoundException), View="myError")],也不能使用 try/catch 重定向,因为不支持子操作的重定向。

处理子操作异常的最佳方法是什么?

底线:我想处理异常并返回自定义错误页面。

4

3 回答 3

3
  1. 如果在方法中抛出异常,GetViewModel那么您的 return 语句甚至不会得到处理,实际上它因为没有 catch 语句,您最终会Application_Error在 global.asax 中(如果有的话)。

  2. 你是对的,你应该做一个ContainsKey检查,然后如果它是错误的,则返回你的错误页面。

  3. 只需将结果放在ContainsKey变量中并且Assert该变量为真?或者您可以检查viewModel变量Assert,如果ContainsKey为假,则确保您的错误视图名称实际上在viewModel.

一般来说, Atry catch并不是一个很好的实践,如果你可以避免它,你应该使用额外的逻辑来防止异常发生(比如ContainsKey在这个例子中)。例外情况是特殊情况:)。

于 2012-05-25T18:51:10.873 回答
1

在我的例子中,我在子操作中添加了一个 ModelState 错误(使用自定义消息而不是异常的消息),并将 ValidationSummary 放在子操作的部分视图中。由于父操作的摘要没有得到错误,因此它不会重复错误。当然这仍然显示页面。就我而言,这非常好。

但是你要确保你没有在 child action 中做这样的事情return PartialView(modelContainingPotentiallySensitiveInfo)。我无法想象具体的场景,但通常你指向一个完全不同的错误页面的原因是首先防止与错误相关的安全漏洞。因此,如果您使用我的技术,请确保创建一个新的空模型,该模型尚未从数据库中查询,以传递到部分页面。

当然,如果调用 PartialView 时出现异常,比如 cshtml 中的错误,那么您就无法返回操作并显示错误。所以这不是一个完美的解决方案,但对其他人来说可能就足够了。

于 2012-11-14T18:09:15.800 回答
0

以防其他人遇到这个问题。

我最终使用 try/catch 块来捕获 KeyNotFound 异常。我记录错误,然后将用户重定向到 ErrorView。在错误视图中,我使用 javascript 将用户重定向到适当的视图。

[ChildActionOnly]
    public ActionResult TabInfo(int id, string tab, string jobno)
    {
        try
        {
            var viewModel = _viewModelManager.GetViewModel(tab, id);

            ViewBag.Jobid = id;
            ViewBag.Tab = tab;

            return PartialView(string.Format("~/Views/{0}/Index.cshtml", tab), viewModel);
        }
        catch (Exception ex)
        {
            return View("Error");
        }

    }

错误视图

@model System.Web.Mvc.HandleErrorInfo

@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <script type="text/javascript">
        window.location.href = '@Url.Content("~/400.htm")';
    </script>
</body>
</html>
于 2012-11-14T22:10:27.450 回答