开发者

Asp.net MVC 2 Areas. Only one will work

This is my goal:

I need to two (or more) "Areas" for my MVC web app. They would be accessed like so:

/* Home */
http://example.com/
http://example.com/about
http://example.com/faq
http://example.com/contact

/* Admin */
http://example.com/admin
http://example.com/admin/login
http://example.com/admin/account
http://example.com/admin/ect

I would like to organize the project like the following:

MyExampleMVC2AreasProject/
    Areas/
        Admin/
            Controllers/
            Models/
            Views/
                Home/
                Shared/
                    Site.Master
                Web.Config
            AdminAreaRegistration.cs
        Web/
            Controllers/
            Models/
            Views/
                Home/
                Shared/
                    Site.Master
                Web.Config
            WebAreaRegistration.cs
    Global.asax
    Web.Config

So, in Global.asax I have:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

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

        RegisterRoutes(RouteTable.Routes);
    }

Here is WebAreaRegistration.cs

using System.Web.Mvc;

namespace MyExampleMVC2AreasProject.Areas.Web
{
    public class WebAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "Web";
            }
        }

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

'AdminAreadRegistration.cs' is set up the same but the url param is Admin/{action}/{id}.

With the setup above the Web "Area" w开发者_运维百科orks great (example.com/about, example.com/contact, etc).

What do I need to do to get the Admin "Area" hooked up with the routes the way I want them? I just get 404ed now.

I've tried every combination of routes, routes w/namespaces, URL Parameters, parameter defaults, etc, I could think of. I have a feeling I'm missing something pretty basic.


I use this AreaRegistrationUtil class. It automatically registers anything which inherits AreaRegistration in any assembly you specify. As an added bonus, it's WAY faster than AreaRegistration.RegisterAllAreas because it only looks at the assembly you specify.


You probably need to set your namespaces on all your area registrations.

Example

context.MapRoute(
    "Admin_default",
    "admin/{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new string[] { "MyExampleMVC2AreasProject.Areas.Admin.Controllers" } // This is area namespace
);


My current solution is here: http://notesforit.blogspot.com/2010/08/default-area-mvc-2.html

I don't like it and would love to get a better solution.

-- copied from URL above:

Implement your Areas as usually, register any routes that you need.

For example:

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

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

And:

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 {controller = "Overview", action = "Index", id = UrlParameter.Optional }
      );
    }
  }

It's important, that URL should have any prefix, for example http://site.com/PREFIX/{controller}/{action}, because prefix of default Area will be cropped

Next in Global.asax.cs:

public class MvcApplication : System.Web.HttpApplication
{
  public static string _defaultAreaKey = "DefaultArea";

  public static void RegisterDefaultRoute(RouteCollection routes)
  {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    //reading parameter DefaultArea from web.config 
    string defaultArea = ConfigurationManager.AppSettings[_defaultAreaKey];

    //check for null
    if (String.IsNullOrEmpty(defaultArea)) 
      throw new Exception("Default area isn\'t set");

    //select routes from registered, 
    //which have DataTokens["area"] == DefaultArea
    //Note, each Area might have more than one route
    var defRoutes = from Route route in routes
            where
            route.DataTokens != null &&
            route.DataTokens["area"] != null && 
            route.DataTokens["area"].ToString() == defaultArea
            select route;


    //cast to array, for LINQ query will be done,
    //because we will change collection in cycle
    foreach (var route in defRoutes.ToArray())
    {
      //Important! remove from routes' table
      routes.Remove(route);

      //crop url to first slash, ("Public/", "Admin/" etc.)
      route.Url = route.Url.Substring(route.Url.IndexOf("/") + 1);

      //Important! add to the End of the routes' table
      routes.Add(route);
    }      
  }

  protected void Application_Start()
  {
    //register all routes
    AreaRegistration.RegisterAllAreas();

    //register default route and move it to end of table
    RegisterDefaultRoute(RouteTable.Routes);      
  }
}

Do not forget add parameter to web.config:

<configuration>

 <appSettings>
  <add key="DefaultArea" value="Public"/>
 </appSettings>

<!-- ALL OTHER-->
</configuration>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜