MVD ( Model View Dispatcher ) 4

Article-5-small

 Начало

После появления в нашей работе IML стало намного проще построить ajax приложение, чем обычное из-за возможности разделять сложные View на более простые, что позволяет существенно упросить код, но также заметно увеличилось количество Action в Controller.

MVD ( model view dispatcher )  – шаблон разработки, который позволяет выполнять Command/Query без написания Action

Рассмотрим пример:

листинг кода демонстрирует частый случай, когда Action возвращает View, которая строится на основе данных из Query ( GetUserDetailsQuery ). Видно что большая часть логики скрыта в Query и это правильно, потому что Query имеет все нужные инструменты для работы с базой данных и Event Broker, а также то, что можно повторно использовать.

Теперь пример вызова этого Action из View

Со временем стало появляться желание вызвать Query и передать его данные во View в обход Controller, потому что он является просто промежуточным звеном, которое надо покрывать тестами и поддерживать в дальнейшем. Проблема не в том, что приходится создавать много Action, а в их избыточности, которая была выявлена после изучения большинства сценариев, которые они решают в рамках CQRS архитектуры. Controller вызывает Dispatcher и не имеет, какой-то дополнительной логики, может за некоторыми исключениями, но чаще всего это довольно-таки рутинный код.

Write less, do more

Рассмотрим новый код View

В записи изменился способ построения Url, теперь это не обычный Url.Action, а специализированный построитель, который так же построит адрес, но на основе Query и пути к View

Данный код будет работать без написания Action, что позволяет существенно экономить время на разработке и поддержке.

Больше нету MVC ?

Чтобы получить ответ на этот вопрос, давайте  посмотрим как интегрировать MVD в проект

  •  Создать DispatcherController ( имя важно ), который унаследовать от DispatcherControllerBase  ( версия 1.1 устанавливает его по умолчанию )

примечание: в качестве параметра в конструктор надо передать Assembly в которой лежат Ваши Command/Query, а так же другие классы, которые задействованы во View.

DispatcherControllerBase содержит следующие Action:

Можно построить url, который выполнит Push command 

Для того, чтобы упростить построение url адреса, можно использовать Url.Dispatcher

А что он может ?

MVD покрывает большинство сценариев, которые встречаются при веб разработки на платформе asp.net mvc.

примечание: примеры можно скачать.

  • Push одиночной command

 примечание: в качестве значений для параметров можно использовать Selector

примечание: push возвращает результат, а для композита будет массив из результатов каждой command

  •  Push композита command

 примечание: надо учитывать, что в случае совпадения имен параметров,  значение будет одинаковым и взято из последней, поэтому в таких ситуациях можно добавлять дополнительный префикс к имени.

  • Query как Json

  •  Query как View

примечание: путь к View строится не как в asp.net mvc относительно Controller, а от корневой директории сайта, что позволяет строить любую структуру папок для хранения View.  

  •  Query как File

примечание: для построения File, надо чтобы Query в качестве результата возвращал массив byte ( byte[] ) 

  • Model как View

примечание: если запрос будет выполнен не через Ajax, то результат будет не JSON, а ContentResult

  • View

 примечание: данный способ подходит для получения template по Ajax

Спектр применения MVD очень большой, в следующей версии будет поддержка Async методов, что позволяет с уверенностью утверждать о том, что возможностей хватит на разработку проекта без единого дополнительного Controller.

А как быть если ?

Многие могут заметить, что отсутствие Controller не позволяет использовать такую возможность как Attributes, которые применяются  в разных сценариях. Рассмотрим очень частую задачу, которая имеет место практически в любом сайте – это проверка на авторизацию.

В рамках asp.net mvc это решается с помощью атрибутов, которыми отмечаются те Action ( или Controller ) где описывается логика проверки, в MVD данную задачу можно решить несколькими способами:

  • Отметить атрибутом DispatcherController  и в коде атрибута. Способ очень удобен, если Вы пишите CRM  систему и все действия проходя с авторизацией

примечание: можно также в коде атрибута проверять текущий запрашиваемый адрес на “белом” списке, то есть исполнять код, если адрес не входит в этот список.

  • Использовать возможности Dispatcher Event, которые описаны в статье 

примечание: можно отмечать атрибутами Command/Query , что будет очень похоже на работу стандартного asp.net mvc

  • Реализовать проверку на клиенте

Поэтапный алгоритм:

  1. После загрузки элемента ( InitIncoding ) выполняем Ajax запрос ( строка 3 )
  2. По OnSuccess проверяем результат и если пользователь не авторизирован, то делаем Break
  3. Если OnBreak, то делаем trigger на “ветку” SignIn и показываем диалог с формой авторизации
  4. Если код пройдет OnBreak, то выполняем действия по запуску сценариев странице

Код работает для большинства сценариев и не ограничивает спектр ( роли, права и т.д. )  проверок, а также есть возможность делать разные проверки в зависимости от страницы, то есть создать Home/Index и Dashboard/Index, где использовать разный код.

Vlad Kopachinsky

I am a Senior developer at Incoding Software in Russian Federation. I created the Incoding Framework for rapid development

More Posts - Website - Twitter - Facebook - LinkedIn

4 thoughts on “MVD ( Model View Dispatcher )

  1. Artur Movsesyan 20.12.2013 Fri, 20 Dec 2013 04:44:47 +0000

    Привет. Вопрос такой: как добавить ошибку к ModelState, если нет контроллера? Только изнутри Command/Query?

  2. Artur Movsesyan 20.12.2013 Fri, 20 Dec 2013 05:59:35 +0000

    А как будет выглядеть на MVD следующий сценарий?

    public ActionResult SomeAction(){
    var user = dispatcher.Query(new GetCurrentUserQuery());
    if(user.IsManager)
    return View();
    return RedirectToAction("AnotherAction");
    }

    • Vlad Kopachinsky 20.12.2013 Fri, 20 Dec 2013 07:20:50 +0000

      Можно так :

      @(Html.When(JqueryBind.Click)
      .Do()
      .AjaxGet(Url.Dispatcher().Query(new SomeQuery()))
      .OnSuccess(dsl =>
      {
      dsl.Utilities.Document.RedirectTo("redirectUrl")
      .If(r => r.Data(r => r.IsUser));
      dsl.Utilities.Document.RedirectTo(Url.Dispatcher().AsView("SomeView"))
      .If(r => r.Data
      (r => r.IsUser == false));
      })
      .AsHtmlAttributes()
      .ToButton("Test"))

      Бывают ситуации, когда возможностей MVD не хватает, но Вы всегда можете написать свой Action. Особенность MVD в том, что он не перекрывает MVC, а дополняет. Пока большинство сценариев решаются с применением MVD, но я постоянно занимаюсь развитием функциональной части.

      P.S. Спасибо за интересные вопросы, если у Вас будут ещё сценарии, которые Вы видите нерешаемыми в рамках MVD пишите, буду благодарен. Примеры сценариев и их решение, я позже добавлю в основную статью.

Leave a Reply