问题 如何捕获MVC视图的异常?


在控制器中,尝试... catch可以捕获异常。如何捕获异常?例如,视图可能包含以下代码:

<%= Html.Encode(Model.MyID)%>

如果Model为null,则在访问视图时将出现异常。在哪里捕获异常并将用户重定向到错误页面,并提供用户友好的错误消息?


7040
2017-07-02 14:02


起源

你使用的是哪种技术? - John Topley
MS ASP.NET MVC框架 - KentZhou
我不会将异常用于非异常行为,并且绝对不在视图中。 - Paco
这是Orchard模块视图的解决方案: stackoverflow.com/a/29536117/3936440 - ViRuSTriNiTy


答案:


只需将[HandleError]属性添加到Controller类的顶部即可。这样,将处理由Controller生成的任何异常,并向用户显示/Views/Shared/Error.aspx。传递给该视图的模型是System.Web.Mvc.HandleErrorInfo对象。

控制器:

[HandleError]
public class MyController : Controller
{
  public ActionResult Default()
  {
    MyClass thing = MyClassFactory.Create();
    return View(thing);
  }
}

这是一个“最后的手段”异常处理。大卫的回答最适合你能提前想到的那些案例。


4
2017-07-02 14:24





考虑使用Elmah: http://code.google.com/p/elmah/


2
2017-07-02 15:05





虽然我支持David Liddle的回答(“这个逻辑应该在你的Controller中而不是View中处理”),但我也可以告诉你,你应该在一般情况下进行防御性编码。

例如,而不是

try
{
    Html.Encode(Model.MyID)
}
catch
{
    Response.Redirect("~/Error/500");
}

你应该

if (Model == null)
{
    // ...
}
else
{
    //.....
}

(当然,再次,不要在视图中放置视图选择逻辑)


2
2017-08-18 06:44



我必须添加 @ 之前 if 和 else? - Dylan Czenski


好吧,你不能总是捕获控制器中的每个错误,但希望你的视图应该足够轻量级,而且不太可能发生。

但是,如果视图中出现异常,则应设置自定义500错误页面以将用户重定向到以防万一。我相信您可以在Global.asax中设置这样的重定向,也可以是IIS设置。


1
2017-07-02 14:12





此逻辑应在Controller内处理,而不是View。例如,如果您尝试查看不存在MyID的产品,则重定向到错误页面。

如果发生错误,您还可以重定向到InvalidProduct视图,该视图将提供更详细的错误说明/说明。

编辑:除了下面的人们注释以捕获未处理的异常之外,还要在ActionResult方法声明或Controller上添加[HandleError]属性(对于所有ActionResults)。

[HandleError]
public ProductsController
{
    public ActionResult Show(int id)
    {
        Product p = //e.g. get product from db

        if (p == null)
        {
            return RedirectToAction("Error");
            //return RedirectToAction("InvalidProduct");
        }

        return View(p);
    }

1
2017-07-02 14:10



如果您不知道有异常/错误,会发生什么? - Matthew Groves
您的应用程序应“快速失败”。无论如何,您无法处理您不知道的异常。 - jlembke
这不是OP问题的答案。当然最好在控制器中使用这种逻辑,但这仍然不是答案。我正在客户端进行现场原型制作,上传文件大约需要15分钟。可以在记事本中编辑视图,但是要编辑控制器,我必须在我的机器上重新编译并上传二进制文件。所以我正在使用Views来尝试一些东西。但是我看不到异常,因为它们被我和服务器之间的某些代理隐藏了,并且它们没有出现在日志中。仍在寻找解决方案。 - cheeesus


您可以在视图中的脚本块中使用try / catch:

@try
{    
  <div>typical Razor view stuff here...</div>
}
catch (Exception ex)
{
  @<script type="text/javascript">
    alert('@ex.Message.Replace("'","\\'").Replace("\r\n","<br/>")');
  </script>
}

1
2018-05-23 17:07



谢谢。这确实帮助我们快速解决了生产问题。我改变你的代码的是做一个console.log而不是alert,我把整个“ex”对象记录为JSON,这样我就可以查看“ex”的所有内部对象。以下是我在脚本中使用的内容:console.log('@ Newtonsoft.Json.JsonConvert.SerializeObject(ex)'); - user2272865


我同意Matthew Groves的说法,你不能总是抓住每一个错误。不幸的是,在我的情况下,我有一个视图,有100个变量。很难说明所有这些。

这里有多种方法可以捕获错误: http://www.codeproject.com/Articles/850062/Exception-handling-in-ASP-NET-MVC-methods-explaine

就我而言,我想用控制器中使用的数据记录视图中出现的错误。所以我选择在我的控制器中覆盖OnException。这样,在操作期间,我可以将我的数据存储在控制器实例上,然后在OnException方法中访问它。


1
2017-08-15 00:55