如何在asp.net mvc中处理'查找未找到'InvalidOperationException?

时间:2009-07-23 00:40:02

标签: c# asp.net-mvc

我有一个asp.net mvc 1.0站点,它提供来自2级层次结构的一些内容 /类别/条

当事情正常时,文章会映射到视图并呈现视图。但是,当url符合路由条件但视图不存在时,会引发异常,我无法捕获Controller操作。

路由:

routes.MapRoute(
  "Article",
  "{category}/{article}.aspx",
  new { controller = "MyController", action = "Article" }
);

MyController Action:

public ActionResult Article(string category, string article)
{
    string path = string.Format("~/Views/{0}/{1}.aspx", category, article);
    ViewResult vr = View(path);
    return vr;
}

但是,当找不到视图时,会生成System.InvalidOperationException,我无法在Controller Action中捕获。

  

异常详细信息:System.InvalidOperationException:视图   '〜/ Views / my-category / my-article-with-long-name.aspx'或其主人   无法找到。搜索了以下位置:   〜/查看/我的类别/我的-物品与 - 长name.aspx

我可以在Application_Error()中的global.asax.cs方法中捕获错误,但是:

  1. 不知道如何从那里重定向到错误视图
  2. 想知道是否有更接近异常的地方 提高。

4 个答案:

答案 0 :(得分:7)

xandy,Greg, 我感谢你的回答。这篇文章(Strategies For Resource Based 404 Errors in aspnet mvc)帮助我以一种非常干净的方式得到了我正在寻找的解决方案。我需要做的就是覆盖Controller.OnException。由于我只有一个需要行为的控制器,所以我只需在该控制器中覆盖OnException。

话虽如此,我的解决方案是治疗症状而不是疾病,正如你们所建议的那样,最好在调用此方法之前检查文件是否存在。查看路径。

以下是我用来治疗症状的代码:)

protected override void OnException(ExceptionContext filterContext)
{
    //InvalidOperationException is thrown if the path to the view
    // cannot be resolved by the viewengine
    if (filterContext.Exception is InvalidOperationException)
    {
        filterContext.ExceptionHandled = true;
        filterContext.Result = View("~/Views/Error/NotFound.aspx");
        filterContext.HttpContext.Response.StatusCode = 404;
    }

    base.OnException(filterContext);
}

我无法解决的一个问题是如何以干净的方式显示NotFound视图。它通常通过ErrorController NotFound Action访问。我不得不硬编码它的路径。我可以忍受这个,但想知道是否有可能没有HC路径。

答案 1 :(得分:3)

有一个合适的地方可以解决这个问题。如果您实现自己的ViewEngine,则可以覆盖" FileExists"方法

public class ViewEngine : RazorViewEngine
{
    protected override bool FileExists(ControllerContext context, string path)
    {
        if(!base.FileExists(context, path))
            throw new NotFoundException();

        return true;
    }

}

您只需要在Global.asax中注册视图引擎,就像这样,

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new ViewEngine());

在Application_Error中,您可以实现捕获NotFoundExceptions的处理程序,记录它们,然后通过执行ErrorController返回友好消息。

答案 2 :(得分:0)

我认为检查视图是否存在的最佳位置是在控制器内。如果封装视图的构造函数不起作用,则可能是ASP.net推迟构造函数外部的View实例化(不确定是否)。

但您可能尝试的一件事是手动检查并查看路径是否存在,使用Server.MapPath()获取绝对文件路径并检查它是否存在。

答案 3 :(得分:0)

我只会返回默认视图,也许404响应是合适的。当然要做到这一点,你需要稍微改变你的架构。

AFAIK您需要有一些代码来检查文件是否存在,如果您不想要默认的框架行为,就像在ASPX文件中一样。您可能应该使用ResolveURL or Url.Content来解析应用程序路径中的路径。

作为一个注释,通常情况下,将您的域名(文件名)暴露给世界并不完全安全。如果ASPX只是数据,那么您应该将文本放入数据库或普通的非可执行文本文件中。如果您正在构建某种CMS(即,您真的想要一种“安装”功能),那么您可以考虑使用ASPX视图来包含部分视图以封装ASP.NET代码块。

至于进入404页面,this answer可能有所帮助。