Asp.net MVC 2领域。只有一个会起作用

时间:2010-12-10 23:11:17

标签: c# asp.net-mvc asp.net-mvc-2

这是我的目标:

我的MVC网络应用需要两个(或更多)“区域”。他们会这样访问:

/* 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

我会喜欢来组织项目,如下所示:

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

所以,在Global.asax我有:

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

以下是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'的设置相同,但网址参数为Admin/{action}/{id}

通过上面的设置,Web“区域”效果很好(example.com/about,example.com/contact等)。

我需要做些什么才能让Admin“区域”以我想要的方式与路线联系起来?我现在只需要404。<登记/> 我已经尝试过各种路由组合,路由w /名称空间,URL参数,参数默认值等等。 我有一种感觉,我错过了一些非常基本的东西。

3 个答案:

答案 0 :(得分:0)

我目前的解决方案是:http://notesforit.blogspot.com/2010/08/default-area-mvc-2.html

我不喜欢它,并希望得到更好的解决方案。

- 从上面的网址中复制:

通常实施您的区域,注册您需要的任何路线。

例如:

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

并且:

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

重要的是,该网址应包含任何前缀,例如http://site.com/PREFIX/ {controller} / {action},因为默认Area的前缀将被裁剪

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

不要忘记向web.config添加参数:

<configuration>

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

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

答案 1 :(得分:0)

我使用this AreaRegistrationUtil class。它会自动注册在您指定的任何程序集中继承AreaRegistration的任何内容。作为一个额外的好处,它比AreaRegistration.RegisterAllAreas更快,因为它只查看你指定的程序集。

答案 2 :(得分:0)

您可能需要在所有区域注册上设置名称空间。

实施例

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