Afficher une vue d'un autre contrôleur dans ASP.NET MVC

248

Est-il possible d'afficher une vue d'un autre contrôleur?

Disons par exemple que j'ai une CategoriesControlleret une Category/NotFound.aspxvue. Une fois dans le CategoriesController, je peux facilement revenir View("NotFound").

Maintenant, disons que j'ai une ProductsControlleret une action et une vue pour ajouter un produit. Cependant, cette action nécessite que nous ayons une catégorie à laquelle ajouter le produit. Par exemple Products/Add/?catid=10,.

Si je ne parviens pas à trouver la catégorie en fonction de catid, je souhaite afficher la NotFoundvue à partir du contrôleur Catégories au lieu de créer une CategoryNotFoundvue sous le contrôleur Produits.

Est-ce possible ou est-ce que je structure les choses de la mauvaise façon? Y at-il un bon moyen de le faire?

dtc
la source

Réponses:

283

Oui. Par défaut, ASP.NET MVC s'enregistre d'abord \Views\[Controller_Dir]\, mais après cela, s'il ne trouve pas la vue, il s'enregistre \Views\Shared.

Le répertoire partagé est là spécifiquement pour partager des vues sur plusieurs contrôleurs. Ajoutez simplement votre vue au sous-répertoire partagé et vous êtes prêt à partir.

Si vous le faites, return View("~/Views/Wherever/SomeDir/MyView.aspx")vous pouvez retourner n'importe quelle vue que vous souhaitez.

womp
la source
Merci, cela ressemble à la solution que je devrais utiliser. Je me demande toujours s'il est possible d'afficher une vue à partir d'un autre contrôleur. Je suppose que cela viole une règle dans MVC?
dtc
1
Dans la situation que vous décrivez ci-dessus, oui, vous devez utiliser le dossier partagé.
Jonathan Freeland
69
Oui, c'est aussi possible. Si vous retournez la vue ("~ / Views / Wherever / SomeDir / MyView.aspx"), vous pouvez retourner la vue que vous souhaitez. Cela ne viole aucune règle particulière en soi, cependant, ASP.Net MVC est tout au sujet de la "convention sur la congfiguration". En d'autres termes, le cadre est conçu pour fonctionner automatiquement à l'aide de certaines conventions, et vous devez l'utiliser dans la mesure du possible.
womp
1
Merci pour l'explication. Je ne savais pas que Views pouvait être appelé ainsi. Le répertoire partagé fonctionne bien sûr parfaitement :)
dtc
1
Je n'étais pas dans un contrôleur, j'ai donc dû l'utiliser new ViewResult { ViewName = "~/Views/Error/Unauthorised.cshtml" };et cela a fonctionné
Nacht
162

Vous pouvez utiliser:

return View("../Category/NotFound", model);

Il a été testé dans ASP.NET MVC 3, mais devrait également fonctionner dans ASP.NET MVC 2.

Guillaume86
la source
3
Fonctionne dans MVC 2 et s'est avéré être la solution la plus propre à une situation inhabituelle avec laquelle je fais face.
Todd Menier
3
Resharper signalera ce lien comme une erreur mais il fonctionne toujours.
CodeMonkeyKing du
1
@CodeMonkeyKing - Resharper 7 (dans VS2012) identifie correctement un chemin au format "~/Views/Category/NotFound.cshtml".
Richard Ev
A noter: cette solution fonctionne avec les modes d'affichage, par exemple si vous aviez une vue "/Category/NotFound.Mobile.cshtml".
BenWillkommen
55

Oui c'est possible. Renvoyez une RedirectToAction()méthode comme celle-ci:

return RedirectToAction("ActionOrViewName", "ControllerName");
doncadavona
la source
1
Je crois que cela devrait aller comme RedirectToAction ("ActionOrView", "Controller", null) car sinon le deuxième paramètre est routeValues
Zoran P.
Mais dans ce cas, vous devez réellement écrire l'action dans le contrôleur, contrairement à la solution View.
tobbenb3
@ tobbenb3 C'est une bien meilleure solution que de coder en dur un résultat. Dans tous les cas, vous ne devez pas passer dans une chaîne de chemin.
perustaja
34

As-tu essayé RedirectToAction?

Paul Johnson
la source
1
Je dirais que c'est le MVC pour toute personne qui ne veut pas la vue dans les dossiers partagés, notez que pour toutes les autres solutions (telles que l'utilisation de chemins directs), toute personne essayant de re-factoriser les vues n'aura pas à prendre en compte qu'il est également utilisé dans un autre contrôleur, ce qui entraîne un comportement imprévisible
yoel halb
4
que diriez-vous sans rediriger?
Luckyy
meilleure solution que de déplacer la vue vers des dossiers partagés
juFo
Cette solution nécessite une action sur le contrôleur, View (directPath) rend la sortie sans aucune action. Lorsque vous ajoutez une action, vous devez penser à la cacher à un accès direct via l'URL, cela générera une étape dans l'historique du navigateur, etc. Mais oui, c'est ma voie à suivre.
Jan Zahradník
3
RedirectToAction envoie un code de réponse 302 au navigateur. Ce n'est pas approprié lorsque vous essayez d'afficher une page 404 introuvable. Autrement dit, cette solution semble fonctionner, mais confondra les moteurs de recherche.
NightOwl888 du
20

Oui, vous pouvez. Renvoyer une action comme celle-ci:

return RedirectToAction("View", "Name of Controller");

Un exemple:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees");

Cette approche appellera la méthode GET

Vous pouvez également transmettre des valeurs à une action comme celle-ci:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees", new {id = id.ToString(), viewtype = "extended" });
ignacio chiazzo
la source
comment pourrais-je envoyer un objet avec cette approche?
Djeroen
Jetez un oeil @Djeroen
ignacio chiazzo
5
Vous ne renvoyez pas de vue, vous appelez une action.
0014
Avant tout, cela m'a été utile.
anil shrestha
5

Vous pouvez également appeler n'importe quel contrôleur à partir de JavaScript / jQuery . Supposons qu'un contrôleur renvoie 404 ou un autre contrôle utilisateur / page. Ensuite, sur une action, à partir de votre code client, vous pouvez appeler une adresse qui déclenchera votre contrôleur et retourner le résultat au format HTML votre code client peut prendre ce résultat retourné et le mettre où vous voulez dans votre page ...

Marko
la source
Je ne le savais pas. Cela ressemble à quelque chose que je pourrais utiliser à l'avenir. Oui, mvc rocks :)
dtc
1

Avec ce code, vous pouvez obtenir n'importe quel contrôleur:

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, 
controller);
Yair GR
la source
Traduction: Avec ce code, vous pouvez obtenir n'importe quel contrôleur: [code], Cordialement,
Robert Columbia
3
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse.
Nic3500