web-dev-qa-db-fra.com

ASP.NET MVC `Html.ActionLink` entre les" zones "

J'ai ajouté une nouvelle zone à mon projet MVC3 et j'essaie de créer un lien depuis la page _Layout vers la nouvelle zone. J'ai ajouté une zone appelée 'Admin' qui a un contrôleur 'Meets'.

J'ai utilisé le concepteur de studio visuel pour ajouter la zone afin qu'elle ait la classe d'enregistrement de zone correcte, etc., et le fichier global.asax enregistre toutes les zones.

Cependant, lorsque j'utilise les 2 liens d'action suivants dans une page à la racine, je rencontre quelques problèmes:

@Html.ActionLink("Admin", "Index", "Meets", new { area = "Admin" }, null)
@Html.ActionLink("Admin", "Index", "Meets", new { area = "" }, null)

Lorsque je clique sur les deux liens, je suis redirigé vers le contrôleur Meets dans la zone Admin, où l'application continue de générer une erreur indiquant qu'elle ne trouve pas la page d'index (même si la page d'index est présente dans le dossier Views dans la sous-zone Area). annuaire.

Le href pour le 1er lien ressemble à ceci:

http://localhost/BCC/Meets?area=Admin

Et le href pour le 2ème lien ressemble à ceci:

http://localhost/BCC/Meets

De plus, si je clique sur le lien que je m'attends à créer:

http://localhost/BCC/Admin/Meets

Je reçois juste une ressource introuvable. Erreur. Tout cela laisse perplexe! J'espère que quelqu'un pourra aider ...

48
jcvandan

J'ai compris cela - j'ai créé un nouveau projet de test et j'ai fait exactement la même chose que je faisais auparavant et cela a fonctionné ... puis après une inspection plus approfondie de tout ce qui concerne la route entre les deux projets, j'ai trouvé une divergence.

Dans le fichier global.asax de mon application BCC, il y avait une ligne de code voyous qui était inexplicablement apparue:

        public static void RegisterRoutes(RouteCollection routes)
        {
            // Problem here
            routes.Clear();

            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

Comme vous pouvez voir où se trouve mon commentaire, à un moment ou à un autre, j'avais placé les routes.Appel Clear () au début de RegisterRoutes, ce qui signifiait après avoir enregistré les zones dans Application_Start, j'effaçais alors immédiatement ce que je venais de inscrit.

Merci pour l'aide ... cela a finalement conduit à mon salut!

7
jcvandan

Étrange en effet. Étapes qui ont parfaitement fonctionné pour moi:

  1. Créer une nouvelle application ASP.NET MVC 3 à l'aide du modèle Visual Studio par défaut
  2. Ajoutez une zone appelée Admin à l'aide de Visual Studio Designer en cliquant avec le bouton droit sur le projet
  3. Ajouter un nouveau contrôleur dans ~/Areas/Admin/Controllers/MeetsController:

    public class MeetsController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
    
  4. Ajouter une vue correspondante ~/Areas/Admin/Views/Meets/Index.cshtml

  5. Dans la mise en page (~/Views/Shared/_Layout.cshtml) ajouter des liens:

    @Html.ActionLink("Admin", "Index", "Meets", new { area = "Admin" }, null)
    @Html.ActionLink("Admin", "Index", "Meets", new { area = "" }, null)
    
  6. Exécutez l'application.

HTML rendu pour les ancres:

<a href="/Admin/Meets">Admin</a>
<a href="/Meets">Admin</a>

Comme prévu, le premier lien fonctionne alors que le second ne fonctionne pas.

Quelle est donc la différence avec votre configuration?

73
Darin Dimitrov

Une autre option consiste à utiliser RouteLink () au lieu d'ActionLink (), qui contourne complètement les enregistrements de zone:

Version d'ActionLink:

Html.ActionLink("Log Off", "LogOff", "Account", new { area = "" }, null)

Version RouteLink:

Html.RouteLink("Log Off", "Default", 
    new { action = "LogOff", controller = "Account" })

Le deuxième paramètre est un "nom de route" qui est enregistré dans Global.asax.cs et dans diverses sous-classes "AreaRegistration". Pour utiliser 'RouteLink' pour établir un lien entre différentes zones, il vous suffit de spécifier le nom d'itinéraire correct.

Cet exemple suivant montre comment je générerais trois liens vers différentes zones à partir d'un partiel partagé, ce qui fonctionne correctement quelle que soit la zone dans laquelle je me trouve (le cas échéant):

@Html.RouteLink("Blog", "Blog_default", 
    new { action = "Index", controller = "Article" })
<br/>
@Html.RouteLink("Downloads", "Download_default", 
    new { action = "Index", controller = "Download" })
<br/>
@Html.RouteLink("About", "Default", 
    new { action = "Index", controller = "About" })

Bon codage!

30
Shaun Wilson

Vérifiez que votre classe AdminAreaRegistration ressemble à ceci:

public class AdminAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Admin";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Admin_default",
            "Admin/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );
    }
}

et que vous avez ceci dans Global.asax.cs:

protected void Application_Start()
{
    ... // ViewEngine Registration
    AreaRegistration.RegisterAllAreas();
    ... // Other route registration
}
3
Mikael Östberg

J'ai résolu ce problème en procédant comme suit.

Dans mon Global.asax.cs, j'ai

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });
    }

    protected void Application_Start()
    {
        //Initialise IoC
        IoC.Initialise();

        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

Dans mon PublicAreaRegistration.cs (Espace public), j'ai

public class PublicAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Public";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute("Root", "", new { controller = "Home", action = "Index" });

        context.MapRoute(
            "Public_default",
            "Public/{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            , new[] { "<Project Namespace here>.Areas.Public.Controllers" }
        );
    }
}

Dans mon AuthAreaRegistration.cs (zone d'accès restreint), j'ai

public class AuthAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Auth";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Auth_default",
            "Auth/{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Et enfin, mes liens dans mes pages * .cshtml seraient comme

1) @ Html.ActionLink ("Fermer la session", "Fermer la session", nouveau {area = "Public", controller = "Home"})

ou

2) @ Html.ActionLink ("Admin Area", "Index", new {area = "Auth", controller = "Home"})

J'espère que cela vous fera économiser des heures de recherche! BTW, je parle ici de MVC3.

Kwex.

2
Kwex

Ce n'est peut-être pas le cas pour la plupart des développeurs, mais j'ai rencontré ce problème lorsque j'ai ajouté une première zone et que je n'ai pas créé ma solution. Dès que j'ai construit ma solution, les liens ont commencé à se remplir correctement.

1
Abhi