Eu tenho um site que tem uma página de layout. No entanto, esta página de layout possui dados que todos os modelos de páginas devem fornecer como título, nome da página e o local em que realmente estamos para um auxiliar de HTML que fiz, que executa alguma ação. Além disso, cada página tem suas próprias propriedades de modelos de exibição.
Como posso fazer isso? Parece que é uma má idéia digitar um layout, mas como passo essas informações?
asp.net-mvc-4
Rushino
fonte
fonte
ViewBag
. Talvez uma questão de preferências. Voto positivo com o seu comentário emboraRespostas:
Se você precisar passar as mesmas propriedades para cada página, seria sensato criar um modelo de vista base usado por todos os seus modelos de vista. Sua página de layout pode usar esse modelo base.
Se houver lógica necessária por trás desses dados, isso deve ser colocado em um controlador de base usado por todos os seus controladores.
Você pode fazer muitas coisas, a abordagem importante é não repetir o mesmo código em vários lugares.
Editar: Atualização dos comentários abaixo
Aqui está um exemplo simples para demonstrar o conceito.
Crie um modelo de vista base do qual todos os modelos herdarão.
Sua página de layout pode aceitar isso como modelo.
Por fim, defina os dados no método de ação.
fonte
public class HomeController : BaseController
. Dessa forma, o código comum precisa ser gravado apenas uma vez e pode ser aplicado a todos os controladores.Eu usei o RenderAction html helper para fazer a navalha no layout.
Eu precisava disso para uma string simples. Portanto, minha ação retorna uma string e a anota com facilidade. Mas se você precisar de dados complexos, poderá retornar o PartialViewResult e model.
Você só precisa colocar o modelo no início da exibição parcial '_maPartialView.cshtml' que você criou
Em seguida, você pode usar os dados no modelo nessa vista parcial com html.
fonte
Outra opção é criar uma classe LayoutModel separada com todas as propriedades necessárias no layout e inserir uma instância dessa classe no ViewBag. Eu uso o método Controller.OnActionExecuting para preenchê-lo. Em seguida, no início do layout, você pode retirar esse objeto do ViewBag e continuar acessando esse objeto fortemente digitado.
fonte
OnActionExecuting
. Usar o ViewBag também significa que você perde a segurança do tipo no seu controlador, nunca é uma coisa boa.Presumivelmente, o principal caso de uso para isso é obter um modelo base para a visualização de todas (ou a maioria das) ações do controlador.
Dado isso, usei uma combinação de várias dessas respostas, o principal apoio da resposta de Colin Bacon.
É correto que isso ainda seja lógico do controlador, porque estamos preenchendo um modelo de visão para retornar a uma visão. Portanto, o local correto para colocar isso é no controlador.
Queremos que isso aconteça em todos os controladores, porque usamos isso para a página de layout. Estou usando-o para exibições parciais que são renderizadas na página de layout.
Também queremos o benefício adicional de um ViewModel fortemente tipado
Assim, eu criei um BaseViewModel e BaseController. Todos os controladores ViewModels herdarão do BaseViewModel e BaseController, respectivamente.
O código:
BaseController
Observe o uso de OnActionExecuted, conforme extraído desta postagem do SO
Página inicial
BaseViewModel
HomeViewModel
FooterModel
Layout.cshtml
_Nav.cshtml
Espero que isso ajude.
fonte
Você não precisa mexer em ações ou alterar o modelo, basta usar um controlador de base e converter o controlador existente no contexto de visualização do layout.
Crie um controlador base com os dados comuns desejados (título / página / local etc) e inicialização de ação ...
Verifique se todos os controladores usam o controlador base ...
Transmitir o controlador base existente a partir do contexto de visualização em sua
_Layout.cshml
página ...Agora você pode consultar os valores em seu controlador base na página de layout.
ATUALIZAR
Você também pode criar uma extensão de página que permita o uso
this
.Então você só precisa se lembrar de usar
this.Controller()
quando quiser o controlador.ou controlador específico que herda de
_BaseController
...fonte
se você quiser passar um modelo inteiro, faça o mesmo no layout:
e adicione isso no controlador:
fonte
Eu não acho que nenhuma dessas respostas seja flexível o suficiente para um aplicativo de nível corporativo grande. Não sou fã de usar demais o ViewBag, mas, neste caso, por flexibilidade, eu abriria uma exceção. Aqui está o que eu faria ...
Você deve ter um controlador de base em todos os seus controladores. Adicione seus dados de layout OnActionExecuting no seu controlador base (ou OnActionExecuted se desejar adiar isso) ...
Em seguida, no seu _Layout.cshtml, puxe seu ViewModel do ViewBag ...
Ou...
Isso não interfere na codificação dos controladores da sua página ou nos modelos de exibição.
fonte
MyLayoutViewModel
criado dinamicamente, como posso passar alguns parâmetros para oOnActionExecuting
método?base.OnActionExecuting(filterContext)
no seuOnActionExecuting
método !!!Criar uma vista de base que representa o modelo de vista de layout é uma abordagem terrível. Imagine que você deseja ter um modelo que represente a navegação definida no layout. Você faria
CustomersViewModel : LayoutNavigationViewModel
? Por quê? Por que você deve passar os dados do modelo de navegação por todos os modelos de exibição existentes na solução?O modelo de visualização de layout deve ser dedicado, por si só, e não deve forçar o restante dos modelos de visualização a depender dele.
Em vez disso, você pode fazer isso no seu
_Layout.cshtml
arquivo:Mais importante ainda, não precisamos
new LayoutViewModel()
e teremos todas as dependências queLayoutViewModel
foram resolvidas para nós.por exemplo
fonte
Scoped
objeto de modelo de layout no ASP..Net Core também.Outras respostas cobriram praticamente tudo sobre como podemos passar o modelo para a nossa página de layout. Mas eu encontrei uma maneira pela qual você pode passar variáveis para sua página de layout dinamicamente sem usar nenhum modelo ou exibição parcial em seu layout. Digamos que você tenha esse modelo -
E você deseja obter cidade e estado dinamicamente. Por exemplo
no seu index.cshtml, você pode colocar essas duas variáveis no ViewBag
E então, em seu layout.cshtml, você pode acessar essas variáveis do viewbag
fonte
Há outra maneira de lidar com isso. Talvez não seja o caminho mais limpo do ponto de vista arquitetônico, mas evita muita dor envolvida nas outras respostas. Simplesmente injete um serviço no layout do Razor e chame um método que obtenha os dados necessários:
Posteriormente, na exibição de layout:
Novamente, não é limpo em termos de arquitetura (obviamente o serviço não deve ser injetado diretamente na visualização), mas faz o trabalho.
fonte
@inject
é a melhor solução, na minha opinião.Você também pode fazer uso do RenderSection ; isso ajuda a injetar seus
Model
dados no_Layout
visualização.Você pode injetar
View Model
Dados,Json
,Script
,CSS
,HTML
etcNeste exemplo, estou injetando
Json
do meuIndex
View paraLayout
View.Index.chtml
_Layout.cshtml
Isso elimina a necessidade de criar uma base separada
View Model
.A esperança ajuda alguém.
fonte
o que eu fiz é muito simples e funciona
Declare a propriedade Static em qualquer controlador ou você pode criar uma classe de dados com valores estáticos, se desejar:
Esses valores podem ser atualizados pelos controladores com base nas operações. depois, você pode usá-los em seu _Layout
Em _layout.cshtml
fonte
Por que ninguém sugeriu métodos de extensão no ViewData?
Opção 1
Parece-me de longe a solução menos intrusiva e mais simples para o problema. Sem seqüências codificadas. Sem restrições impostas. Sem codificação mágica. Nenhum código complexo.
Definir dados na página
Opção 2
Outra opção, facilitando a declaração de campo.
Defina os dados na página. A declaração é mais fácil que a primeira opção, mas a sintaxe de uso é um pouco mais longa.
Opção # 3
Em seguida, você pode combinar isso com o retorno de um único objeto que contém todos os campos relacionados ao layout com seus valores padrão.
Definir dados na página
Esta terceira opção tem vários benefícios e acho que é a melhor opção na maioria dos casos:
Declaração mais simples de campos e valores padrão.
Sintaxe de uso mais simples ao definir vários campos.
Permite definir vários tipos de dados no ViewData (por exemplo, Layout, Cabeçalho, Navegação).
Permite código e lógica adicionais dentro da classe LayoutData.
PS Não se esqueça de adicionar o namespace de ViewDataExtensions em _ViewImports.cshtml
fonte
Você pode criar um arquivo navalha na pasta App_Code e acessá-lo nas suas páginas de exibição.
Projeto> Repository / IdentityRepository.cs
Projeto> App_Code / IdentityRepositoryViewFunctions.cshtml:
Projeto> Visualizações / Compartilhado / _Layout.cshtml (ou qualquer outro arquivo .cshtml)
fonte
em vez de passar por isso, você sempre pode usar outra abordagem que também é rápida
crie uma nova exibição parcial no Diretório compartilhado e chame sua exibição parcial em seu layout como
na sua visão parcial, você pode chamar seu banco de dados e executar o que quiser
supondo que você adicionou seu banco de dados do Entity Framework
fonte
É incrível que ninguém tenha dito isso aqui. Passar um viewmodel através de um controlador base é uma bagunça. Estamos usando reivindicações do usuário para passar informações para a página de layout (para mostrar dados do usuário na barra de navegação, por exemplo). Há mais uma vantagem. Os dados são armazenados por meio de cookies, portanto, não há necessidade de recuperar os dados em cada solicitação por meio de parciais. Basta fazer algumas "reivindicações de identidade de rede asp" no Google.
fonte
Você pode usar assim:
fonte