具有默认路由的租户区域路由
Tenant area route with default route
所以我有一个网站,每个租户基本上有一个 'area'。所以它将显示为 www.site.com/ 并且将使用一个区域转到该组页面。
事实上,我还有一个区域外的默认路线,因此您可以转到 www.site.com/,它将带您到实际的 ~/Views/Home/Index 页面。但是,如果您尝试键入 www.site.com/Home/Index 或说要创建新组的页面 www.site.com/Group/Create 它认为它需要转到不存在的区域t存在并给出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} 是您当前正在访问的任何组,然后它会转到该组的常规 controller/action。然而,对于默认路线,它似乎仍然去区域路线而不是无论如何。
我在想可能会有后备方案。因此,当它尝试前往该区域但找不到正确的 controller/action 时,它将接下来检查默认路线。如果它仍然找不到任何东西,它将给出 404 错误资源无法找到。虽然我不太确定该怎么做。
所以要使 www.site.com/ 工作并允许 www.site.com/Home/Index 工作。
问题是,当您尝试访问 /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() }
);
}
假设您的组名永远不会与您的控制器名称相同(例如:Home),这应该可以工作
所以我有一个网站,每个租户基本上有一个 'area'。所以它将显示为 www.site.com/ 并且将使用一个区域转到该组页面。
事实上,我还有一个区域外的默认路线,因此您可以转到 www.site.com/,它将带您到实际的 ~/Views/Home/Index 页面。但是,如果您尝试键入 www.site.com/Home/Index 或说要创建新组的页面 www.site.com/Group/Create 它认为它需要转到不存在的区域t存在并给出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} 是您当前正在访问的任何组,然后它会转到该组的常规 controller/action。然而,对于默认路线,它似乎仍然去区域路线而不是无论如何。
我在想可能会有后备方案。因此,当它尝试前往该区域但找不到正确的 controller/action 时,它将接下来检查默认路线。如果它仍然找不到任何东西,它将给出 404 错误资源无法找到。虽然我不太确定该怎么做。
所以要使 www.site.com/ 工作并允许 www.site.com/Home/Index 工作。
问题是,当您尝试访问 /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() }
);
}
假设您的组名永远不会与您的控制器名称相同(例如:Home),这应该可以工作