MVC3 Controller и просмотр многократного использования - PullRequest
0 голосов
/ 04 августа 2011

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

Последние добавления включали аутентификацию (аутентификацию по индивидуальным формам), автоматическое построение меню (с использованием атрибутов действия контроллера) и несколько других экранов.Проблема, с которой я столкнулся, заключается в том, что мне пришлось создавать дублированные контроллеры и представления.

Лучший пример - бит аутентификации.Каждое приложение теперь имеет контроллер учетной записи и представление проверки подлинности, которые являются копиями друг друга.Вы можете увидеть, как это может быстро стать кошмаром обслуживания, так как добавлено больше приложений.Другим примером является общее представление в каждом приложении, которое отображает меню (обычно вызывается через Html.Action).Для этого также нужен контроллер, который выглядит одинаково в каждом из приложений.

Мне удалось абстрагировать детали реализации аутентификации и построения меню в общий проект под названием XXX.Core.Mvc, который также имеет общие расширения htmlHelper.и что-нибудь конкретное для сети Mvc.Так что теперь все дублированные представления и контроллеры в приложениях действуют как прокси.

Я ищу хороший пример того, как избавиться от них, чтобы общие представления и контроллеры находились в общем проекте, где они могутбыть ссылаться / вызываться.Кто-нибудь сделал что-то подобное?Можете ли вы порекомендовать какие-нибудь хорошие статьи или примеры?

Например, как вы указываете действие контроллера, которое возвращает View ActionResult представлению в другом проекте или общем пути?Как маршрутизировать например / Аккаунт / Аутентификация на контроллере в другом проекте?Каковы последствия развертывания подхода?

1 Ответ

0 голосов
/ 16 августа 2011

Я попробовал две вещи.В каждом случае общий контроллер и представления были расположены в отдельной сборке.Для подтверждения концепции я реализовал общую обработку ошибок приложения.Поэтому в моем приложении Mvc3 для конечной точки global.asax реализует:

protected void Application_Error()
{
    ApplicationErrorHandler.Get().Handle(Server, new HttpResponseWrapper(Response), new HttpContextWrapper(Context));
}

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

public class ApplicationErrorHandler
{
    public static ApplicationErrorHandler Get()
    {
        return new ApplicationErrorHandler();
    }

    public void Handle(HttpServerUtility server, HttpResponseBase response, HttpContextBase context)
    {
        var exception = server.GetLastError();
        var httpException = exception as HttpException;
        response.Clear();
        server.ClearError();
        var routeData = new RouteData();
        routeData.Values["controller"] = "Errors";
        routeData.Values["action"] = "Http500";
        routeData.Values["exception"] = exception;
        response.StatusCode = 500;
        if (httpException != null)
        {
            response.StatusCode = httpException.GetHttpCode();
            switch (response.StatusCode)
            {
                case 403:
                    routeData.Values["action"] = "Http403";
                    break;
                case 404:
                    routeData.Values["action"] = "Http404";
                    break;
            }
        }
        IController errorsController = new ErrorsController();
        var rc = new RequestContext(context, routeData);
        errorsController.Execute(rc);
    }
}

В этой же сборке находится в папке Controllers.ErrorsController и Views \ Errors содержит 3 необходимых представления;Http403.cshtml, Http404.cshtml и Http405.cshtml.Таким образом, структура такая же, как в вашем обычном проекте Mvc3.Однако для того, чтобы получить поддержку @model и intelisense для работы, вам также понадобится web.config - копия файла из Views в вашем обычном проекте и размещенная под views в этой отдельной сборке.

Когда, скажем, приложениеВ нашем приложении возникает ошибка (http status 500 - внутренняя ошибка сервера), выполняется ErrorsController, и представлением, используемым в этом случае, будет Http500.cshtml.Рассматриваемый путь будет:

  • ~ \ Views \ Errors \ Http500.cshtml
  • ~ \ View \ Shared \ Http500.cshtml

InДля того, чтобы предоставить файл из сборки, я попробовал две вещи:

Подход первый: реализовать VirtualPathProvider.Я не буду вдаваться в подробности, но цель состоит в том, чтобы встроить представления cshtml в качестве ресурсов и обработать их с помощью VirtualPathProvider и VirtualFile.Проблема с этим подходом заключается в том, что я не нашел подходящего способа также сервировать web.config из папки Views, чтобы Razor мог оценить представление.Я мог бы получить его для извлечения файла и его потоковой передачи, но не для его выполнения.Чтобы объяснить причину проблемы, рассмотрим файл Http500.cshtml:

@model Exception
<h3>@MvcHtmlString.Create(Model.Message.Replace(Environment.NewLine, "<br />").Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"))</h3>
<p>@MvcHtmlString.Create(Model.StackTrace.Replace(Environment.NewLine, "<br />").Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"))</p>
<input type="hidden" name="serverError" value="true"/>

. Было возвращено содержимое файла, а не оцененное исключение.Причина в том, что также необходимо обслужить файл web.config из папки View, чтобы использовать Razor.По умолчанию механизм просмотра - это веб-формы (.aspx).

Второй подход: создать виртуальный каталог в IIS.Этот подход работает намного лучше, потому что представления не должны быть скомпилированы как ресурсы, нет необходимости в виртуализации.Все, что нужно, это создать виртуальный каталог Ошибки в папке Views в моем конечном приложении и указать его, где развернуты Views \ Errors из общей сборки.

Конечно, он не ведет себя как правильный плагин, потому чтообщие файлы должны быть развернуты отдельно от .dll, но меня это не слишком беспокоит.

Однако, если кто-то знает, как заставить виртуальные файлы работать на Razor, я весь в ушах.Хорошо - все глаза действительно.

...