MVC自定义路由子域
我正在尝试构建一个连接到MVC区域的“租户”子域路由。 在这种情况下,我有一个名为“Tenant”的区域,它有两个控制器; 公共和管理员。 我的自定义路由用于抓取子域,如果它匹配然后路由到适当的控制器行动区。
这个项目的基础来自以下http://www.matrichard.com/post/asp.net-mvc-5-routing-with-subdomain
我遇到的问题是在自定义子域路由中。 当我点击Public/Index
Route时, routeData
返回null,我看到下面的错误。 虽然如果路由是/admin
它将返回正确的routeData
。
'/'应用程序中的服务器错误。
匹配的路线不包含“控制器”路线值,这是必需的。
它似乎也总是使用RouteDebugger工具进行匹配,这是我的问题的线索吗?
示例路线:
控制器=公共行动=指数,面积=租户
http://tenant1.mydomain.com:8080/
http://tenant1.mydomain.com:8080/logon
controller = Admin action = Index,area = Tenant
http://tenant1.mydomain.com:8080/admin
http://tenant1.mydomain.com:8080/admin/edit
-
SubdomainRouteP.cs
public class SubdomainRouteP : Route
{
public string Domain { get; set; }
public SubdomainRouteP(string domain, string url, RouteValueDictionary defaults): this(domain, url, defaults, new MvcRouteHandler())
{
}
public SubdomainRouteP(string domain, string url, object defaults): this(domain, url, new RouteValueDictionary(defaults), new MvcRouteHandler())
{
}
public SubdomainRouteP(string domain, string url, object defaults, IRouteHandler routeHandler): this(domain, url, new RouteValueDictionary(defaults), routeHandler)
{
}
public SubdomainRouteP(string domain, string url, RouteValueDictionary defaults, IRouteHandler routeHandler): base(url, defaults, routeHandler)
{
this.Domain = domain;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
//
// routeData object returns null in some cases
//
var routeData = base.GetRouteData(httpContext);
var subdomain = httpContext.Request.Url.Host.Split('.').First();
string[] blacklist = { "www", "mydomain", "localhost" };
// This will ignore anything that is not a client tenant prefix
if (blacklist.Contains(subdomain))
{
return null; // Continue to the next route
}
// Why is this NULL?
if (routeData == null)
{
routeData = new RouteData(this, new MvcRouteHandler());
}
routeData.DataTokens["Area"] = "Tenant";
routeData.DataTokens["UseNamespaceFallback"] = bool.FalseString;
routeData.Values.Add("subdomain", subdomain);
// IMPORTANT: Always return null if there is no match.
// This tells .NET routing to check the next route that is registered.
return routeData;
}
}
RouteConfig.cs
routes.Add("Admin_Subdomain", new SubdomainRouteP(
"{client}.mydomain.com", //of course this should represent the real intent…like I said throwaway demo project in local IIS
"admin/{action}/{id}",
new { controller = "Admin", action = "Index", id = UrlParameter.Optional }));
routes.Add("Public_Subdomain", new SubdomainRouteP(
"{client}.mydomain.com", //of course this should represent the real intent…like I said throwaway demo project in local IIS
"{controller}/{action}/{id}",
new { controller = "Public", action = "Index", id = UrlParameter.Optional }));
// This is the MVC default Route
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
下面的Url给了我RouteDebugger的以下结果。 在测试1和2期间,路由仍然匹配/ admin。
测试失败1: http://tenant.mydomain.com/
: http://tenant.mydomain.com/
测试2失败: http://tenant.mydomain.com/logon
: http://tenant.mydomain.com/logon
成功3: http://tenant.mydomain.com/admin
: http://tenant.mydomain.com/admin
匹配Url默认值
真正的 admin/{action}/{id}
controller = Admin, action = Index
True {controller}/{action}/{id}
controller = Public, action = Index
您链接的帖子有一个错误:当约束或URL不匹配时, base.GetRouteData
方法将返回null
。 在这种情况下,将子域名添加到路由字典显然会引发异常。 在该行之前应该有一个空警戒条款。
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeData = base.GetRouteData(httpContext);
if (routeData != null)
{
routeData.Values.Add("client", httpContext.Request.Url.Host.Split('.').First());
}
return routeData;
}
你的路线应该如此。 您需要确保在基类返回null(表示URL或约束不匹配,并且我们需要跳过处理此路由)的情况下返回null。
另外,我不确定它是否与将数据直接添加到DataTokens
什么不同,但是MVC框架具有IRouteWithArea
,可以实现该IRouteWithArea
以配置路由适用的区域。
public class SubdomainRouteP : Route, IRouteWithArea
{
public string Area { get; private set; }
public SubdomainRouteP(string area, string url, RouteValueDictionary defaults): this(area, url, defaults, new MvcRouteHandler())
{
}
public SubdomainRouteP(string area, string url, object defaults): this(area, url, new RouteValueDictionary(defaults), new MvcRouteHandler())
{
}
public SubdomainRouteP(string area, string url, object defaults, IRouteHandler routeHandler): this(area, url, new RouteValueDictionary(defaults), routeHandler)
{
}
public SubdomainRouteP(string area, string url, RouteValueDictionary defaults, IRouteHandler routeHandler): base(url, defaults, routeHandler)
{
this.Area = area;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeData = base.GetRouteData(httpContext);
// This will ignore anything where the URL or a constraint doesn't match
// in the call to base.GetRouteData().
if (routeData != null)
{
var subdomain = httpContext.Request.Url.Host.Split('.').First();
string[] blacklist = { "www", "mydomain", "localhost" };
// This will ignore anything that is not a client tenant prefix
if (blacklist.Contains(subdomain))
{
return null; // Continue to the next route
}
routeData.DataTokens["UseNamespaceFallback"] = bool.FalseString;
routeData.Values.Add("subdomain", subdomain);
}
// IMPORTANT: Always return null if there is no match.
// This tells .NET routing to check the next route that is registered.
return routeData;
}
}
我无法弄清楚你想用domain
参数做什么。 该网址很可能会返回域名。 因此,您似乎应该在第一个"{controller}/{action}/{id}"
路线中有一个约束,否则您将永远不会有通过默认路由的情况。 或者,您可以在网址中使用明确的细分,以便区分它(与您的管理路线相同)。
routes.Add("Admin_Subdomain", new SubdomainRouteP(
"Tenant",
"admin/{action}/{id}",
new { controller = "Admin", action = "Index", id = UrlParameter.Optional }));
routes.Add("Public_Subdomain", new SubdomainRouteP(
"Tenant",
"public/{action}/{id}",
new { controller = "Public", action = "Index", id = UrlParameter.Optional }));
// This is the MVC default Route
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
另一个选择是添加另一个构造函数参数,以传递一个显式的有效域列表来检查。
链接地址: http://www.djcxy.com/p/36763.html上一篇: MVC Custom Routing Subdomain
下一篇: Getting error 404 not found with ASP.NET MVC Area routing