Как установить макет Razor в MVC через фильтр атрибутов? - PullRequest
7 голосов
/ 29 октября 2010

Я бы хотел установить макет Razor по умолчанию с помощью кода в базовом контроллере или атрибуте.В Документах упоминалось, что это возможно, но я не могу понять, как это делается.

Я знаю, что для метода View доступен параметр masterPage, но я бы хотел, чтобы все представления возвращались контроллером.чтобы установить это значение автоматически.

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

Спасибо

Ответы [ 2 ]

15 голосов
/ 30 октября 2010

Я думаю, что вы могли бы просто написать ActionFilter как ...

public class YourCustomLayoutAttribute : ActionFilterAttribute, IResultFilter
{
      public override void OnResultExecuting(ResultExecutingContext filterContext)
      {
           var viewResult = filterContext.Result as ViewResult;
           if(viewResult != null)
           {
              // switch the layout
              // I assume Razor will follow convention and take the "MasterName" property and change the layout based on that.
              viewResult.MasterName = "CustomLayout";
           }
       }
}

Я просто написал этот код по месту моих штанов без компилятора, так что он, вероятно, не будет компилироваться, но вы, вероятно, получитеидея.Я думаю, что IResultFilter - правильный интерфейс, который вы хотите, у него есть методы, которые выполняются непосредственно перед отображением представления.Если это правильно, вы сможете изменить MasterName для представления, которое будет отображаться на лету.

Это будет использование кода контроллера.

[YourCustomLayout] // this should trigger your custom action result for all actions
public class MyController : Controller
{
   public ActionResult Index()
   {
      return View("Index", "MainLayout"); // even if you were to use the overload to set a master, the action result should override it as it executes later in the pipeline.
   }
}
3 голосов
/ 29 октября 2010

Самый простой способ, которым я могу придумать, это сделать ваши контроллеры производными от пользовательского базового класса, который переопределяет метод View:

public class MyControllerBase : Controller {
    public override ViewResult View(string viewName, string masterName, object model) {
        if(String.IsNullOrEmpty(masterName)) {
            masterName = GetDefaultLayout();
        }
        base.View(viewName, masterName, model);
    }

    public virtual string GetDefaultLayout() {
        return // your default layout here
    }
}

В приведенном выше коде вы можете явно установить masterName для некоторогожестко закодированное значение.Или ваши контроллеры могут переопределить метод, чтобы обеспечить макет для конкретного контроллера.Или вы можете прочитать его из какого-либо атрибута на контроллере, что-то похожее на:

masterName = GetType().GetCustomAttributes().
             OfType<MyCustomAttribute>().FirstOrDefault().DefaultLayoutPage;

Конечно, вам придется создать свой MyCustomAttribute.

...