Пишем код

Заметки о .net разработке

Portable Areas как вариант модульности в MVC

with 3 comments

Один из первых вопросов, которым я задался после знакомства с азами технологии MVC3, это способ выделения и повторного использования функционала в нескольких веб-проектах.
В WPF или WinForms все просто и понятно — обособленный функционал изолируется в модуль, модуль компилируется в библиотеку, библиотека — подключается к проекту и повторно используется. Нужно лишь грамотно изолировать модули, и всё будет хорошо.

В MVC всё не так просто, если «обособленный функционал» — это набор контроллеров и вьюшек, реализующих, допустим, гостевую книгу, то просто так вынести их в отдельный модуль нельзя — MVC просто не найдет ваши контроллеры в соседних библиотеках.

Однако решение, конечно, есть, и его нам предлагает небезызвестная библиотека MvcContrib — open-source проект, неаффилированный Майкрософтом.

Изоляция нескольких взаимосвязанных контроллеров и вьюшек возможна в MVC3 и «из коробки» — для этого существуют так называемые «области» — areas. Однако вынести такие области в отдельный проект, на данный момент, без помощи MvcContrib нельзя.

Допустим, что у вас уже есть на сайте гостевая книга и есть желание повторно использовать её в другом проекте. Что надо сделать?

  1. Создать проект типа ClassLibrary и добавить в него референсы на System.Web.Mvc.dll, System.Web.Razor.dll (если вьюшки используют Razor), MvcContrib.dll и Microsoft.Web.Mvc.dll (последняя — для поддержки строгой типизации, можно пропустить).
    Зависимости portable area
  2. Создать структуру проекта, очень похожую на обычный MVC-шаблон. Единственное отличие, что папки Views, Controllers, etc. должны расположиться в корневой папке с именем нашей выделяемой области (portable area). В примере это — Guestbook. В данную структуру скопировать вьюшки и контроллеры, которые хочется обособить.

    Всем вьюшки в области необходимо выставить метод компиляции — embedded resource!
  3. Создать регистрационный класс, который и позволит связать основное MVC-приложение и выделенную область. Класс этот должен наследоваться от PortableAreaRegistration. В простейшем случае он может выглядеть так:

     public class GuestbookRegistration : PortableAreaRegistration
        {
            public override string AreaName
            {
                get { return "Guestbook"; }
            }
        }
    

    Единственный необходимый параметр — это поле AreaName с названием области.
    Однако, здесь же можно и изменить маршруты для выделенной области:

     public class GuestbookRegistration : PortableAreaRegistration
        {
            public override string AreaName
            {
                get { return "Guestbook"; }
            }
    
            public override void RegisterArea(AreaRegistrationContext context, IApplicationBus bus)
            {
                base.RegisterArea(context, bus);
    
                context.MapRoute(
                   "Guestbook_Default",
                   "GuestbookPro/{action}/{id}",
                   new { controller = "Guestbook", action = "Index", id = UrlParameter.Optional });
    
            }
        }
    

    Дефолтный маршрут выглядит, как нетрудно догадаться, так: AreaName + «/{controller}/{action}/{id}». То есть полный путь до индексового экшена по умолчанию будет выглядеть как http://localhost/Guestbook/Guestbook/Index.

Создание модуля на этом завершено :) Как его использовать? Очень просто. В основной проект добавляем референсы на модуль и MvcContrib (ну и Microsoft.Web.Mvc пригодится :)). Создаем папку Areas и копируем Web.config из папки Views в папку Areas.

Всё. Запускаем проект и заходим на localhost/Guestbook/Guestbook (первый guestbook — имя области, второй — имя контроллера).

На экшены из модуля можно также ставить ссылки и подключать их с использованием RenderAction — всё, как с обычными контроллерами.

@(Html.ActionLink<GuestbookController>(x => x.Index(), "строготипизированная ссылка на гостевую"));
@Html.ActionLink("нестроготипизированная ссылка на гостевую", "Index", "Guestbook", new { area = "Guestbook" }, null);


@{ Html.RenderAction<GuestbookController>(x => x.Index()); }
@{ Html.RenderAction("Index", "Guestbook", new { area = "Guestbook" }); }

Однако, чтобы строготипизированные ссылки работали, контроллеры внутри выделенной области надо обозначить атрибутом ActionLinkArea(«AreaName»):

 [ActionLinkArea("Guestbook")]
    public class GuestbookController : Controller
    {
    }

P.S. Ну и последний бонус для тех, кто хочет заставить это работать на linux под Mono.
На данный момент придется создать две папки Areas в структуре рабочего проекта на сервере — с большой буквы «A» и с маленькой. Необходимость в «маленькой» — баг со стороны библиотеки MvcContrib (она осуществляет предварительные проверки). Патч на этот баг отправлен разработчикам (патч в один символ :)).

Опубликовать в Facebook
Опубликовать в Google Plus

Written by Shaddix

Июль 10th, 2011 at 11:02 пп

Posted in .net,MVC,web

3 Responses to 'Portable Areas как вариант модульности в MVC'

Subscribe to comments with RSS or TrackBack to 'Portable Areas как вариант модульности в MVC'.

  1. I will immediately grab your rss feed

    volest

    31 Янв 17 at 15:02

  2. Есть такая услуга — добровольное медицинское обслуживание .
    Она предполагает, что пациент вносит небольшую сумму за то, что ходит на прием в течение года БЕСПЛАТНО.
    Однако опросы показывают, что лишь 6% жителей Питера знают о ее существовании.
    По какой причине?
    Да потому что клиникам намного выгодней сдирать с людей деньги за каждое посещение.
    А если какой-нибудь сотрудник клиники попытается рассказать про добровольное медицинское обслуживание клиенту — это сулит ему увольнением.
    Эта информация уже вызвала кучу возмущений, после того как информацию об услуге распространил один врач.
    Его уволили «по собственному желанию», после того, как он предложил ДМО своему пациенту.
    Самое удивительное, что официальные положения по ДМО присутствуют в открытом доступе, просто находили на эту информацию единицы.
    Как отстоять свои права?
    О правилах предоставления такой услуги и обязанностях клиник можно узнать, сделав запрос в Яндексе: «добровольное медицинское обслуживание».
    Обязательно обслуживание, а не страхование.

    34j5c6h86

    Claytonfar

    6 Мар 17 at 05:00

  3. Abduldeelf

    4 Апр 17 at 21:21

Leave a Reply