要在保留标准 MVC5 路由功能的同时捕获子域,请使用从 Route 派生的以下 SubdomainRoute 类。
此外,SubdomainRoute 允许选择将子域指定为 查询参数,使 sub.example.com/foo/bar 和 example.com/foo/bar?subdomain=sub 等效。这允许您在配置 DNS 子域之前进行测试。查询参数(使用时)通过Url.Action等生成的新链接传播。
查询参数还可以使用 Visual Studio 2013 进行本地调试,而无需 configure with netsh or run as Administrator。默认情况下,IIS Express 仅在非提升时绑定到 localhost;它不会绑定到像 sub.localtest.me 这样的同义主机名。
class SubdomainRoute : Route
{
public SubdomainRoute(string url) : base(url, new MvcRouteHandler()) {}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeData = base.GetRouteData(httpContext);
if (routeData == null) return null; // Only look at the subdomain if this route matches in the first place.
string subdomain = httpContext.Request.Params["subdomain"]; // A subdomain specified as a query parameter takes precedence over the hostname.
if (subdomain == null) {
string host = httpContext.Request.Headers["Host"];
int index = host.IndexOf('.');
if (index >= 0)
subdomain = host.Substring(0, index);
}
if (subdomain != null)
routeData.Values["subdomain"] = subdomain;
return routeData;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
object subdomainParam = requestContext.HttpContext.Request.Params["subdomain"];
if (subdomainParam != null)
values["subdomain"] = subdomainParam;
return base.GetVirtualPath(requestContext, values);
}
}
为方便起见,从您的 RegisterRoutes 方法调用以下 MapSubdomainRoute 方法,就像您使用旧的 MapRoute 一样:
static void MapSubdomainRoute(this RouteCollection routes, string name, string url, object defaults = null, object constraints = null)
{
routes.Add(name, new SubdomainRoute(url) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
});
}
最后,为了方便地访问子域(从真正的子域或查询参数),创建一个具有 Subdomain 属性的 Controller 基类会很有帮助:
protected string Subdomain
{
get { return (string)Request.RequestContext.RouteData.Values["subdomain"]; }
}