2010-07-29 21 views
128

Soy un desarrollador de Java nuevo en .NET. Estoy trabajando en un proyecto .Net MVC2 donde quiero tener una vista parcial para envolver un widget. Cada objeto del widget JS tiene un objeto de datos JSON que se completará con los datos del modelo. Luego, los métodos para actualizar estos datos se vinculan a los eventos cuando los datos se cambian en el widget o si esos datos se cambian en otro widget. El código es algo como esto.ASP.NET MVC: Cómo convertir el modelo de vista en el objeto Json

myController

virtual public ActionResult DisplaySomeWidget(int id) 
{ 
    SomeModelView returnData = someDataMapper.getbyid(1); 

    return View(myview, returnData); 
} 

myview.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SomeModelView>" %> 

    <script type="text/javascript"> 

     //creates base widget object; 
     var thisWidgetName= new Widget(); 

     thisWidgetName.updateTable= function() { 
      // UpdatesData 
     }; 

      $(document).ready(function() { 
       thisWidgetName.data = <% converttoJSON(model) %> 
       $(document).bind('DATA_CHANGED', thisWidgetName.updateTable()); 
      }); 
     </script> 

    <div><%:model.name%></div> 

Lo que no sé es cómo enviar los datos a través de como SomeModelView y luego ser capaz de utilizar eso para poblar el widget, así como convertir eso a Json. Parecía que había algunas maneras realmente simples de hacerlo en el controlador pero no en la vista. Me imagino que esta es una pregunta básica que he estado haciendo durante unas horas tratando de hacer esta astilla.

+1

Sé que esto es una cuestión de edad. Pero a partir de hoy hay mejores formas de hacerlo. No mezcle JSON en línea con el resultado de su Vista. JSON es fácilmente seriales a través de AJAX y se puede tratar como objetos. Cualquier cosa en JavaScript debería estar separada de la Vista. Puede devolver modelos fácilmente sin ningún esfuerzo a través de un controlador. – ppumkin

Respuesta

296

En mvc3 con la navaja @Html.Raw(Json.Encode(object)) parece hacer el truco.

+1

+1 Utilicé Html.Raw, pero nunca encontré Json.Encode y usé JavaScriptSerializer para agregar la cadena en el controlador al modelo de vista – AaronLS

+0

Eso funciona como un amuleto. Creo que funciona mejor en la vista en ciertos casos. – PJH

+4

Este enfoque funciona incluso cuando desea pasar el JSON resultante a Javascript. Razor se queja con los garabatos verdes si coloca el código @ Html.Raw (...) como un parámetro de función dentro de las etiquetas

4

Puede utilizar Json de la acción directa,

Su acción sería algo como esto:

virtual public JsonResult DisplaySomeWidget(int id) 
{ 
    SomeModelView returnData = someDataMapper.getbyid(1); 
    return Json(returnData); 
} 

Editar

Sólo vio que se asume que este es el Model de un Ver para que lo anterior no sea estrictamente correcto, tendría que hacer una llamada Ajax al método del controlador para obtener esto, el ascx no lo haría entonces tengo un modelo per se, dejaré mi código en caso de que sea útil para usted y puede enmendar la llamada

+1

pero no puede renderizar esto en la vista, tendría que hacer una segunda llamada ajax –

+0

@Andrew Bullock acaba de editar una vez que realicé – Pharabus

+0

Gracias, originalmente estaba haciendo esto usando una llamada jQuery get json y estaba planeando tener el HTML los elementos se pueblan a sí mismos de json. Sin embargo, el patrón que estamos siguiendo ahora es que nuestras vistas deberían devolver un modelView y esa es la forma más fácil de llenar elementos HTML básicos como tablas, etc. Podría enviar los mismos datos en formato JSON que ViewData, pero parece un desperdicio. –

28

Bien hecho, acaba de comenzar a usar MVC y ha encontrado su primer gran falla.

No desea realmente convertirlo a JSON en la vista, y realmente no desea convertirlo en el controlador, ya que ninguna de estas ubicaciones tiene sentido. Lamentablemente, estás atrapado en esta situación.

Lo mejor que he encontrado que hacer es enviar el JSON a la vista en un modelo de vista, así:

var data = somedata; 
var viewModel = new ViewModel(); 
var serializer = new JavaScriptSerializer(); 
viewModel.JsonData = serializer.Serialize(data); 

return View("viewname", viewModel); 

a continuación, utilizar

<%= Model.JsonData %> 

en su opinión. Tenga en cuenta que el .NET JavaScriptSerializer estándar es bastante basura.

hacerlo en el controlador al menos hace que sea comprobable (aunque no exactamente igual que el anterior - es probable que desee tomar un ISerializer como una dependencia para que pueda burlarse de ella)

actualización también, con respecto a su JavaScript , sería una buena práctica para envolver TODO el widget JS tiene por encima de este modo:

(
    // all js here 
)(); 

esta manera si pones varios widgets en una página, no se va a conflictos (a menos que necesite acceder a los métodos desde otro lugar en la página, pero en ese caso debe registrar el widget wi el framework de widgets de todos modos).Puede que no sea un problema ahora, pero sería una buena práctica agregar los corchetes ahora para ahorrar muchos esfuerzos en el futuro cuando se convierta en un requisito, también es una buena práctica de OO encapsular la funcionalidad.

+1

Esto parece interesante. Iba a hacer una copia de los datos como json y pasarla como viewData, pero de esta manera parece más interesante. Jugaré con esto y te dejaré saber. Por cierto, esta es la primera vez que publico una pregunta sobre Stackoverflow y me tomó aproximadamente 5 minutos obtener buenas respuestas, ¡eso es increíble! –

+0

¿Qué pasa con 'JavaScriptSerializer'? –

+0

nada _rong_ con eso, simplemente no es personalizable, si quieres cualquier formato de valor personalizado tienes que hacerlo de antemano, básicamente haciendo de todo una cadena :(esto es más prominente con las fechas. Sé que hay soluciones fáciles, pero no deberían ¡Necesario! –

0

Andrew tuvo una gran respuesta, pero yo quería tocarlo un poco. La forma en que esto es diferente es que me gusta que mis ModelViews no tengan datos generales en ellas. Solo los datos para el objeto. Parece que ViewData se ajusta a la factura de los datos generales, pero por supuesto soy nuevo en esto. Sugiero hacer algo como esto.

controlador

virtual public ActionResult DisplaySomeWidget(int id) 
{ 
    SomeModelView returnData = someDataMapper.getbyid(1); 
    var serializer = new JavaScriptSerializer(); 
    ViewData["JSON"] = serializer.Serialize(returnData); 
    return View(myview, returnData); 
} 

Ver

//create base js object; 
var myWidget= new Widget(); //Widget is a class with a public member variable called data. 
myWidget.data= <%= ViewData["JSON"] %>; 

Lo que esto hace para usted es que le da los mismos datos en su JSON como en su modelview por lo que potencialmente puede devolver el JSON de vuelta a su controlador y tendría todas las partes. Esto es similar a solo solicitarlo a través de JSONRequest; sin embargo, requiere una llamada menos, por lo que le ahorra esa sobrecarga. Por cierto, esto es funky para Dates, pero parece ser otro hilo.

18

Me pareció que estaba bastante bien para hacerlo así (el uso de la vista):

@Html.HiddenJsonFor(m => m.TrackingTypes) 

Aquí es la clase de método de ayuda Extensión de acuerdo:

public static class DataHelpers 
{ 
    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) 
    { 
     return HiddenJsonFor(htmlHelper, expression, (IDictionary<string, object>) null); 
    } 

    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes) 
    { 
     return HiddenJsonFor(htmlHelper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); 
    } 

    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes) 
    { 
     var name = ExpressionHelper.GetExpressionText(expression); 
     var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 

     var tagBuilder = new TagBuilder("input"); 
     tagBuilder.MergeAttributes(htmlAttributes); 
     tagBuilder.MergeAttribute("name", name); 
     tagBuilder.MergeAttribute("type", "hidden"); 

     var json = JsonConvert.SerializeObject(metadata.Model); 

     tagBuilder.MergeAttribute("value", json); 

     return MvcHtmlString.Create(tagBuilder.ToString()); 
    } 
} 

No es super sofisticado, pero resuelve el problema de dónde colocarlo (en Controlador o a la vista?) La respuesta es obviamente: ninguno;)

+0

Esto fue agradable y limpio en mi opinión y envuelto en un ayudante reutilizable. Saludos, J – John

0

La extensión de la gran respuesta de Dave. Puede crear un simple HtmlHelper.

public static IHtmlString RenderAsJson(this HtmlHelper helper, object model) 
{ 
    return helper.Raw(Json.Encode(model)); 
} 

Y en su opinión:

@Html.RenderAsJson(Model) 

De esta manera se puede centralizar la lógica para crear el JSON si, por alguna razón, le gustaría cambiar la lógica más tarde.

3

@ Html.Raw (Json.Encode (objeto)) se puede utilizar para convertir la ventana de objetos modal a JSON

Cuestiones relacionadas