Como definir um layout Razor no MVC por meio de um filtro de atributo?
-
27-09-2019 - |
Pergunta
Eu gostaria de definir um layout padrão de barbear via código em um controlador base ou em um atributo. Foi mencionado nos documentos que isso é possível, mas não consigo descobrir como é feito.
Eu sei que existe o parâmetro Masterpage no método de exibição disponível, mas gostaria que todas as visualizações retornadas por um controlador tenham esse valor definido automaticamente.
E não, não posso usar o _Viewstart para isso, pois minhas opiniões serão em vários lugares (essa não é uma configuração normal do site MVC).
Obrigado
Solução
Eu acho que você poderia apenas escrever um filtro de ação como ...
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";
}
}
}
Acabei de escrever esse código pelo assento da minha calça sem compilador, para que provavelmente não seja compilado, mas você provavelmente entendeu a ideia. Eu acho que o IRESultFilter é a interface correta que você deseja, ele tem métodos que executam logo antes da exibição. Se isso estiver correto, você poderá modificar o nome do MasterN para a visualização que está prestes a ser renderizada em tempo real.
Este seria o uso do código do controlador.
[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.
}
}
Outras dicas
A maneira mais fácil de pensar em fazer isso é ter seus controladores derivarem de uma classe base personalizada que substitui o método de exibição:
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
}
}
No código acima, você pode definir explicitamente o nome do master como algum valor codificado. Ou seus controladores podem substituir o método para fornecer um layout específico do controlador. Ou você pode lê -lo em algum atributo no controlador, algo semelhante a:
masterName = GetType().GetCustomAttributes().
OfType<MyCustomAttribute>().FirstOrDefault().DefaultLayoutPage;
Claro que você teria que criar seu MyCustomAttribute
.