47 votes

.NET MVC Appeler une méthode sur un contrôleur différent

Quelqu'un peut-il me dire comment appeler une méthode sur un contrôleur différent à partir d'une méthode d'action ? Je ne veux pas faire de redirection. Je veux appeler une méthode sur un contrôleur différent qui renvoie une chaîne et utiliser la réponse dans ma méthode d'action.

42voto

Pete Points 5231

Il me semble que vous devriez remanier votre application et extraire la fonctionnalité qui génère la chaîne de caractères dans une nouvelle classe distincte (ou réutiliser une classe existante, si vous en avez une qui convient) et laisser les deux contrôleurs utiliser cette classe.

12voto

Drew Noakes Points 69288

Vous pouvez y parvenir par le biais de l'option Action méthode de HtmlHelper .

Dans une vue, vous le feriez comme ceci :

@Html.Action("OtherAction")

Cependant, il n'est pas simple d'obtenir une instance de HtmlHelper dans une méthode d'action (à dessein). En fait, c'est un hack tellement horrible que j'hésite à le poster...

var htmlHelper = new HtmlHelper(new ViewContext(
                                      ControllerContext, 
                                      new WebFormView(ControllerContext, "HACK"),
                                      new ViewDataDictionary(),
                                      new TempDataDictionary(),
                                      new StringWriter()),
                                new ViewPage());

var otherViewHtml = htmlHelper.Action("ActionName", "ControllerName");

Cela fonctionne sur MVC 3. Il se peut que vous deviez supprimer le StringWriter arg du ViewContext pour MVC 2, IIRC.

</hack>

11voto

Nick Points 2964

Pourriez-vous simplement instancier le contrôleur dans votre méthode d'action et appeler l'autre méthode dont vous avez besoin ?

public ActionResult YourActionMethod()
{
   SomeController c = new SomeController();
   ActionResult result = c.SomeMethod();

   return View();
}

9voto

awrigley Points 6468

Je n'ai pas utilisé l'IoC de Castle Windsor, mais en théorie, vous devriez pouvoir créer une classe de fabrique de contrôleur personnalisée, puis demander au cadre MVC d'utiliser cette fabrique de contrôleur personnalisée, en l'enregistrant dans le fichier Global.asax.css, dans l'événement Application_Start :

protected void Application_Start()
{
   RegisterRoutes(RouteTable.Routes);
   ControllerBuilder.Current.SetControllerFactory(new MyCustomControllerFactor());
}

[Voir Pro Asp.Net MVC 2 Framework, Steven Sanderson, Apress, pages 64 - 66].

De cette façon, vous pouvez instancier vos contrôleurs depuis n'importe où dans votre code.

La notion de NE PAS appeler les actions d'un autre contrôleur à partir du contrôleur "actuel" ou d'un autre code est tout à fait erronée. Les contrôleurs ne sont que des classes. Ils ne deviennent des "contrôleurs" que lorsqu'ils sont invoqués d'une manière spéciale par le cadre MVC.

Par conséquent, le bien et le mal se résument à la question de savoir POURQUOI vous faites cela, et non PAS SI vous devriez le faire ou non.

Si vous utilisez simplement un contrôleur comme classe, c'est parfait. Si vous essayez de l'utiliser pour envoyer une réponse à l'utilisateur, alors vous devez utiliser une RedirectToAction comme suggéré ci-dessus.

Il existe un certain nombre de raisons d'utiliser un contrôleur comme une classe plutôt que comme un contrôleur. Par exemple, lorsque vous testez votre contrôleur. Par conséquent, il est nécessaire de traiter vos contrôleurs comme une classe plutôt que comme une erreur.

Un exemple d'utilisation d'un contrôleur comme classe dans un scénario de non-test :

Je suis en train d'écrire un mini framework qui exploite les capacités de modélisation du framework MVC pour produire le HTML des courriels en HTML, ce que toutes les applications web doivent faire, pour une raison ou une autre (par exemple, les courriels de confirmation de commande).

En gros, vous instanciez votre MailManagerController (pour simplifier, supposons que vous n'utilisez pas d'IoC) dans l'action de votre NormalController (qui doit envoyer un courriel), puis vous le faites :

MailManagerController mailmanager = new MailManagerController();
string html = mailmanager.OrderConfirmation(order).RenderToString();
Postman.SendEmail(html, order.UserEmailAddress, "MyApp order confirmation");

Où RenderToString est une méthode d'extension de ViewResultBase qui rend le résultat d'une action (qui renvoie un objet ViewResultBase) en une chaîne de caractères, et Postman est une classe statique qui s'occupe de l'envoi de courriels une fois que vous avez le texte.

La beauté de cette technique est que vous pouvez utiliser le cadre MVC pour produire des courriels modélisés, car l'action OrderConfirmation aura une vue associée qui n'est rien d'autre qu'un modèle html pour le courriel que vous allez envoyer.

2voto

twk Points 2220

On dirait que vous essayez de faire quelque chose pour lequel les contrôleurs ne sont pas conçus. Concevez votre méthode requise comme une méthode publique dans une classe et invoquez-la à partir des deux actions du contrôleur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X