2009-05-26 27 views
17

Tengo una aplicación MVC con bastantes acciones de controlador que se llaman usando Ajax (jQuery) y devuelven contenido de vistas parciales que actualiza una parte de la pantalla. Pero lo que preferiría es devolverle algo así a JSON.ASP MVC Ver contenido como JSON

return Json(new { 
    Result = true, 
    Message = "Item has been saved", 
    Content = View("Partial") 
}); 

Donde el HTML es solo una propiedad del Json. Lo que esto significa es que necesito recuperar el HTML que es renderizado por el método View. ¿Hay alguna manera fácil de hacer esto? Algunos ejemplos que he visto son bastante intrincados.

Editar: Esta pregunta fue originalmente para ASP.NET MVC 1, pero si la versión 2 lo hace más fácil, me gustaría escuchar la respuesta.

+0

He cambiado la etiqueta para asp.net-mvc para que la gente lo ven en sus Preferencias. –

+0

¿Has encontrado una respuesta a esto? Parece que se está convirtiendo en una pregunta bastante popular. – Jon

+0

Aún no. No creo que la respuesta de NerdDinner haga lo que quiero. – Craig

Respuesta

4

NerdDinner tiene algunos buenos ejemplos de esto. Aquí está el SearchController en NerdDinner, que tiene un método llamado SearchByLocation que devuelve una lista de JsonDinners (source code para NerdDinner es Creative Commons):

namespace NerdDinner.Controllers { 

    public class JsonDinner { 
     public int  DinnerID { get; set; } 
     public string Title  { get; set; } 
     public double Latitude { get; set; } 
     public double Longitude { get; set; } 
     public string Description { get; set; } 
     public int  RSVPCount { get; set; } 
    } 

    public class SearchController : Controller { 

     IDinnerRepository dinnerRepository; 

     // 
     // Dependency Injection enabled constructors 

     public SearchController() 
      : this(new DinnerRepository()) { 
     } 

     public SearchController(IDinnerRepository repository) { 
      dinnerRepository = repository; 
     } 

     // 
     // AJAX: /Search/FindByLocation?longitude=45&latitude=-90 

     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult SearchByLocation(float latitude, float longitude) { 

      var dinners = dinnerRepository.FindByLocation(latitude, longitude); 

      var jsonDinners = from dinner in dinners 
           select new JsonDinner { 
            DinnerID = dinner.DinnerID, 
            Latitude = dinner.Latitude, 
            Longitude = dinner.Longitude, 
            Title = dinner.Title, 
            Description = dinner.Description, 
            RSVPCount = dinner.RSVPs.Count 
           }; 

      return Json(jsonDinners.ToList()); 
     } 
    } 
} 
+0

No estoy seguro de que esto haga lo que quiero. Devuelve una lista de elementos Json. Por cierto Robert, nunca te elegí como desarrollador mientras jugaba para St.Kilda. – Craig

+0

Creo que me tienes confundido con otra persona. :) –

+0

¿Entiendo correctamente (a partir de su código original) que desea ver el recorrido cuando devuelve el JsonResult? Porque es bastante fácil devolver una sola cena en lugar de una lista de cenas. –

0

¿Por qué no tienen "parciales" estáticas html y agarrar todas las dinámicas contenido del json? Debería poder cargar los archivos html con jquery cuando la página se carga o cuando se necesita con bastante facilidad.

este enlace en JQuery Ajax da este ejemplo:

//Alert out the results from requesting test.php (HTML or XML, depending on what was returned). 
$.get("test.php", function(data){ 
    alert("Data Loaded: " + data); 
}); 
+0

Podría hacer esto, pero por la forma en que funciona ASP MVC sería mucho más trabajo escribir código de plomería. – Craig

11

Aquí está la respuesta! Es un cambio leve del método Martin From's y parece funcionar. Si faltan cosas, ¿pueden las personas contribuir con los cambios de código en la sección de comentarios? Gracias.

Desde que Controlador de llamada de esta manera:

string HTMLOutput = Utils.RenderPartialToString("~/Views/Setting/IndexMain.ascx", "", items, this.ControllerContext.RequestContext); 

añadir esto a una clase

public static string RenderPartialToString(string controlName, object viewData, object model, System.Web.Routing.RequestContext viewContext) 
{ 
    ViewDataDictionary vd = new ViewDataDictionary(viewData); 
    ViewPage vp = new ViewPage { ViewData = vd }; 

    vp.ViewData = vd; 
    vp.ViewData.Model = model; 
    vp.ViewContext = new ViewContext(); 
    vp.Url = new UrlHelper(viewContext); 

    Control control = vp.LoadControl(controlName); 

    vp.Controls.Add(control); 

    StringBuilder sb = new StringBuilder(); 

    using (StringWriter sw = new StringWriter(sb)) 
    using (HtmlTextWriter tw = new HtmlTextWriter(sw)) 
    { 
     vp.RenderControl(tw); 
    } 

    return sb.ToString(); 
} 
+0

Gracias por esto. Estoy buscando modificar esto ligeramente para que sea un poco mejor y publicaré el resultado. – Craig

+0

Esperamos ver lo que surge con – Jon

1

He pasado años tratando de hacer lo mismo. Tengo una solución rápida que deberá extenderse.

NOTA: Puedo ver un problema ya ..Las cookies y otras variables se pierden :(

Lo que hice:

  1. Crear nueva ActionResult

    public class JsonHtmlViewResult : ViewResult 
    { 
        public IJsonHtml Data { get; set; } 
    
        public override void ExecuteResult(ControllerContext context) 
        { 
         if (Data == null) 
         { 
          Data = new DefaultJsonHtml(); 
         } 
    
         using (StringWriter sw = new StringWriter()) 
         { 
          HttpRequest request = HttpContext.Current.Request; 
          HttpContext.Current = new HttpContext(request, new HttpResponse(sw)); 
    
          base.ExecuteResult(context); 
    
          Data.HtmlContent = sw.ToString(); 
         } 
    
         // Do the serialization stuff. 
         HttpResponseBase response = context.HttpContext.Response; 
         response.ClearContent(); 
         response.ContentType = "application/json"; 
    
         JavaScriptSerializer serializer = new JavaScriptSerializer(); 
         response.Write(serializer.Serialize(Data)); 
        } 
    } 
    
  2. la clase de datos

    public interface IJsonHtml 
    { 
        String HtmlContent { get; set; } 
    } 
    
    public class DefaultJsonHtml : IJsonHtml 
    { 
        public String HtmlContent { get; set; } 
    } 
    
  3. Las extensiones de controlador

    public static ActionResult JsonHtmlViewResult(this Controller controller, string viewName, string masterName, object model, IJsonHtml data) 
    { 
        if (model != null) 
        { 
         controller.ViewData.Model = model; 
        } 
    
        return new JsonHtmlViewResult 
        { 
         Data = data, 
         ViewName = viewName, 
         MasterName = masterName, 
         ViewData = controller.ViewData, 
         TempData = controller.TempData 
        }; 
    } 
    
1

he encontrado una respuesta más reciente utilizando la maquinilla de afeitar que puede ser útil http://codepaste.net/8xkoj2

public static string RenderViewToString(string viewPath, object model,ControllerContext context) 
{    
    var viewEngineResult = ViewEngines.Engines.FindView(context, viewPath, null); 
    var view = viewEngineResult.View; 


    context.Controller.ViewData.Model = model; 

    string result = String.Empty; 
    using (var sw = new StringWriter()) 
    { 

     var ctx = new ViewContext(context, view, 
            context.Controller.ViewData, 
            context.Controller.TempData, 
            sw); 
     view.Render(ctx, sw); 

     result = sw.ToString(); 
    } 

    return result; 
} 
0

que ponen para no saben ya qué número de versión que se puede hacer esto, pero hoy en día puede devolver JSON de una manera muy simple:

public ActionResult JSONaction() 
{ 
    return Json(data, JsonRequestBehavior); 
} 

sin necesidad de ayudantes elaborados, etc.

los datos son, por supuesto, sus datos de su modelo JsonRequestBehavior especifica si se permiten las solicitudes HTTP GET del cliente. (source), es opcional DenyGet es el comportamiento por defecto, por lo que si utiliza sobre todo JsonRequestBehavior.AllowGet y here es por qué esto es ahí

+0

El problema no es devolver Json sino asociar una Vista al Json. – Craig

Cuestiones relacionadas