web-dev-qa-db-fra.com

ASP.NET MVC - Combinez le résultat Json avec ViewResult

Puis-je renvoyer un résultat Json contenant également une vue rendue?

J'en ai besoin pour renvoyer le nouvel ID d'un formulaire soumis avec son code HTML et quelques autres propriétés.

Cela peut également être utile lorsque je dois renvoyer deux (ou plus) résultats de vue provenant d’une action unique dans un objet Json.

Merci!

29
elado

Vous pouvez également rendre un PartialViewResult en chaîne, puis transmettre cette chaîne via JSON à votre vue, en la rendant dans votre page à l'aide de jQuery.

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

J'ai créé une extension pour faciliter les choses:

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

Je l'appelle comme suit dans mon contrôleur:

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

Où "ceci" est le contrôleur dans le cas, "ProductItemForm" est mon point de vue et "modèle" est mon objet productItem :)

J'espère que cela t'aides ;)

40
Diego Ponciano

Je réfléchis à ce problème depuis un moment. Ma solution est similaire au retour de la vue partielle HTML sous forme de chaîne JSON, mais l’inverse. Renvoie une vue partielle avec JSON incorporé. Je n’aimais pas cette approche avant que jQuery 1.4.3 ait fusionné sa méthode .data () avec l’attribut HTML 5 data. Cela facilite beaucoup la génération de JSON dans une vue ASP.NET MVC et sa lecture via jQuery.

Voir l'exemple ... Ce n'est pas parfait, mais je l'aime bien mieux que de créer des entrées de formulaire masqué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 du "principe de responsabilité unique" (si vous l’appliquez à des vues). Cependant, si votre application nécessite la transmission des deux éléments de données dans une réponse, cela ne me pose aucun problème. Et tant que votre modèle est construit correctement, il ne sera pas contraire aux principes de conception.

1
Jason Capriotti

Dans le premier cas, je pense que vous pouvez simplement renvoyer du HTML, mais incorporer les données dans le formulaire renvoyé. Utilisez jQuery pour accéder aux données de votre rappel de réussite.

$.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 deuxième cas, une vue partagée utilisant deux ou plusieurs noms de noms et utilisant RenderPartial est probablement une meilleure solution que le retour de HTML via 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
tvanfosson

C’est peut-être un peu un hacky (et j’écris du haut de ma tête) mais vous pouvez créer votre propre sous-classe d’ActionResult et implémenter un ResultFilter qui intercepterait ces types spécifiques d’ActionResult et afficherait les Vues pertinentes et les remplira. JsonResult et le retourner.

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, restituez la vue pertinente, fusionnez-la à l'emplacement approprié dans JsonResult et renvoyez enfin le JsonResult au client.

En dehors de tout cela, vous voudrez peut-être changer votre approche, par exemple: vous pouvez essayer de renvoyer une vue complète (HTML) de votre action dont une partie correspond à la vue que vous souhaitez renvoyer, mais qui inclut également des informations supplémentaires qui auraient autrement été dans votre objet JSON. Vous pouvez extraire les composants pertinents du code HTML renvoyé à l'aide d'opérations jQuery simples côté client.

0
paracycle