2009-07-25 7 views
29

Puis-je retourner un résultat Json qui contient également une vue rendue?ASP.NET MVC - Combiner le résultat Json avec ViewResult

J'ai besoin d'elle pour retourner le nouvel ID d'un formulaire soumis avec son HTML et d'autres propriétés.

Cela peut également être utile lorsque j'ai besoin de renvoyer deux (ou plus) résultats d'une seule action dans un objet JSON.

Merci!

Répondre

39

Vous pouvez également rendre une PartialViewResult à une chaîne, et ensuite passer cette chaîne via JSON à votre point de vue, ce qui rend en votre page en utilisant jQuery.

Vous pouvez le voir dans cet article: http://www.atlanticbt.com/blog/asp-net-mvc-using-ajax-json-and-partialviews/.

J'ai créé une extension pour le rendre plus facile:

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(); 
     } 
    } 
} 

Dans mon contrôleur je l'appelle comme suit:

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

Où « ce » est le contrôleur dans le cas, " ProductItemForm » est mon avis et "modèle" est mon objet productItem :)

Hope this helps;)

+1

J'aime cette approche. J'ai ajouté le RenderPartialView à ma classe de contrôleur de base, donc je le fais souvent. – jsalwen

0

Cela peut être un peu hacky (et j'écris du dessus de ma tête) mais vous voudrez peut-être créer votre propre sous-classe de ActionResult et également implémenter un ResultFilter qui intercepterait ces types spécifiques d'ActionResult et rendrait le pertinent Vues et remplir un JsonResult et le renvoyer.

Par exemple, vous pouvez définir:

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

puis dans un ResultFilter, rendre la vue pertinente et la fusion dans l'endroit approprié dans le JsonResult et enfin retourner le JsonResult au client. En dehors de tout cela, vous voudrez peut-être changer votre approche dans la façon dont vous faites cela, par exemple. vous pourriez essayer de renvoyer une vue complète (c.-à-d. HTML) de votre action dont une partie est la vue que vous voulez retourner mais qui inclut également des informations supplémentaires qui auraient autrement été dans votre objet JSON. Vous pouvez supprimer les composants pertinents du code HTML renvoyé en utilisant des opérations jQuery simples sur le client.

+0

pouvez-vous expliquer plus au sujet du filtre de résultat? c'est exactement ce que je quoi; créer un ActionResult personnalisé ... – Benoit

1

Dans le premier cas, je pense que vous pouvez simplement retourner du HTML, mais intégrer les données dans le formulaire retourné. Utilisez jQuery pour accéder aux données de votre rappel de succès.

$.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(); 
      } 
}); 

Dans le second cas, un point de vue partagé qui prend deux ViewNames ou plus et utilise RenderPartial est probablement une meilleure solution que le retour HTML par JSON.

Multiview.aspx

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

Puis dans votre action:

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

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

J'ai réfléchi à ce problème pendant un moment. Ma solution est similaire à renvoyer le HTML de vue partielle en tant que chaîne JSON, mais le contraire. Renvoie une vue partielle avec JSON incorporé dedans.Je n'ai pas aimé cette approche jusqu'à ce que jQuery 1.4.3 ait fusionné leur méthode .data() avec l'attribut de données HTML 5. Cela rend beaucoup plus facile de générer du JSON dans une vue ASP.NET MVC et de le lire via jQuery.

Voir l'exemple ... Ce n'est pas parfait, mais je l'aime beaucoup mieux que de créer des entrées de formes cachées ou des aides qui rendent la vue partielle avant de la renvoyer.

Vue partielle:

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

JavaScript qui lit le JSON

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

Cela peut sembler aller à l'encontre de la "responsabilité unique principe" (si vous l'appliquez à des vues) . Cependant, si votre application nécessite que les deux données soient transmises dans une réponse, je ne vois rien de mal à cela. Et tant que votre modèle est construit correctement, il ne va pas à l'encontre des principes de conception.