Força todas as áreas a usarem o mesmo layout

88

Tenho a seguinte estrutura de projeto:

  • / Visualizações / Compartilhado / _Layout;

  • / Areas / Area1 / Views / ControllerName / Index;

...

  • / Areas / AreaN / Visualizações / Nome do controlador / Index.

Existe alguma maneira de forçar todas as áreas a usar o _Layout como layout base ?

Existe alguma maneira de fazer isso sem adicionar o arquivo _ViewStart (por exemplo, por meio da configuração de roteamento)?

Veja também:

Como eu especifico layouts diferentes no arquivo ViewStart da ASP.NET MVC 3 razor?

Mikhail
fonte
Aqui está uma boa resposta e outra
Rafael Emshoff

Respostas:

157

Você só precisa adicionar um arquivo chamado:

_ViewStart.cshtml

Em cada pasta de visualizações de área:

/Areas/Area1/Views/_ViewStart.cshtml

E edite o arquivo para apontar para o layout raiz como este:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Para que isso funcione, você não precisa especificar um valor na propriedade de layout da visualização, se o fizer, você estará substituindo o layout global

Nota: Como Tony mencionou, você pode editar a propriedade de layout de cada visualização para apontar para o layout raiz, no entanto, esta não é a maneira recomendada de fazer isso, pois você acoplaria suas visualizações com seu layout e alteraria seria doloroso

Editar 1

Se você gostaria de usar o código para definir o layout da visualização padrão, talvez você deva considerar a criação de um mecanismo de visualização customizado.

Tente google sobre custom RazorViewEngineeRazorView

Este artigo pode ser um bom ponto de partida

http://weblogs.asp.net/imranbaloch/archive/2011/06/27/view-engine-with-dynamic-view-location.aspx

Eu não fiz algo assim, mas espero estar apontando na direção certa

Jupaol
fonte
1
Existe alguma maneira de fazer isso sem adicionar o arquivo "_ViewStart" (por exemplo, por meio da configuração de roteamento)?
Mikhail
2
Dentro do roteamento acho que não. São duas coisas diferentes. O roteamento é responsável por tentar casar a URL da solicitação atual com uma rota registrada na RoutesTable, quando uma correspondência é encontrada, um IMvcRouteHandler é criado e então um IHttpHandler (MvcHandler) é responsável por processar a ação do seu controlador. Como você pode ver, isso não tem nada a ver com visualizações ou layouts. Isso ocorre porque uma rota não retorna necessariamente uma visualização, ela pode retornar json ou xml. Portanto, o roteamento não é o lugar correto para implementar algo assim.
Jupaol
Você também pode adicionar o _ViewStartdiretamente na pasta Área para aplicá-lo a todas as áreas.
Artur
21

Expandindo a resposta da Jupaol ....

Pelo menos no VS2013, o arquivo _ViewStart.cshtml é adicionado por padrão ao criar a área, então ele já está lá, e você pode alterar o conteúdo conforme ele observa para apontar para a raiz _Layout.cshtml. Você pode então remover o _Layout.cshtml da área, uma vez que ele não é mais usado (e uma fonte potencial de confusão agora)

No entanto, ao fazer isso, qualquer roteamento executado nesse _Layout.cshtml raiz precisará considerar áreas.
O _Layout.cshtml padrão tem vários auxiliares ActionLink que precisam de uma pequena modificação:

Adicione o parâmetro RouteValueDictionary a qualquer chamada ActionLink definindo Area = "". Observe que a string vazia se refere ao nível raiz. Isso permitirá que esses links funcionem corretamente quando chamados de dentro de uma área, ainda funcionem quando chamados da raiz.

por exemplo:

<li>@Html.ActionLink("Home", "Index", "Home", new { Area = "" }, null)</li>
Rob Campbell
fonte
2

Você especifica um layout usando:

@ {Layout = "_Layout"; }

Se você quiser tornar isso mais fácil, mude tudo de uma vez. Talvez você possa apenas defini-la como uma variável view bag e passá-la para o controlador. Para tornar ainda mais fácil, você pode criar um controlador de base do qual os outros controladores herdam e fazer com que ele atribua o layout ao view bag ali.

Não sei por que o roteamento precisaria ser alterado ou talvez não esteja entendendo. Espero que isto ajude :)

Tony
fonte