【问题标题】:How to handle 'View not found' InvalidOperationException in asp.net mvc?如何在 asp.net mvc 中处理“未找到视图”InvalidOperationException?
【发布时间】:2010-11-13 05:32:34
【问题描述】:

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

当一切正常时,文章会映射到视图并呈现视图。但是,当 url 满足路由条件但视图不存在时,会引发我无法在 Controller 操作中捕获的异常。

路由:

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

MyController 动作:

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' 或其主人 找不到。搜索了以下位置: ~/Views/my-category/my-article-with-long-name.aspx

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

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

【问题讨论】:

    标签: c# asp.net-mvc


    【解决方案1】:

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

    话虽如此,我的解决方案治疗的是症状而不是疾病,正如你们俩所建议的,最好在调用 this.View 之前检查文件是否存在。路径上的视图。

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

    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 路径。

    【讨论】:

    • 我已经尝试过并且喜欢该解决方案。唯一的问题是,如果由于其他原因导致 InvalidOperationException,它将导致 404。我在尝试序列化某些内容时发生了这样的异常。
    【解决方案2】:

    有一个合适的地方来处理这个。如果您实现自己的 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 返回一条友好的消息。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        我只返回一个默认视图,也许 404 响应是合适的。当然,要完成这项工作,您需要稍微更改您的架构。

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

        请注意,一般来说,将您的域(文件名)暴露给全世界并不完全安全。如果 ASPX 只是数据,那么您应该将文本放入数据库或普通的、不可执行的文本文件中。如果您正在构建某种 CMS(即您确实想要一种“安装”功能的方式),那么您可能会考虑使用 ASPX 视图来包含部分视图来封装 ASP.NET 代码块。

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

        【讨论】:

          猜你喜欢
          • 2018-06-21
          • 1970-01-01
          • 2022-01-22
          • 2011-07-12
          • 2014-01-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多