2009-07-25 16 views
29

¿Puedo devolver un resultado Json que también contenga una vista procesada?ASP.NET MVC - Combine el resultado Json con ViewResult

Lo necesito para devolver el nuevo ID de un formulario enviado junto con su HTML y algunas otras propiedades.

También puede ser útil cuando necesito devolver dos (o más) resultados de vista de una acción dentro de un objeto Json.

Gracias!

Respuesta

39

También puede hacer que un PartialViewResult en una cadena, y luego pasar a través de esta cadena JSON a la vista, lo que hace que en tu página usando jQuery.

Puedes verlo en esta publicación: http://www.atlanticbt.com/blog/asp-net-mvc-using-ajax-json-and-partialviews/.

He creado una extensión para que sea más fácil:

public static class MvcHelpers 
{ 
    public static string RenderPartialView(this Controller controller, string viewName, object model) 
    { 
     if (string.IsNullOrEmpty(viewName)) 
      viewName = controller.ControllerContext.RouteData.GetRequiredString("action"); 

     controller.ViewData.Model = model; 
     using (var sw = new StringWriter()) 
     { 
      ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName); 
      var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw); 
      viewResult.View.Render(viewContext, sw); 

      return sw.GetStringBuilder().ToString(); 
     } 
    } 
} 

En mi controlador de la llamo de la siguiente manera:

const string msg = "Item succesfully updated!"; 
return new JsonResult 
      { 
       Data = new 
          { 
           success = true, 
           message = msg, 
           view = this.RenderPartialView("ProductItemForm", model) 
          }, 
       JsonRequestBehavior = JsonRequestBehavior.AllowGet 
      }; 

Donde "este" es el controlador en el caso " ProductItemForm" es mi opinión y "modelo" es mi objeto productItem :)

esperanza esto ayuda;)

+1

Me gusta este enfoque. Agregué la clase RenderPartialView a mi controlador base, así que lo hago a menudo. – jsalwen

0

Esto podría ser un poco hacky (y estoy escribiendo sobre mi cabeza) pero es posible que desee crear su propia subclase de ActionResult y también implementar un ResultFilter que intercepte estos tipos específicos de ActionResult y represente el relevante Visualiza y completa un JsonResult y lo devuelve.

Por ejemplo, puede definir:

public CompoundResult: ActionResult 
{ 
    public string ViewName { get; set; } 
    public JsonResult JsonResult { get; set; } 
    public CompoundResult(string viewName, JsonResult jsonResult) 
    { 
     ViewName = viewName; 
     JsonResult = jsonResult; 
    } 
} 

y luego en una ResultFilter, renderizar la vista correspondiente y fusionarla en el lugar correspondiente en el JsonResult y finalmente devolver el JsonResult al cliente.

Aparte de todo esto, es posible que desee cambiar su enfoque de cómo hacer esto, por ejemplo. puede tratar de devolver una vista completa (es decir, HTML) de su acción, una parte de la cual es la vista que desea devolver, pero que también incluye información adicional que de otro modo habría estado en su objeto JSON. Puede extraer los componentes relevantes del HTML devuelto utilizando operaciones simples de jQuery en el lado del cliente.

+0

¿Puede explicarme más sobre el filtro de resultados? es exactamente lo que yo qué; crear un ActionResult personalizado ... – Benoit

1

En el primer caso, creo que puede simplemente devolver HTML, pero incrustar los datos en el formulario devuelto. Use jQuery para acceder a los datos en su exitosa devolución de llamada.

$.ajax({ 
    url: '<%= Url.Action("MyAction")', 
    dataType: 'html', 
    data: $('form').serialize(), 
    success: function(data) { 
       $('form').html(data); 
       var id = $('form').find('input#formId[type=hidden]').val(); 
      } 
}); 

En el segundo caso, una visión compartida que tiene dos o más ViewNames y utiliza renderPartial es probablemente una mejor solución que la devolución de HTML a través de JSON.

Multiview.aspx

... 
<% foreach (string viewName in Model.Views) 
    { 
     Html.RenderPartial(viewName); 
    } 
%> 

Luego, en su acción:

public ActionResult MyAction(...) 
{ 
    ... set up model with data 
    model.Views = new List<string> { "View1", "View2" }; 

    return View("Multiview", model); 
} 
1

He estado pensando en este problema por un tiempo. Mi solución es similar a devolver el HTML de vista parcial como una cadena JSON, pero al revés. Devuelve una vista parcial con JSON incrustado en ella.No me gustó este enfoque hasta que jQuery 1.4.3 fusionó su método .data() con el atributo de datos HTML 5. Esto hace que sea mucho más fácil generar JSON dentro de una vista ASP.NET MVC y leerlo a través de jQuery.

Ver ejemplo ... No es perfecto, pero me gusta mucho más que crear entradas de formularios ocultos o ayudantes que representen la vista parcial antes de devolverla.

Vista parcial:

<div id="content"> 
    <h1>Some Title</h1> 
    <p>Ipsum Lorem</p> 
</div> 
<div id="dataDiv" data-stuff='{ "name": "Jason", "color": "Blue"}'></div> 

JavaScript que lee el JSON

$(document).ready(function() { 
    var name = $('#dataDiv').data('stuff').name; 
    var color = $('#dataDiv').data('stuff').color; 
    alert(name + ' ' + color); 
}); 

Esto puede parecer ir contra el "principio de responsabilidad individual" (si se aplica a las vistas) . Sin embargo, si su aplicación requiere que se transmitan ambos datos en una respuesta, entonces no veo nada malo en ello. Y siempre que su modelo esté construido correctamente, no irá en contra de ningún principio de diseño.

Cuestiones relacionadas