【问题标题】:Tenant area route with default route带默认路由的租户区域路由
【发布时间】:2016-12-26 22:53:21
【问题描述】:

所以我有一个网站,基本上每个租户都有一个“区域”。所以它会显示为 www.site.com/ 并且会使用一个区域进入该组页面。

事情是我也有一个区域外的默认路线,所以你可以去 www.site.com/ 这将带你到实际的 ~/Views/Home/Index 页面。但是,如果您尝试键入 www.site.com/Home/Index 或说出创建新组 www.site.com/Group/Create 的页面,它认为它需要转到不存在的区域并给出找不到 404 资源。

这是 RouteConfig.cs 中的默认路由

        routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
             new { controller = "Home", action = "Index", id = UrlParameter.Optional },
             new[] { "TicketSystem.Controllers" }
        );

这是该地区的路线配置:

        context.MapRoute(
            "Group_default",
            "{group}/{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new[] { "TicketSystem.Areas.Group.Controllers" }); 

所以 {group} 是您当前正在访问的任何组,然后它会转到该组的常规控制器/操作。但是对于默认路由,无论如何它似乎仍然会转到区域路由。

我在想可能会有一个后备。因此,当它试图去该区域并且找不到正确的控制器/动作时,它将检查下一个默认路由。如果它仍然找不到任何东西,它将给出 404 错误资源找不到。虽然我不确定该怎么做。

所以要使 www.site.com/ 工作并允许 www.site.com/Home/Index 工作。

【问题讨论】:

  • group 的值是多少?它只能是您在应用程序中拥有的区域或任何随机字符串中的一个吗?
  • @Shyju 该区域的组值可以是任何字符串,只要它没有空格。加载该区域时,它会检查以确保该组存在于数据库中。所以它可能是 www.site.com/testgroup 或 www.site.com/othergroup 并且它们都应该进入实际组页面。
  • 所以你基本上只有一个区域。仪式?当组在 url 中时,您希望由区域处理吗?
  • 是的,单个区域将包含该组的所有访问/页面。任何不需要组的页面都将位于常规控制器/视图中。因此 www.site.com/group1 将转到该区域,但 www.site.com/home/index 将转到常规 Home 控制器和 Index 操作。目前它认为 www.site.com/home/index 中的主页是基于我的 OP 中的路由的组。
  • 我发布了一个应该可以正常工作的答案。

标签: c# asp.net-mvc asp.net-mvc-routing asp.net-mvc-areas


【解决方案1】:

问题是,当您尝试访问 /Home/Index 时,路由引擎不知道 "Home" ,您的意思是控制器名称或组名!

为了解决这个问题,您可以创建一个自定义路由约束来检查请求 url 中的组值是否是您应用中的有效控制器名称。如果是,该请求将不被区域路由注册定义处理。

public class GroupNameConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName,
                       RouteValueDictionary values, RouteDirection routeDirection)
    {
        var asm = Assembly.GetExecutingAssembly();

        //Get all the controller names

        var controllerTypes = (from t in asm.GetExportedTypes()
            where typeof(IController).IsAssignableFrom(t)
            select t.Name.Replace("Controller", ""));
        var groupName = values["group"];
        if (groupName != null)
        {
            if (controllerTypes.Any(x => x.Equals(groupName.ToString(),
                                                       StringComparison.OrdinalIgnoreCase)))
            {
                return false;
            }
        }
        return true;
    }
}

在注册区域路线时注册此约束。

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


        );
    }

假设您永远不会拥有与您的控制器名称相同的 groupName(例如:Home),这应该可以工作

【讨论】:

  • 太棒了,完美!我可以添加一个简单的检查,以确保人们不能使组名与任何控制器名称相同,这应该不难。第一次检查约束,我学习的最好方法是实际使用它们,现在我在自己的上下文中使用它们现在一切都有意义了。谢谢!
  • 对于那些进行分析的人,您可以添加if (groupName.ToString().Equals("VSEnterpriseHelper.axd", StringComparison.OrdinalIgnoreCase)){ return false; } 这将允许分析 axd 文件正常工作,而不是认为它是一个组。可能是一种更简单的方法,但它可以让您知道问题实际发生在哪里。如果你想要一个 asmx 文件之类的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-14
  • 2013-06-17
  • 2013-10-03
  • 2018-06-30
相关资源
最近更新 更多