jquery - partialview - Devuelve Vista parcial y JSON desde ASP.NET MVC Action
return partialview (2)
Estoy seguro de que hay una variedad de formas de hacer esto. De forma manual renderizo la vista desde el controlador, y luego transfiero la vista renderizada como parte de mi respuesta JSON.
Esto preserva las responsabilidades de cada entidad. Las vistas todavía se encuentran utilizando el motor de visualización y se pueden reutilizar. El controlador sabe poco o nada sobre la vista más allá de su nombre y tipo de modelo.
Representación manual
public static class RenderHelper
{
public static string PartialView( Controller controller, string viewName, object model )
{
controller.ViewData.Model = model;
using( var sw = new StringWriter() )
{
var 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 );
viewResult.ViewEngine.ReleaseView( controller.ControllerContext, viewResult.View );
return sw.ToString();
}
}
}
En tu método de acción:
object model = null; // whatever you want
var obj = new {
someOtherProperty = "hello",
view = RenderHelper.PartialView( this, "_PartialName", model )
};
return Json( obj );
Tenga en cuenta que devolveré un tipo anónimo. Puede devolver cualquier tipo (serializable) que desee, siempre que tenga una propiedad de cadena para la vista procesada.
Pruebas
La prueba de una acción que utiliza la representación manual requiere una ligera modificación. Esto se debe a renderizar la vista un poco antes de lo que sería renderizado en la tubería de MVC.
Representación manual
- Ingrese el método de acción
- Renderizar vista explícitamente <- esto hará que sea difícil probar la acción de llamada
- Método de salida de acción
Renderizado automático
- Ingrese el método de acción
- Crear un resultado de vista
- Método de salida de acción
- Resultado de la vista de proceso (por lo tanto, representando la vista)
En otras palabras, nuestro proceso de renderizado manual inicia una variedad de otras operaciones que dificultan la prueba (como interactuar con el administrador de compilación para compilar la vista).
Suponiendo que desea probar el método de acción y no el contenido real de la vista, puede verificar si el código se está ejecutando o no en un entorno alojado.
public static string PartialView( Controller controller, string viewName, object model )
{
// returns false from a VS 2013 unit test, true from IIS
if( !HostingEnvironment.IsHosted )
{
// return whatever you want here
return string.Empty;
}
// continue as usual
}
Verificar HostingEnvironment.IsHosted
es barato (bajo el capó, es simplemente un cheque nulo).
Voy a presentar KnockoutJS en una aplicación existente. Mi plan es modificar / utilizar las vistas parciales existentes que ya hemos creado y vincularlas a los modelos de vista de JS con los atributos declarativos de Knockout. Cuando realizo una llamada AJAX a una acción, idealmente me gustaría que la acción devuelva tanto el código HTML de la vista parcial como el objeto JSON. Luego puedo llenar un div con el HTML, convertir el JSON en un objeto Knockout y vincularlo al HTML. Pero no puedo descifrar cómo devolver los dos de la acción.
Necesito el modelo de vista completa porque lo actualizaré y, finalmente, lo enviaré de vuelta al servidor.
Pensé en hacer que la acción devuelva la vista parcial (ya vinculada al modelo), y en la vista parcial, incluir javascript para convertir el modelo .Net en un objeto Knockout. Pero siento que esparcir el JS de esa manera es desordenado e imposible de mantener. Prefiero tener todo lo cerca de la llamada original de Ajax.
Supongo que otra alternativa es hacer dos llamadas de acción. Uno para el JSON y otro para la vista parcial. Pero tiene que haber un camino más suave.
¿Alguna idea sobre la mejor manera de hacer esto?
Podría crear una <input>
oculta en el parcial con un valor establecido en la cadena JSON del ViewModel. Luego, antes de renderizar la vista parcial, tome el valor JSON de ese campo y analícelo. Luego quítelo de la vista parcial, insértelo en su página y haga ko.applyBindingsToDescendants(viewModel, $("#parentElement")[0])
No estoy del todo seguro de cómo me siento acerca de este enfoque, y es solo una teoría. No lo he probado, pero sospecho que funcionará. Una trampa de botín que tendrías que tener en cuenta es que el navegador intente guardar en caché tu solicitud GET. En tu solicitud de ajax, te gustaría hacer:
$.ajax({
url: "/",
type: ''GET'',
cache: ''false''
});
O simplemente haga una solicitud $.post
. ( referencia )
Entonces esa es una opción.