2009-05-26 12 views
17

Mam aplikację MVC z kilkoma kontrolowanymi akcjami, które są wywoływane za pomocą Ajax (jQuery) i zwracają częściowe widoki, które aktualizują część ekranu. Ale wolałbym raczej zwrócić JSONowi coś takiego.ASP MVC Wyświetl treść jako JSON

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

Gdzie HTML jest własnością Json. Oznacza to, że muszę pobrać kod HTML renderowany za pomocą metody View. Czy jest jakiś łatwy sposób, aby to zrobić, kilka przykładów, które widziałem są dość zawiłe.

Edytuj: To pytanie było pierwotnie dla programu ASP.NET MVC 1, ale jeśli wersja 2 ułatwia to, chciałbym usłyszeć odpowiedź.

+0

zmieniłem tag w asp.net-mvc tak ludzie widzą go w swoich preferencjach. –

+0

Czy znalazłeś odpowiedź na to pytanie? Wydaje się, że staje się dość popularnym pytaniem. – Jon

+0

Jeszcze nie. Nie sądzę, że odpowiedź NerdDinnera robi to, co chcę. – Craig

Odpowiedz

4

NerdDinner ma kilka niezłych przykładów tego. Oto SearchController w NerdDinner, która ma metodę zwaną SearchByLocation zwracającą listę JsonDinners (source code dla NerdDinner jest kreatywna fotografia):

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

Nie jestem pewien, czy robi to, co chcę. Zwraca listę elementów Json. BTW Robert, nigdy nie wybrałem ciebie jako programisty podczas gry w St.Kilda. – Craig

+0

Myślę, że masz mnie z kimś zmieszanym. :) –

+0

Czy rozumiem poprawnie (z twojego oryginalnego kodu), że chcesz wziąć widok na przejażdżkę, gdy zwrócisz JsonResult? Ponieważ łatwo jest zwrócić pojedynczą kolację, a nie listę kolacji. –

0

Dlaczego po prostu nie mają statyczne html „partials” i złapać wszystkie dynamiczne treść z json? Powinieneś być w stanie załadować pliki html przy pomocy jquery, gdy strona ładuje się lub kiedy potrzeba dość łatwo.

Ten link na JQuery Ajax daje ten przykład:

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

Mogłem to zrobić, ale sposób, w jaki działa ASP MVC, oznaczałby trochę więcej pracy przy pisaniu kodu instalacyjnego. – Craig

11

Oto odpowiedź! Jest to niewielka zmiana z metody Martin From's i wydaje się działać. Jeśli czegoś brakuje, użytkownicy mogą dodawać wszelkie zmiany kodu w sekcji komentarzy. Dzięki.

od ciebie kontrolera nazwać tak:

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

Dodaj to do klasy

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

Dzięki za to. Patrzę na modyfikowanie tego nieco, aby być nieco lepszym i opublikuję wynik. – Craig

+0

Sprawdź, co wymyślisz – Jon

1

Spędziłem wieku próbuje zrobić to samo. Mam szybkie rozwiązanie, które będzie musiało zostać przedłużone.

UWAGA: Widzę już jedną kwestię ..Jakiekolwiek ciasteczka i inne zmienne są tracone :(

Co zrobiłem:

  1. Utwórz nowe 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. klasy danych

    public interface IJsonHtml 
    { 
        String HtmlContent { get; set; } 
    } 
    
    public class DefaultJsonHtml : IJsonHtml 
    { 
        public String HtmlContent { get; set; } 
    } 
    
  3. Rozszerzenia kontroler

    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

znalazłem nowszą odpowiedź za pomocą brzytwy, które mogą być pomocne 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

nie don wiem od którego numer wersji można zrobić to, ale w dzisiejszych czasach możesz zwrócić JSON w bardzo prosty sposób:

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

bez pomocy skomplikowanych pomocników itp.

dane to oczywiście dane z modelu JsonRequestBehavior określa, czy żądania HTTP GET od klienta są dozwolone. (source) jest opcjonalny DenyGet to zachowanie domyślne, więc jeśli jest stosowany głównie JsonRequestBehavior.AllowGet i here to dlaczego jest tam

+0

Problemem nie jest zwrócenie Json, ale dołączenie widoku do Json. – Craig