Acceder a la propiedad modelo de MVC desde Javascript

147

Tengo el siguiente modelo que está envuelto en mi modelo de vista

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; }
}

¿Cómo accedo a una de las propiedades anteriores desde Javascript?

Intenté esto, pero me "indefiní"

var floorplanSettings = "@Model.FloorPlanSettings";
alert(floorplanSettings.IconsDirectory);
Referencia nula
fuente
55
Para ser claros, lo que está sucediendo es que está configurando el valor de la variable JavaScript al valor de la variable C # "Model.FloorPlanSettings", que será el valor .ToString () de esa clase (una cadena). Luego está intentando alertar a una propiedad de JavaScript llamada "IconsDirectory" en la variable de cadena de JavaScript que acaba de crear. No se define porque una cadena de JavaScript no tiene la propiedad "IconsDirectory".
Joel Cochran
Proporcionó un caso de prueba completo y explicó todos los escenarios de asignación de datos del Modelo a la variable de JavaScript,
Rajshekar Reddy
Esto no funciona fuera de la vista (cshtml). es decir, en un archivo externo .js al que hace referencia la vista.
Spencer Sullivan

Respuestas:

240

Puede tomar todo su modelo del lado del servidor y convertirlo en un objeto Javascript haciendo lo siguiente:

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

En su caso, si solo desea el objeto FloorPlanSettings, simplemente pase el Encodemétodo de esa propiedad:

var floorplanSettings = @Html.Raw(Json.Encode(Model.FloorPlanSettings));
Justin Helgerson
fuente
1
Solo para confirmar, no hay necesidad de agregar un; al final de esto? Porque recibo un mensaje de VS que indica que la declaración no se termina. Pero cuando trato de agregar; el código no se ejecuta
Referencia nula
1
¿Qué sabes? También tengo el mismo error en mis diversos proyectos. Simplemente ignóralo; es Visual Studio tratando de ayudar, pero está mal en este caso. El HTML y el script resultantes que se envían al navegador son correctos.
Justin Helgerson
1
Para mí, esto funcionó: var myModel = @ {@ Html.Raw (Json.Encode (Model));}
oculto el
1
No funciona si el modelo es el valor inicial (Crear página en lugar de Editar página) y se encuentra "ReferenceError: Modelo no definido".
Jack
2
En ASP.Net Core, Json.Serialize ()
Mohammed Noureldin
131

Contenido de la respuesta

1) Cómo acceder a los datos del Modelo en el bloque de código Javascript / Jquery en el .cshtmlarchivo

2) Cómo acceder a los datos del Modelo en el bloque de código Javascript / Jquery en el .jsarchivo

Cómo acceder a los datos del modelo en el bloque de código Javascript / Jquery en el .cshtmlarchivo

Hay dos tipos de Modelasignaciones de variables de C # a la variable de JavaScript.

  1. Asignación de propiedad - los tipos de datos básicos como int, string, DateTime(ex: Model.Name)
  2. Asignación de objetos : clases personalizadas o incorporadas (p. Ej. Model, Model.UserSettingsObj)

Veamos los detalles de estas dos tareas.

Para el resto de la respuesta, consideremos el siguiente AppUsermodelo como ejemplo.

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; }
}

Y los valores que asignamos a este modelo son

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

Asignación de propiedad

Usemos una sintaxis diferente para la asignación y observemos los resultados.

1) Sin envolver la asignación de propiedades entre comillas.

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

ingrese la descripción de la imagen aquí

Como puede ver, hay un par de errores, Rajy Truese consideran variables de JavaScript y, dado que no existen, es un variable undefinederror. Donde en cuanto a la variable dateTime el error esunexpected number números no pueden tener caracteres especiales, las etiquetas HTML se convierten en sus nombres de entidad para que el navegador no mezcle sus valores y el marcado HTML.

2) Ajuste de la asignación de propiedades en Cotizaciones.

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

ingrese la descripción de la imagen aquí

Los resultados son válidos, por lo que ajustar la asignación de propiedades entre comillas nos da una sintaxis válida. Pero tenga en cuenta que el número Ageahora es una cadena, por lo que si no lo desea, podemos eliminar las comillas y se representará como un tipo de número.

3) Usar @Html.Rawpero sin envolverlo entre comillas

 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);

ingrese la descripción de la imagen aquí

Los resultados son similares a nuestro caso de prueba 1. Sin embargo, el uso @Html.Raw()en la HTMLcadena nos mostró algún cambio. El HTML se retiene sin cambiar a sus nombres de entidad.

De los documentos Html.Raw ()

Envuelve el marcado HTML en una instancia de HtmlString para que se interprete como marcado HTML.

Pero aún tenemos errores en otras líneas.

4) Usar @Html.Rawy también envolverlo entre comillas

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)';

ingrese la descripción de la imagen aquí

Los resultados son buenos con todos los tipos. Pero nuestros HTMLdatos ahora están rotos y esto romperá los scripts. El problema es porque estamos usando comillas simples 'para envolver los datos e incluso los datos tienen comillas simples.

Podemos superar este problema con 2 enfoques.

1) use comillas dobles " "para ajustar la parte HTML. Como los datos internos solo tienen comillas simples. (Asegúrese de que después de ajustar con comillas dobles no haya "dentro de los datos también)

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

2) Escapar del significado del carácter en el código del lado del servidor. Me gusta

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

Conclusión de la asignación de propiedad

  • Use comillas para tipos de datos no numéricos.
  • No utilice comillas para el tipo de datos numérico.
  • Úselo Html.Rawpara interpretar sus datos HTML tal como están.
  • Cuide sus datos HTML para escapar de las citas que significan en el lado del servidor, o use una cita diferente a la de los datos durante la asignación a la variable javascript.

Asignación de objeto

Usemos una sintaxis diferente para la asignación y observemos los resultados.

1) Sin envolver la asignación de objetos entre comillas.

  var userObj = @Model; 

ingrese la descripción de la imagen aquí

Cuando asigna un objeto ac # a la variable javascript, se asignará el valor .ToString()de ese objeto. De ahí el resultado anterior.

2 Asignación de objeto de ajuste entre comillas

var userObj = '@Model'; 

ingrese la descripción de la imagen aquí

3) Uso Html.Rawsin comillas.

   var userObj = @Html.Raw(Model); 

ingrese la descripción de la imagen aquí

4) Usar Html.Rawjunto con citas

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

ingrese la descripción de la imagen aquí

No Html.Rawfue de mucha utilidad para nosotros al asignar un objeto a la variable.

5) Usar Json.Encode()sin comillas

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;
              };

Vemos algún cambio, vemos que nuestro modelo se está interpretando como un objeto. Pero hemos cambiado esos caracteres especiales entity names. Tampoco es útil utilizar la sintaxis anterior entre comillas. Simplemente obtenemos el mismo resultado entre comillas.

De los documentos de Json.Encode ()

Convierte un objeto de datos en una cadena que está en el formato JSON (JavaScript Object Notation).

Como ya ha encontrado este entity Nameproblema con la asignación de propiedades y si recuerda, lo superamos con el uso de Html.Raw. Así que probemos eso. Vamos a combinar Html.RawyJson.Encode

6) Uso Html.Rawy Json.Encodesin comillas.

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

El resultado es un 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"
 };

ingrese la descripción de la imagen aquí

7) Uso Html.Rawy Json.Encodeentre comillas.

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

ingrese la descripción de la imagen aquí

Como ve, envolver con comillas nos da datos JSON

Conslusión en la asignación de objetos

  • Use Html.Rawy Json.Encodeen combinación para asignar su objeto a la variable javascript como objeto JavaScript .
  • Úselo Html.Rawy Json.Encodeenvuélvalo quotespara obtener un JSON

Nota: Si ha observado que el formato de datos DataTime no es correcto. Esto se debe a que, como se dijo anteriormente, Converts a data object to a string that is in the JavaScript Object Notation (JSON) formatJSON no contiene un datetipo. Otras opciones para solucionar este problema es añadir otra línea de código para manejar este tipo solo usando javascipt Fecha) ( objeto

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


Cómo acceder a los datos del modelo en el bloque de código Javascript / Jquery en el .jsarchivo

La sintaxis de la maquinilla de afeitar no tiene significado en el .jsarchivo y, por lo tanto, no podemos usar directamente nuestro Modelo en un .jsarchivo. Sin embargo, hay una solución.

1) La solución está utilizando variables globales de JavaScript .

Tenemos que asignar el valor a una variable global javascipt restringidos y luego utilizar esta variable dentro de todos bloque de código de sus .cshtmly .jsarchivos. Entonces la sintaxis sería

<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>

Con esto en su lugar, podemos usar las variables userObjy userJsonObjcomo y cuando sea necesario.

Nota: Yo personalmente no sugiero usar variables globales, ya que es muy difícil de mantener. Sin embargo, si no tiene otra opción, puede usarla con una convención de nomenclatura adecuada ... algo así userAppDetails_global.

2) Usando la función () o closure Envuelva todo el código que depende de los datos del modelo en una función. Y luego ejecute esta función desde el .cshtmlarchivo.

external.js

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

.cshtml expediente

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

Nota: Su archivo externo debe ser referenciado antes de la secuencia de comandos anterior. De lo contrario, la userDataDependentfunción no está definida.

También tenga en cuenta que la función también debe tener un alcance global. Entonces, cualquiera de las soluciones tenemos que lidiar con jugadores de alcance global.

Rajshekar Reddy
fuente
¿Se puede actualizar la propiedad Model en javascript y enviarla al método de acción del controlador?
@sortednoun sí, puedes, puedes enviar los datos modificados de un formulario, o si no quieres volver a cargar la página, puedes usar AJAX
Rajshekar Reddy
No estaba usando ajax, y solo intenté modificar la propiedad del modelo en javascript. pero al enviar el formulario, este cambio no se reflejó en el modelo. Estaba haciendo algo como: var model = @ Html.Raw (Json.Encode (Model)); model.EventCommand = "valor actualizado"; Me dio el modelo correctamente y el valor actualizado, pero al enviar el cambio faltaba en el método de acción. (A pesar de que hice lo mismo usando control HTML ocultos y con destino a EventCommand y actualizada su valor en javascript, pero se preguntó si podría hacer iguales directamente al modelo.?)
@sortednoun Entendí tu punto, var model = @Html.Raw(Json.Encode(Model));esto creará un objeto javascript model que no tiene conexión con el Modelo C # que pasas a la vista. De hecho, no habrá una vez que se haya presentado Modella vista. Por lo tanto, el formulario en la interfaz de usuario no tendrá idea de los cambios en los datos del objeto javascript. Ahora debe pasar todo este modelo modificado al controlador a través de AJAX, o debe actualizar el valor de sus controles de entrada en el formulario usando javascript.
Rajshekar Reddy
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 declaración ... no hay EventCommand en MVC, es para Webforms donde hay una conexión entre la UI y las acciones del servidor, en MVC todo está separado. La única forma de interactuar con el controlador es a través de AJAX o Enviar formulario o Solicitud de nueva página (recargar también)
Rajshekar Reddy
21

prueba esto: (te perdiste las comillas simples)

var floorplanSettings = '@Html.Raw(Json.Encode(Model.FloorPlanSettings))';
danmbuen
fuente
1
@JuanPieterse con comillas le da un sin JSONcomillas le da un javascript Object. Mira mi respuesta en el mismo hilo para más detalles. stackoverflow.com/a/41312348/2592042
Rajshekar Reddy
Eso no es cierto, la solución @danmbuen funcionó en mi caso, tuve problemas y envolverlo entre comillas simples funcionó de maravilla, GRACIAS;)
Dimitri
4

Envolver la propiedad del modelo alrededor de los padres funcionó para mí. Todavía tiene el mismo problema con Visual Studio quejándose del punto y coma, pero funciona.

var closedStatusId = @(Model.ClosedStatusId);
La logística
fuente
0

Si se genera el error "ReferenceError: el modelo no está definido" , puede intentar utilizar el siguiente 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 esto ayude...

Murat Yıldız
fuente
0

Sé que es demasiado tarde, pero esta solución funciona perfectamente para .NET Framework y .net core:

@ System.Web.HttpUtility.JavaScriptStringEncode ()

Amer Jamaeen
fuente