Renvoyer une vue partielle et une action JSON à partir d’une action ASP.NET MVC

J’introduis KnockoutJS dans une application existante. Mon plan est de modifier / utiliser les vues partielles existantes que nous avons déjà créées et de les lier aux modèles de vue JS avec les atsortingbuts déclaratifs de Knockout. Lorsque je passe un appel AJAX à une action, l’idéal serait que cette action renvoie à la fois le code HTML de la vue partielle et l’object JSON. Ensuite, je peux remplir un div avec le code HTML, convertir le code JSON en object Knockout et le lier au code HTML. Mais je n’arrive pas à comprendre comment revenir des deux.

J’ai besoin du modèle de vue complète car je vais le mettre à jour et le renvoyer éventuellement au serveur.

Je pensais que l’action devait renvoyer la vue partielle (déjà liée au modèle) et inclure dans cette vue partielle le javascript permettant de convertir le modèle .Net en object Knockout. Mais je pense que disperser le JS comme ça est désordonné et impossible à maintenir. Je préférerais que tout soit proche de l’appel ajax d’origine.

Je suppose qu’une autre alternative est de faire deux appels d’action. Un pour le JSON et un autre pour la vue partielle. Mais il doit y avoir un moyen plus lisse.

Des idées sur la meilleure façon de faire cela?

Je suis sûr qu’il y a différentes façons de le faire. Je rends manuellement la vue à partir du contrôleur, puis je la renvoie en tant que partie de ma réponse JSON.

Cela préserve les responsabilités de chaque entité. Les vues sont toujours localisées à l’aide du moteur de vue et peuvent être réutilisées. Le contrôleur ne sait rien ou presque rien de la vue au-delà de son nom et du type de modèle.

Rendu manuel

public static class RenderHelper { public static ssortingng PartialView( Controller controller, ssortingng viewName, object model ) { controller.ViewData.Model = model; using( var sw = new SsortingngWriter() ) { 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.ToSsortingng(); } } } 

Dans votre méthode d’action:

 object model = null; // whatever you want var obj = new { someOtherProperty = "hello", view = RenderHelper.PartialView( this, "_PartialName", model ) }; return Json( obj ); 

Notez que je retourne un type anonyme. Vous pouvez renvoyer n’importe quel type (sérialisable) de votre choix, à condition qu’il possède une propriété de chaîne pour la vue rendue.

Essai

Tester une action utilisant le rendu manuel nécessite une légère modification. Cela est dû au fait que l’affichage a été rendu un peu plus tôt que dans le pipeline MVC.

Rendu manuel

  1. Entrez la méthode d’action
  2. Rendre la vue explicitement <- cela rendra difficile le test de l'action appelante
  3. Méthode d’action de sortie

Rendu automatique

  1. Entrez la méthode d’action
  2. Créer un résultat de vue
  3. Méthode d’action de sortie
  4. Traiter le résultat de la vue (rendant ainsi la vue)

En d’autres termes, notre processus de rendu manuel déclenche diverses opérations rendant le test difficile (par exemple, interagir avec le gestionnaire de génération pour comstackr la vue).

En supposant que vous souhaitiez tester la méthode d’action et non le contenu réel de la vue, vous pouvez vérifier si le code s’exécute ou non dans un environnement hébergé.

  public static ssortingng PartialView( Controller controller, ssortingng viewName, object model ) { // returns false from a VS 2013 unit test, true from IIS if( !HostingEnvironment.IsHosted ) { // return whatever you want here return ssortingng.Empty; } // continue as usual } 

Vérifier HostingEnvironment.IsHosted est bon marché (sous le capot, il s’agit simplement d’un contrôle nul).

Vous pouvez créer une masquée sur le partiel avec une valeur définie sur la chaîne JSON du ViewModel. Ensuite, avant de rendre la vue partielle, extrayez la valeur JSON de ce champ et parsingz-la. Ensuite, supprimez-le de la vue partielle, insérez-le dans votre page et effectuez ko.applyBindingsToDescendants(viewModel, $("#parentElement")[0])

Je ne suis pas tout à fait sûr de ce que je pense de cette approche, et ce n’est qu’une théorie. Je n’ai pas testé cela mais je suppose que cela fonctionnerait. Le navigateur qui tente de mettre en cache votre requête GET est un piège à éviter. Dans votre demande ajax, vous voudriez faire:

 $.ajax({ url: "/", type: 'GET', cache: 'false' }); 

Ou faites simplement une requête $.post . ( référence )

Donc, c’est une option.