ASP.NET MVC `Html.ActionLink` between “Areas”

后端 未结 6 541
灰色年华
灰色年华 2021-01-31 01:58

I have added a new Area to my MVC3 project and I am trying to link from the _Layout page to the new Area. I have added an Area called \'Admin\' that has a controller \'Meets\'.<

相关标签:
6条回答
  • 2021-01-31 02:31

    Verify that your AdminAreaRegistration class looks like this:

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

    and that you have this in Global.asax.cs:

    protected void Application_Start()
    {
        ... // ViewEngine Registration
        AreaRegistration.RegisterAllAreas();
        ... // Other route registration
    }
    
    0 讨论(0)
  • 2021-01-31 02:37

    This might not be the case for most of the developers but I encountered this problem when I added a my first area and did not build my solution. As soon as I build my solution the links started to populate correctly.

    0 讨论(0)
  • 2021-01-31 02:38

    Another option is to utilize RouteLink() instead of ActionLink(), which bypasses the area registrations altogether:

    ActionLink version:

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

    RouteLink version:

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

    The second parameter is a "Route Name" which is registered in Global.asax.cs and in various 'AreaRegistration' subclasses. To use 'RouteLink' to link between different areas, you only need to specify the correct route name.

    This following example shows how I would generate three links to different areas from a shared partial, which works correctly regardless of which area I am 'in' (if any):

    @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" })
    

    Happy coding!

    0 讨论(0)
  • 2021-01-31 02:38

    I solved this problem by doing the following.

    In my Global.asax.cs, I have

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

    In my PublicAreaRegistration.cs (Public Area), I've got

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

    In my AuthAreaRegistration.cs (Area for Restricted access), I've got

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

    And finally, my links in my *.cshtml pages would be like

    1) @Html.ActionLink("Log Off", "LogOff", new{area= "Public", controller="Home"})

    or

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

    Hope this saves someone hours of research! BTW, I'm talking about MVC3 here.

    Kwex.

    0 讨论(0)
  • 2021-01-31 02:47

    Strange indeed. Steps that worked perfectly fine for me:

    1. Create a new ASP.NET MVC 3 application using the default Visual Studio template
    2. Add an area called Admin using Visual Studio designer by right clicking on the project
    3. Add new Controller in ~/Areas/Admin/Controllers/MeetsController:

      public class MeetsController : Controller
      {
          public ActionResult Index()
          {
              return View();
          }
      }
      
    4. Add a corresponding view ~/Areas/Admin/Views/Meets/Index.cshtml

    5. In the layout (~/Views/Shared/_Layout.cshtml) add links:

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

    Rendered HTML for the anchors:

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

    As expected the first link works whereas the second doesn't.

    So what's the difference with your setup?

    0 讨论(0)
  • 2021-01-31 02:49

    I figured this out - I created a new test project and did exactly the same thing I was doing before and it worked...then after further inspection of all things route-related between the two projects I found a discrepancy.

    In the global.asax file in my BCC application, there was a rogue line of code which had inexplicably appeared:

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

    As you can see where my comment is, at some time or other I had placed the routes.Clear() call at the beginning of RegisterRoutes, which meant after I had registered the Areas in Application_Start, I was then immediately clearing what I had just registered.

    Thanks for the help...it did ultimately lead to my salvation!

    0 讨论(0)
提交回复
热议问题