ASP.NET MVC中的约定有多可塑?

时间:2010-01-23 07:08:53

标签: asp.net-mvc conventions

具体来说,控制器类名称是否必须具有Controller后缀,如果您愿意,可以在不破坏内容的情况下更改项目中的文件夹结构吗?

是否有其他可以覆盖的约定,以及如何?

1 个答案:

答案 0 :(得分:3)

如果你知道框架是如何运作的,那么大多数约定都是可塑的。让我们来解决两个最大的惯​​例:

  1. 用于从路径实例化控制器的“{controller} / {action} /”魔术关键字

  2. 框架首先在控制器目录中搜索视图,然后在共享目录中搜索。

  3. 默认情况下,您创建的每个路由都与MvcRouteHandler对象的实例相关联。匹配路由时,将调用该处理程序来处理传入的请求。以下是MvcHandler的ProcessRequest的样子:

    protected internal virtual void ProcessRequest(HttpContextBase httpContext)
    {
        this.AddVersionHeader(httpContext);
        string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
        IControllerFactory controllerFactory = this.ControllerBuilder.GetControllerFactory();
        IController controller = controllerFactory.CreateController(this.RequestContext, requiredString);
        if (controller == null)
        {
            throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[] { controllerFactory.GetType(), requiredString }));
        }
        try
        {
            controller.Execute(this.RequestContext);
        }
        finally
        {
            controllerFactory.ReleaseController(controller);
        }
    }
    

    注意硬编码字符串“controller”。好吧,如果你想编写自己的控制器查找逻辑,你可以为你想要的任何路径替换这个处理程序。只需something like this (shameless blog plug)

    routes.Add("ImagesRoute",
                     new Route("graphics/{filename}", new ImageRouteHandler()));
    

    现在当路线匹配时,它会调用你自己的逻辑,你可以做任何你喜欢的事情。顺便说一下,用于查找带有“Controller”后缀的XXXXController类的反射是DefaultControllerFactory对象的一部分,在上面的处理程序中调用,并且此工厂是可替换的。

    因此,控制器选择是一种可以覆盖的约定。当从任何控制器方法执行“return View()”时,它何时查找视图?那么这里是WebFormViewEngine的构造函数,它是框架的默认视图引擎:

    public WebFormViewEngine()
    {
        base.MasterLocationFormats = new string[] { "~/Views/{1}/{0}.master", "~/Views/Shared/{0}.master" };
        base.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.aspx", "~/Views/{1}/{0}.ascx", "~/Views/Shared/{0}.aspx", "~/Views/Shared/{0}.ascx" };
        base.PartialViewLocationFormats = base.ViewLocationFormats;
    }
    

    因此,如果您不喜欢查看控制器目录,然后共享的约定 - 您可以轻松地扩展WebFormViewEngine(或use an entirely different view engine)并将其放在global.asax中:< / p>

    ViewEngines.Engines.Add(new MyViewEngine());
    

    关于MVC框架的一个令人惊奇的事情是它的灵活性。您可以使用自己的逻辑替换它的几乎任何部分 - 并且所有代码都可用于查看它们已完成的操作。