我有一个返回PartialView的Action:
[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);
}
_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 })
如果子操作本身发生异常,则忽略子操作方法的HandleErrorAttribute属性。因此,子操作应该处理自己的异常。如果子操作应用了AuthorizeAttribute属性,则该属性将执行并返回HTTP Unauthorized 401状态代码。
我无法使用此[HandleError(ExceptionType = typeof(KeyNotFoundException), View="myError")]
并且无法使用try / catch重定向,因为不支持重定向子操作。
处理子操作例外的最佳方法是什么?
Bottomline:我想处理异常并返回自定义错误页面。
答案 0 :(得分:3)
如果在GetViewModel
方法中抛出异常,那么你的return语句甚至都不会得到处理,事实上它是因为没有catch语句你最终会在Application_Error
中global.asax(如果你有一个当然)。
你是对的,你应该进行ContainsKey
检查,如果是,则返回错误页面。
只需将结果放在ContainsKey
变量中,Assert
变量为真?或者您可以查看viewModel
变量和Assert
,如果ContainsKey
为false,请确保您的错误视图名称实际上位于viewModel
。
try
catch
一般来说不是很好的做法,如果你可以避免它,你应该使用额外的逻辑防止发生异常(比如ContainsKey
实例)。例外情况适用于特殊情况:)。
答案 1 :(得分:1)
在我的情况下,我在子操作中添加了一个ModelState错误(使用自定义消息而不是Exception的消息),并将ValidationSummary放在子操作的局部视图中。由于父操作的摘要没有得到错误,因此它不会重复错误。当然,这仍然显示页面。就我而言,它非常好。
但是你要确保在儿童行动return PartialView(modelContainingPotentiallySensitiveInfo)
中没有做这样的事情。我无法想象特定的场景,但通常你指向一个完全不同的错误页面的原因是首先防止与错误相关的安全漏洞。因此,如果您使用我的技术,请确保创建一个新的空模型,即未从数据库中查询的模型,以传递给部分页面。
当然,如果在调用PartialView时发生异常,就像cshtml中的错误一样,那么就无法返回操作并显示错误。所以这不是一个完美的解决方案,但可能足以满足其他人的需求。
答案 2 :(得分: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>