Acessando a propriedade de modelo do MVC a partir de Javascript

147

Eu tenho o seguinte modelo, que está envolvido no meu modelo de exibição

public class FloorPlanSettingsModel
{
    public int Id { get; set; }
    public int? MainFloorPlanId { get; set; }
    public string ImageDirectory { get; set; }
    public string ThumbnailDirectory { get; set; }
    public string IconsDirectory { get; set; }
}

Como acesso uma das propriedades acima do Javascript?

Eu tentei isso, mas fiquei "indefinido"

var floorplanSettings = "@Model.FloorPlanSettings";
alert(floorplanSettings.IconsDirectory);
Referência nula
fonte
5
Só para esclarecer, o que está acontecendo é que você está configurando o valor da variável JavaScript para o valor da variável C # "Model.FloorPlanSettings", que será o valor .ToString () dessa classe (uma string). Então você está tentando alertar uma propriedade JavaScript chamada "IconsDirectory" na variável de string JavaScript que você acabou de criar. Você fica indefinido porque uma sequência de JavaScript não possui a propriedade "IconsDirectory".
Joel Cochran
Forneceu um caso de teste completo e explicou todos os cenários de atribuição de dados do modelo à variável javascript,
Rajshekar Reddy
Isso não funciona fora da visualização (cshtml). ou seja, em um arquivo .js externo referenciado pela exibição.
Spencer Sullivan

Respostas:

240

Você pode pegar todo o modelo do lado do servidor e transformá-lo em um objeto Javascript, fazendo o seguinte:

var model = @Html.Raw(Json.Encode(Model));

No seu caso, se você deseja apenas o objeto FloorPlanSettings, basta passar o Encodemétodo nessa propriedade:

var floorplanSettings = @Html.Raw(Json.Encode(Model.FloorPlanSettings));
Justin Helgerson
fonte
1
Apenas para confirmar, não há necessidade de adicionar um; no final disso? Porque recebo um aviso do VS informando que a instrução não foi encerrada. Mas quando eu tento adicionar; o código não roda
Referência nula
1
O que você sabe, eu tenho o mesmo erro em meus vários projetos também. Ignore isso; é o Visual Studio tentando ajudar, mas está errado neste caso. O HTML resultante e o script enviado ao navegador estão corretos.
Justin Helgerson
1
Para mim, isso funcionou: var myModel = @ {@ Html.Raw (Json.Encode (Model));}
oculto
1
Não funcionará se o modelo for o valor inicial (página Criar em vez de página Editar) e "ReferenceError: O modelo não está definido" for encontrado.
13136 Jack
2
No ASP.Net Core, Json.Serialize ()
Mohammed Noureldin
131

Conteúdo da resposta

1) Como acessar os dados do modelo no bloco de código Javascript / Jquery no .cshtmlarquivo

2) Como acessar os dados do modelo no bloco de código Javascript / Jquery no .jsarquivo

Como acessar os dados do modelo no bloco de código Javascript / Jquery no .cshtmlarquivo

Existem dois tipos de Modelatribuições c # variable ( ) à variável JavaScript.

  1. Atribuição de propriedade - tipos de dados básicos, como int, string, DateTime(ex: Model.Name)
  2. De atribuição de objetos - personalizado ou aulas embutido (ex: Model, Model.UserSettingsObj)

Vamos analisar os detalhes dessas duas atribuições.

Para o restante da resposta, vamos considerar o AppUsermodelo abaixo como exemplo.

public class AppUser
{
    public string Name { get; set; }
    public bool IsAuthenticated { get; set; }
    public DateTime LoginDateTime { get; set; }
    public int Age { get; set; }
    public string UserIconHTML { get; set; }
}

E os valores que atribuímos a este modelo são

AppUser appUser = new AppUser
{
    Name = "Raj",
    IsAuthenticated = true,
    LoginDateTime = DateTime.Now,
    Age = 26,
    UserIconHTML = "<i class='fa fa-users'></i>"
};

Atribuição de propriedade

Vamos usar sintaxe diferente para atribuição e observar os resultados.

1) Sem agrupar a atribuição de propriedades entre aspas.

var Name = @Model.Name;  
var Age = @Model.Age;
var LoginTime = @Model.LoginDateTime; 
var IsAuthenticated = @Model.IsAuthenticated;   
var IconHtml = @Model.UserIconHTML;  

insira a descrição da imagem aqui

Como você pode ver, existem alguns erros, Raje Truesão consideradas variáveis ​​javascript e, como elas não existem, é um variable undefinederro. Onde, quanto à variável dateTime, o erro é que os unexpected numbernúmeros não podem ter caracteres especiais, as tags HTML são convertidas em nomes de entidades para que o navegador não misture seus valores e a marcação HTML.

2) Atribuição de propriedades de agrupamento entre aspas.

var Name = '@Model.Name';
var Age = '@Model.Age';
var LoginTime = '@Model.LoginDateTime';
var IsAuthenticated = '@Model.IsAuthenticated';
var IconHtml = '@Model.UserIconHTML'; 

insira a descrição da imagem aqui

Os resultados são válidos. Portanto, agrupar a atribuição de propriedade entre aspas nos dá uma sintaxe válida. Mas observe que o número Ageagora é uma string; portanto, se você não quiser, podemos apenas remover as aspas e elas serão renderizadas como um tipo de número.

3) Usando @Html.Rawmas sem colocá-lo entre aspas

 var Name = @Html.Raw(Model.Name);
 var Age = @Html.Raw(Model.Age);
 var LoginTime = @Html.Raw(Model.LoginDateTime);
 var IsAuthenticated = @Html.Raw(Model.IsAuthenticated);
 var IconHtml = @Html.Raw(Model.UserIconHTML);

insira a descrição da imagem aqui

Os resultados são semelhantes ao nosso caso de teste 1. No entanto, o uso @Html.Raw()da HTMLstring nos mostrou algumas mudanças. O HTML é mantido sem alterar os nomes de entidade.

Dos documentos Html.Raw ()

Envolve a marcação HTML em uma instância HtmlString para que seja interpretada como marcação HTML.

Mas ainda temos erros em outras linhas.

4) Usando @Html.Rawe também envolvendo-o entre aspas

var Name ='@Html.Raw(Model.Name)';
var Age = '@Html.Raw(Model.Age)';
var LoginTime = '@Html.Raw(Model.LoginDateTime)';
var IsAuthenticated = '@Html.Raw(Model.IsAuthenticated)';
var IconHtml = '@Html.Raw(Model.UserIconHTML)';

insira a descrição da imagem aqui

Os resultados são bons com todos os tipos. Mas nossos HTMLdados agora estão quebrados e isso quebrará os scripts. O problema é que estamos usando aspas simples 'para agrupar os dados e até os dados possuem aspas simples.

Podemos superar esse problema com duas abordagens.

1) use aspas duplas " "para quebrar a parte HTML. Como os dados internos têm apenas aspas simples. (Certifique-se de que, após agrupar aspas duplas, também não haja "dados)

  var IconHtml = "@Html.Raw(Model.UserIconHTML)";

2) Escape do significado do caractere no código do lado do servidor. Gostar

  UserIconHTML = "<i class=\"fa fa-users\"></i>"

Conclusão da cessão de propriedades

  • Use aspas para dataType não numérico.
  • Não use aspas para dataType numérico.
  • Use Html.Rawpara interpretar seus dados HTML como estão.
  • Cuide dos seus dados HTML para escapar do significado das aspas no lado do servidor ou use uma cotação diferente da dos dados durante a atribuição à variável javascript.

Atribuição de objeto

Vamos usar sintaxe diferente para atribuição e observar os resultados.

1) Sem agrupar a atribuição do objeto entre aspas.

  var userObj = @Model; 

insira a descrição da imagem aqui

Quando você atribui um objeto ac # à variável javascript, o valor .ToString()desse objeto será atribuído. Daí o resultado acima.

2 Empacotando a atribuição de objeto entre aspas

var userObj = '@Model'; 

insira a descrição da imagem aqui

3) Usando Html.Rawsem aspas.

   var userObj = @Html.Raw(Model); 

insira a descrição da imagem aqui

4) Usando Html.Rawjunto com aspas

   var userObj = '@Html.Raw(Model)'; 

insira a descrição da imagem aqui

Não Html.Rawfoi muito útil para nós ao atribuir um objeto à variável.

5) Usando Json.Encode()sem aspas

var userObj = @Json.Encode(Model); 

//result is like
var userObj = {&quot;Name&quot;:&quot;Raj&quot;,
               &quot;IsAuthenticated&quot;:true,
               &quot;LoginDateTime&quot;:&quot;\/Date(1482572875150)\/&quot;,
               &quot;Age&quot;:26,
               &quot;UserIconHTML&quot;:&quot;\u003ci class=\&quot;fa fa-users\&quot;\u003e\u003c/i\u003e&quot;
              };

Nós vemos algumas mudanças, vemos que nosso modelo está sendo interpretado como um objeto. Mas nós transformamos esses caracteres especiais entity names. Também é inútil agrupar a sintaxe acima entre aspas. Simplesmente obtemos o mesmo resultado entre aspas.

Dos documentos de Json.Encode ()

Converte um objeto de dados em uma sequência que está no formato JavaScript Object Notation (JSON).

Como você já encontrou esse entity Nameproblema com a atribuição de propriedades e, se você se lembra, nós o superamos com o uso de Html.Raw. Então, vamos tentar isso. Vamos combinar Html.RaweJson.Encode

6) Usando Html.Rawe Json.Encodesem aspas.

var userObj = @Html.Raw(Json.Encode(Model));

Resultado é um objeto Javascript válido

 var userObj = {"Name":"Raj",
     "IsAuthenticated":true,
     "LoginDateTime":"\/Date(1482573224421)\/",
     "Age":26,
     "UserIconHTML":"\u003ci class=\"fa fa-users\"\u003e\u003c/i\u003e"
 };

insira a descrição da imagem aqui

7) Usando Html.Rawe Json.Encodeentre aspas.

var userObj = '@Html.Raw(Json.Encode(Model))';

insira a descrição da imagem aqui

Como você vê, o agrupamento com aspas nos fornece dados JSON

Conslusão na atribuição de objetos

  • Use Html.Rawe Json.Encodeem combinação para atribuir seu objeto à variável javascript como objeto JavaScript .
  • Use Html.Rawe Json.Encodeenvolva-o também quotespara obter um JSON

Nota: Se você observou o formato de dados DataTime não está correto. Isso ocorre porque, como dito anteriormente, o Converts a data object to a string that is in the JavaScript Object Notation (JSON) formatJSON não contém um datetipo. Outras opções para corrigir isso são adicionar outra linha de código para manipular esse tipo sozinho usando o objeto javascipt Date ()

var userObj.LoginDateTime = new Date('@Html.Raw(Model.LoginDateTime)'); 
//without Json.Encode


Como acessar os dados do modelo no bloco de código Javascript / Jquery no .jsarquivo

A sintaxe do Razor não tem significado no .jsarquivo e, portanto, não podemos usar diretamente nosso Modelo dentro de um .jsarquivo. No entanto, há uma solução alternativa.

1) A solução está usando variáveis ​​globais javascript .

Temos que atribuir o valor a uma variável javascipt com escopo global e depois usá-la em todos os blocos de código dos seus arquivos .cshtmle .js. Portanto, a sintaxe seria

<script type="text/javascript">
  var userObj = @Html.Raw(Json.Encode(Model)); //For javascript object
  var userJsonObj = '@Html.Raw(Json.Encode(Model))'; //For json data
</script>

Com isso, podemos usar as variáveis userObje userJsonObjcomo e quando necessário.

Nota: Eu pessoalmente não sugiro o uso de variáveis ​​globais, pois fica muito difícil para manutenção. No entanto, se você não tiver outra opção, poderá usá-la com uma convenção de nomenclatura adequada userAppDetails_global.

2) Usando a função () ou closure Quebra todo o código que depende dos dados do modelo em uma função. E, em seguida, execute esta função do .cshtmlarquivo

external.js

 function userDataDependent(userObj){
  //.... related code
 }

.cshtml Arquivo

 <script type="text/javascript">
  userDataDependent(@Html.Raw(Json.Encode(Model))); //execute the function     
</script>

Nota: Seu arquivo externo deve ser referenciado antes do script acima. Caso contrário, a userDataDependentfunção é indefinida.

Observe também que a função também deve estar no escopo global. Portanto, qualquer uma das soluções que temos para lidar com players com escopo global.

Rajshekar Reddy
fonte
A propriedade Model pode ser atualizada em javascript e enviar para o método de ação do controlador?
@sortednoun sim você pode, você pode enviar de volta os dados modificados de uma forma ou se você não quer para recarregar a página, então você pode fazer uso de AJAX
Rajshekar Reddy
Eu não estava usando ajax e apenas tentei modificar a propriedade do modelo em javascript. mas, ao enviar o formulário, essa alteração não foi refletida no modelo. Eu estava fazendo algo como: var model = @ Html.Raw (Json.Encode (Model)); model.EventCommand = "updatedvalue"; Ele me deu o modelo corretamente e o valor atualizado, mas ao enviar a alteração estava faltando no método de ação. (Embora eu fiz a mesma coisa usando o controle HTML oculto e ligou-o a EventCommand e atualizado seu valor em javascript Mas se perguntando se poderia fazer mesmo diretamente ao modelo.?)
@sortednoun Entendi seu ponto, var model = @Html.Raw(Json.Encode(Model));isso criará um objeto javascript model que não tem conexão com o modelo C # que você passa para a visualização. De fato, não haverá Modelapós a exibição da exibição. Portanto, o formulário na interface do usuário não terá idéia das alterações nos dados do objeto javascript. Agora você precisa passar todo esse modelo modificado para o controlador via AJAX, ou atualizar o valor dos seus controles de entrada no formulário usando javascript.
Rajshekar Reddy 02/02
Although I did the same thing using hidden Html control and bound it to EventCommand and updated it's value in javascript. But wondering if could do same directly to model?para esta declaração .. não existe EventCommand no MVC, é para Webforms onde há uma conexão entre a interface do usuário e as ações do servidor. No MVC, tudo é separado. Única maneira de você interagir com o controlador é através de AJAX ou Form Submit ou Nova solicitação de página (de recarga também)
Rajshekar Reddy
21

tente o seguinte: (você perdeu as aspas simples)

var floorplanSettings = '@Html.Raw(Json.Encode(Model.FloorPlanSettings))';
danmbuen
fonte
1
@JuanPieterse com citações fornece a você JSONsem citações fornece a javascript Object. Verifique minha resposta no mesmo tópico para obter mais detalhes. stackoverflow.com/a/41312348/2592042
Rajshekar Reddy
Isso não é verdade, a solução @danmbuen funcionou no meu caso, eu tenho problemas e envolvê-lo entre aspas simples funcionou como um encanto, OBRIGADO;)
Dimitri
4

Envolvendo a propriedade model em torno de parens funcionou para mim. Você ainda tem o mesmo problema com o Visual Studio reclamando sobre o ponto-e-vírgula, mas funciona.

var closedStatusId = @(Model.ClosedStatusId);
FROgistics
fonte
0

Se o erro "ReferenceError: Model is not defined" for gerado, você poderá tentar usar o seguinte método:

$(document).ready(function () {

    @{  var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
         var json = serializer.Serialize(Model);
    }

    var model = @Html.Raw(json);
    if(model != null && @Html.Raw(json) != "undefined")
    {
        var id= model.Id;
        var mainFloorPlanId = model.MainFloorPlanId ;
        var imageDirectory = model.ImageDirectory ;
        var iconsDirectory = model.IconsDirectory ;
    }
});

Espero que isto ajude...

Murat Yıldız
fonte
0

Sei que é tarde demais, mas esta solução está funcionando perfeitamente para a estrutura .net e o núcleo .net:

@ System.Web.HttpUtility.JavaScriptStringEncode ()

Amer Jamaeen
fonte