【问题标题】:How to properly handle child action exceptions如何正确处理子动作异常
【发布时间】:2012-06-01 08:28:52
【问题描述】:

我有一个返回 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 }) 

According to MS...

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

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

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

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

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-3 razor error-handling


    【解决方案1】:
      1234563如果你当然有的话)。
    1. 你是对的,你应该做一个ContainsKey 检查,如果它是错误的,返回你的错误页面。

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

    trycatch 并不是一般意义上的好习惯,如果你能避免它,你应该使用额外的逻辑来防止异常发生(比如ContainsKey 在这种情况下)。 例外情况除外:)。

    【讨论】:

    • 这个方法返回一个我创建的基本类型的视图模型,所以我不能返回一个视图——我想我必须自己抛出错误并让 HandleError 属性小心。知道为什么 HandleError 属性没有返回我的自定义错误视图吗?
    • 啊好吧,HandleError 不是在本地返回吗?默认情况下,HandleError 在本地开发服务器下运行时什么都不做。目的是向开发人员展示更多有用的信息
    • +1 查看并提供答案。您能否确认我的问题的更新并更新您的答案,或者让我知道如何进一步排除故障?
    • @Rich 没问题,你为什么不改变你的HandleError 属性以采用基本Exception (ExceptionType = typeof(Exception)。您的属性未捕获 HttpException,因为它当前配置为仅处理 KeyNotFoundException
    • 那也没用。视图中的 Http Exception 不断冒泡并导致显示 mvc 模板错误视图。还有其他建议吗?
    【解决方案2】:

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

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

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

    【讨论】:

    • 谢谢。我已经忘记了这个。我用我最终使用的解决方法提供了我自己的答案。
    【解决方案3】:

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

    我最终使用 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-29
      • 2021-05-22
      • 1970-01-01
      • 2016-12-30
      • 1970-01-01
      • 2016-08-21
      • 2023-03-07
      • 2021-01-20
      相关资源
      最近更新 更多