Onde e como o arquivo de layout _ViewStart.cshtml está vinculado?

199

Aqui está o About.cshtml do modelo padrão do MVC 3:

@{
    ViewBag.Title = "About Us";
}

<h2>About</h2>
<p>
     Put content here.
</p>

Eu esperaria que uma referência ao arquivo _ViewStart fosse encontrada no About.cshtml, mas claramente não é.

Eu olhei em global.asaxe web.config, mas eu não consigo descobrir como o About.cshtmlarquivo é "ligado" com o layout do arquivo _ViewStart.

Tudo funciona como esperado, eu gostaria de saber o que está acontecendo sob o capô ...

Kman
fonte

Respostas:

237

Do blog de ScottGu :

Começando com a versão ASP.NET MVC 3 Beta, agora você pode adicionar um arquivo chamado _ViewStart.cshtml (ou _ViewStart.vbhtml para VB) abaixo da pasta \ Views do seu projeto:

O arquivo _ViewStart pode ser usado para definir o código de exibição comum que você deseja executar no início da renderização de cada exibição. Por exemplo, poderíamos escrever código em nosso arquivo _ViewStart.cshtml para definir programaticamente a propriedade Layout para cada modo de exibição como o arquivo SiteLayout.cshtml por padrão:

Como esse código é executado no início de cada Visualização, não precisamos mais definir explicitamente o Layout em nenhum dos nossos arquivos de visualização individuais (exceto se desejarmos substituir o valor padrão acima).

Importante: Como o _ViewStart.cshtml nos permite escrever código, opcionalmente, podemos tornar nossa lógica de seleção de Layout mais rica do que apenas um conjunto de propriedades básicas. Por exemplo: podemos variar o modelo de Layout que usamos, dependendo do tipo de dispositivo que está acessando o site - e ter um layout otimizado para telefone ou tablet para esses dispositivos e um layout otimizado para desktops para PCs / laptops. Ou, se estivéssemos construindo um sistema CMS ou aplicativo compartilhado comum usado em vários clientes, poderíamos selecionar layouts diferentes para usar, dependendo do cliente (ou de sua função) ao acessar o site.

Isso permite muita flexibilidade da interface do usuário. Ele também permite que você escreva com mais facilidade a lógica de visualização uma vez e evite repeti-la em vários locais.

Veja também isso .

Jim Tollan
fonte
14
Portanto, é mais ou menos um recurso "codificado" do MVC3? Não preciso alterá-lo para outra página "padrão", apenas curioso para saber como foi configurado. Obrigado por classificar tudo para fora :)
Kman
2
Kman- codificado, por convenção (escolha outro 'identificador' aqui :)) - então sim, exatamente. contente que limpou o nevoeiro
jim tollan 15/02/12
Não é apenas na sua pasta "Views" que você pode precisar. Se você adicionar um RazorViewEngine personalizado para organizar as visualizações em outras pastas, também precisará incluir o arquivo na raiz dessas pastas de exibição alternativas. Por exemplo, movi todas as visualizações de modelo do Inspinia para uma pasta e executei isso no mecanismo de exibição ViewLocationFormats = ViewLocationFormats.Union(new string[] { "~/Inspinia/ExampleViews/{1}/{0}.cshtml" }).ToArray();. Como resultado, tive que adicionar uma cópia do meu arquivo _ViewStart.cshtml a "~ / Inspinia / ExampleViews", caso contrário, ele não foi escolhido e nenhum layout foi definido.
Triynko
2
Se a pasta Views tiver subpastas, você pode colocar um _ViewStartem cada subpasta que se vinculará às exibições nessa subpasta?
toddmo
35

Em um sentido mais geral, essa capacidade da estrutura MVC de "conhecer" sobre _Viewstart.cshtml é chamada de "Codificação por convenção".

Convenção sobre configuração (também conhecida como codificação por convenção) é um paradigma de design de software que busca diminuir o número de decisões que os desenvolvedores precisam tomar, ganhando simplicidade, mas não necessariamente perdendo flexibilidade. A frase significa essencialmente que um desenvolvedor precisa apenas especificar aspectos não convencionais do aplicativo. Por exemplo, se houver uma classe Venda no modelo, a tabela correspondente no banco de dados será chamada de "vendas" por padrão. Somente se alguém se desviar dessa convenção, como chamar a tabela "produtos_soldados", é necessário escrever um código referente a esses nomes.

Wikipedia

Não há mágica nisso. Ele acabou de ser gravado na base de código principal da estrutura MVC e, portanto, é algo que o MVC "conhece". É por isso que você não o encontra nos arquivos .config ou em outro local; na verdade, está no código MVC. No entanto, você pode substituir para alterar ou anular essas convenções.

arriscar
fonte
13
Se o MVC sabe disso, por que o Visual Studio não sabe e aponta isso para mim? Se a codificação por meio de convenções que o material funciona, desde que você acontecer para não quebrar a convenção que tipo de suga ...
Arne Evertsson
Não quebrar a convenção é o tipo de questão. O AKAIK Ruby on Rails também segue esse paradigma.
Umar Farooq Khawaja
+1 Raif. Não faz sentido defender a "codificação por convenção" mal documentada. Eu poderia dizer isso sobre qualquer um dos meus códigos anteriores. "O quê? Você não esperava que batesse quando chegou aos 33? Todo mundo sabe que você pula 33." Infelizmente, a lacuna na documentação do ASP.NET MVC é enorme. Os únicos documentos da Microsoft são gerados automaticamente, sem resumos de fontes internas.
precisa
6
Convenção sobre configuração não significa que você não pode alterá-la. Deve haver configuração disponível para poder especificar o nome e o local desse arquivo. Pode muito bem haver, mas quem sabe o que é. As pessoas usam o mantra "convenção sobre configuração" para cobrir uma infinidade de decisões ruins em uma base de código e meio que me irritou como o cara que vem depois do fato para manter sua bagunça mal documentada que "simplesmente funciona" (mas Deus permita que você mude qualquer coisa - você passará horas tentando descobrir como quebrou tudo).
Robert C. Barth
3
@AidenStrydom Eu discordo. A resposta aceita na verdade me diz como usar _ViewStart. Esta resposta apenas fala sobre um conceito de design. Eu vim aqui para obter informações sobre _ViewStart, não informações sobre por que o Visual Studio não me disse nada sobre _ViewStart.
Millie Smith
23

Apenas outro pensamento.

Se você deseja ter seu próprio cshtmlarquivo como um modelo comum, pode fazê-lo desta maneira

Dentro do seu, _viewstart.cshtmlvocê pode mencionar seu cshtmlarquivo comum .

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

O código-fonte é um lugar muito melhor para procurar isso do que a documentação.

Fazendo referência ao código MVC 6 do Github, temos alguns arquivos de interesse

----atualizar----

Devido a alterações na estrutura de origem, as informações sobre como as páginas do viewstart são reunidas agora podem ser encontradas no RazorViewEngine.cs, procurando a função "GetViewStartPages".

----/atualizar----

Para responder como eles entram em cena, veja o RazorView , que eu acredito (por causa do IView) está ligado ao pipeline do MVC. Este arquivo possui um método RenderAsync que é chamado do pipeline MVC para renderizar a exibição solicitada.

RenderAsync faz chamadas para RenderPage E ENTÃO RenderLayout (NOTE THE ORDER). O RenderPage primeiro faz chamadas para lidar com arquivos de viewstart (observe o plural, pode haver mais de um arquivo _viewstart).

Portanto, as informações que você procura podem ser obtidas na função RenderViewStartAsync no arquivo RazorView.cs no espaço de nome Microsoft.AspNet.Mvc.Razor.

Frison Alexander
fonte
7

Isso pode adicionar algumas informações adicionais a esta pergunta agora (2016 ala MVC4, MVC5).

O mecanismo Razor localiza e executa o código em _ViewStart.cshtml antes de qualquer outro código que esteja no mesmo diretório ou subdiretório em que o _ViewStart.cshtml é encontrado.

Qualquer visualização pode substituir a propriedade Layout ou qualquer um de seus valores.

Apenas pensei em adicionar um pouco mais de informação para mostrar por que é _ViewStart.

Se você obtiver o ILSpy e examinar o código no RazorViewEngine (System.Web.Mvc.dll), verá que o próprio código faz referência a esse nome.

_ViewStart no System.Web.Mvc.dll

Você pode ver que o RazorViewEngine procura um arquivo com esse nome:

código do razorviewengine

RazorViewEngine.ViewStartFileName = "_ViewStart";
raddevus
fonte
3
isto é o que eu estava procurando, eu odeio "não sei" o que está acontecendo no meu projeto, porque também estou fazendo meus próprios modelos para o VS e esse arquivo que acabou de sair do ar foi muito difícil de entender
Sebastian 506563
1

Se você deseja ter um layout comum para suas páginas, precisa definir o layout comum e associar uma visualização ao layout. Temos que definir as propriedades de layout em cada visualização, isso viola o princípio DRY (Não se repita). Para isso, o .Net Framework fornece o arquivo "_ViewStart.cshtml", colocado dentro da pasta de exibição. Colocamos informações de layout no arquivo "_ViewStart.cshtml" e, por padrão, todas as visualizações usam essas informações de layout. Se você deseja fornecer algumas informações diferentes sobre o layout, suponha que a visualização da tela inicial, crie um novo "_ViewStart.cshtml" com referência a esse layout e coloque-o na pasta "Home View".

KamalDeep
fonte
1

A resposta curta é : o ViewStarts inicia primeiro quando qualquer exibição está sendo renderizada. A longa história está abaixo:

A história da criação de um único arquivo de visualização:

  1. O ViewStart é mesclado com o ViewImports e, em seguida, executado como um único arquivo. Observe que o ViewImports sempre é mesclado com qualquer arquivo cshtml, incluindo o arquivo ViewStart. Seu objetivo é abstrair instruções @using e outras diretivas comuns.
  2. A saída do ViewStart (como Layout e ViewData) fica disponível para o arquivo View específico.
  3. Dentro do arquivo View, se a variável Layout for / se torna nula, o corpo da view é renderizado e a saída final é entregue ao usuário.
  4. Se a variável Layout for / se tornar nula, a execução será movida para o arquivo de layout, que por sua vez será mesclado com ViewImports como um único arquivo e, em seguida, na instrução @RenderBody () dentro da execução do arquivo de layout, será movida de volta para o arquivo de exibição que é mesclado com o ViewImports novamente e a saída é mesclada com o arquivo de layout no local @RenderBody () e a saída final é finalmente entregue ao usuário.

Espera que isso o torne ciente do que realmente está acontecendo dentro dos mistérios desconhecidos do ciclo de vida do seu programa.

Shadi Namrouti
fonte