具体来说,控制器类名称是否必须具有Controller
后缀,如果您愿意,可以在不破坏内容的情况下更改项目中的文件夹结构吗?
是否有其他可以覆盖的约定,以及如何?
答案 0 :(得分:3)
如果你知道框架是如何运作的,那么大多数约定都是可塑的。让我们来解决两个最大的惯例:
用于从路径实例化控制器的“{controller} / {action} /”魔术关键字
框架首先在控制器目录中搜索视图,然后在共享目录中搜索。
默认情况下,您创建的每个路由都与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框架的一个令人惊奇的事情是它的灵活性。您可以使用自己的逻辑替换它的几乎任何部分 - 并且所有代码都可用于查看它们已完成的操作。