Встроенный код в Razor _Layout.cshtml - PullRequest
4 голосов
/ 16 марта 2012

Я работаю над веб-приложением MVC3 Razor, которое получает оформление страницы из системы управления контентом java.Так как это оформление доступно для каждой страницы, я поместил извлечение содержимого CMS в файл _Layout.cshtml, но я не совсем доволен реализованным кодом ...

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    @{
        -- The first two lines are temporary and will be removed soon.
        var identity = new GenericIdentity("", "", true);
        var principal = new GenericPrincipal(identity, new string[] { });
        var cmsInterface = MvcApplication.WindsorContainer.Resolve<ICMSInterface>();
        cmsInterface.LoadContent(principal, 2);
     }
     @Html.Raw(cmsInterface.GetHeadSection())
 </head>

<body>
    @Html.Raw(cmsInterface.GetBodySection(0))
    @RenderBody()
    @Html.Raw(cmsInterface.GetBodySection(1))
</body>
</html>

Поскольку для файла _layout нет контроллера, я не вижу, куда еще я могу поместить код для поиска.Вот несколько вещей, которые я рассмотрел:

  • Получение содержимого CMS по частям, поэтому мне не нужен вызов LoadContent.К сожалению, из-за компонента, который я должен использовать для извлечения контента CMS, это невозможно, это все или ничего.
  • Используйте частичное представление, чтобы я мог использовать контроллер.Поскольку мне нужно поместить всю страницу в частичное, эта опция кажется немного смешной.
  • Вызовите один статический метод для некоторого вспомогательного класса, который извлекает данные и добавляет три раздела в ViewBag.Это позволит мне убрать код из поля зрения и кажется лучшим решением, но я все еще не особенно доволен им.

У кого-нибудь есть другие предложения / комментарии?

Ответы [ 4 ]

5 голосов
/ 23 марта 2012

Вы можете использовать фильтр глобального действия, чтобы добавить необходимые данные в ViewBag во всех контроллерах:

public class LoadCmsAttribute : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        if (!filterContext.IsChildAction &&
            !filterContext.HttpContext.Request.IsAjaxRequest() &&
            filterContext.Result is ViewResult)
        {
            var identity = new GenericIdentity("", "", true);
            var principal = new GenericPrincipal(identity, new string[] { });
            var cmsInterface = MvcApp.WindsorContainer.Resolve<ICMSInterface>();
            cmsInterface.LoadContent(principal, 2);

            var viewBag = filterContext.Controller.ViewBag;
            viewBag.HeadSection = cmsInterface.GetHeadSection();
            viewBag.FirstBodySection = cmsInterface.BodySection(0);
            viewBag.SecondBodySection = cmsInterface.BodySection(1);
        }
    }
}

Global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    ...
    filters.Add(new LoadCmsAttribute());
}
1 голос
/ 22 марта 2012

* "Так как нет контроллера для файла _layout". * Дело в том, что ваше предположение не совсем верно! На самом деле, довольно часто заполнять страницу _Layout с помощью контроллеров. Давайте подумаем, например, о прямоугольнике входа / выхода, который является большим количеством веб-сайтов ... обычно он помещается в _Layout и обрабатывается с помощью контроллера. Нет контроллера, который передает ViewModel в Layout ... просто потому, что Layout ... это просто ... Layout, а не то, что передает информацию ... однако это может быть "контейнер" для другого содержимого, которое в Поворот может иметь ViewModel. На практике вы можете вызывать дочерние контроллеры из _Layout, используя Html.Action или Html.RenderAction ... Именно так обрабатывается вход в систему на большинстве веб-сайтов asp.net Mvc ... и я предлагаю вам сделать то же самое для вашего контента ... заполните свой контент, вызвав специализированные дочерние контроллеры, по одному для каждой отдельной "области" страницы макета.

1 голос
/ 16 марта 2012

Одно решение:

  1. Создайте базовый контроллер, от которого наследуется каждый из ваших контроллеров.
  2. Переопределите OnActionExecuted или аналогичный обзор
  3. Добавьте данные вViewBog или ViewData в вашем переопределенном коде

Код OnActionExecuted будет запускаться при каждом вызове действия, поэтому вы можете захотеть выполнить некоторую проверку, чтобы убедиться, что действие вернет представление и т. Д.лучше переопределить OnActionExecuting, OnResultExecuting и т. д., но это то, что приходит мне на ум.

Другое решение:

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

http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

Это может быть лучшим решением, если вам не нужен базовый контроллер.

0 голосов
/ 23 марта 2012
...