Насколько податливы соглашения в ASP.NET MVC? - PullRequest
3 голосов
/ 23 января 2010

В частности, должно ли имя класса контроллера иметь суффикс Controller, и можете ли вы изменить структуру папок в своем проекте, если хотите, не нарушая ничего?

Существуют ли другие соглашения, которые могут быть отменены, и как?

1 Ответ

3 голосов
/ 23 января 2010

Большинство конвенций податливы, если вы знаете, как работает фреймворк. Давайте рассмотрим два самых больших соглашения:

  1. магические ключевые слова "{controller} / {action} /" для создания контроллеров с маршрута

  2. способ, которым платформа ищет представления сначала в каталоге контроллера, а затем в общем каталоге.

Каждый созданный вами маршрут по умолчанию связан с экземпляром объекта MvcRouteHandler. Когда маршрут соответствует, этот обработчик вызывается для обработки входящего запроса. Вот как выглядит ProcessRequest в MvcHandler:

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». Ну, вы можете заменить этот обработчик для любого маршрута, который вам нужен, если вы хотите закодировать свою собственную логику поиска контроллера. Просто сделайте что-то вроде этого (бесстыдный плагин блога) :

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

Теперь, когда маршрут совпадает, он вызывает вашу собственную логику, и вы можете делать все, что пожелаете. Кстати, отражение, которое используется для поиска класса XXXXController с суффиксом «Controller», является частью объекта 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 (или использовать совершенно другой механизм представления ) и добавить его в свой global.asax:

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

Одна из замечательных особенностей инфраструктуры MVC - ее гибкость. Вы можете заменить практически любую его часть своей собственной логикой - и весь код доступен, чтобы увидеть, что они сделали.

...