我有一个 ASP.NET MVC 4 应用程序,其中有两个区域:
- 后台
- 注册
我有一个名为的类DomainRoute
,可以将整个子域路由到一个区域:
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using System.Web.Routing;
namespace Admin.Web.PresentationLogic
{
/// <summary>
/// DomainRoute is an extension of the default Route, that makes it possible to route domains and subdomains the specific controllers.
/// </summary>
public class DomainRoute : Route
{
private string _subDomain;
private string[] _namespaces;
/// <summary>
/// Initializes a new instance of the <see cref="DomainRoute"/> class.
/// </summary>
/// <param name="subDomain">The sub domain.</param>
/// <param name="url">The URL format.</param>
/// <param name="defaults">The defaults.</param>
public DomainRoute(string subDomain, string url, RouteValueDictionary defaults)
: base(url, defaults, new MvcRouteHandler())
{
this._subDomain = subDomain;
}
/// <summary>
/// Initializes a new instance of the <see cref="DomainRoute" /> class.
/// </summary>
/// <param name="subDomain">The sub domain.</param>
/// <param name="url">The URL format.</param>
/// <param name="defaults">The defaults.</param>
/// <param name="namespaces">The namespaces.</param>
public DomainRoute(string subDomain, string url, RouteValueDictionary defaults, string[] namespaces)
: base(url, defaults, new MvcRouteHandler())
{
this._subDomain = subDomain;
this._namespaces = namespaces;
}
/// <summary>
/// Returns information about the requested route.
/// </summary>
/// <param name="httpContext">An object that encapsulates information about the HTTP request.</param>
/// <returns>
/// An object that contains the values from the route definition.
/// </returns>
public override RouteData GetRouteData(System.Web.HttpContextBase httpContext)
{
// Request information
string requestDomain = httpContext.Request.Headers["HOST"];
if (!string.IsNullOrEmpty(requestDomain))
{
if (requestDomain.IndexOf(":") > 0)
{
requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":"));
}
}
else
{
requestDomain = httpContext.Request.Url.Host;
}
var index = requestDomain.IndexOf(".");
if (index < 0)
{
return RouteTable.Routes["Default"].GetRouteData(httpContext);
}
var subDomain = requestDomain.Substring(0, index);
if (!String.IsNullOrWhiteSpace(subDomain))
{
if (this._subDomain.Equals(subDomain, StringComparison.InvariantCultureIgnoreCase))
{
RouteData data = new RouteData(this, this.RouteHandler);
// Add defaults first
if (Defaults != null)
{
foreach (KeyValuePair<string, object> item in Defaults)
{
data.Values[item.Key] = item.Value;
}
}
var pathRegex = this.CreateRegex(Url);
var requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
// Match domain and route
Match pathMatch = pathRegex.Match(requestPath);
// Iterate matching path groups
for (int i = 1; i < pathMatch.Groups.Count; i++)
{
Group group = pathMatch.Groups[i];
if (group.Success)
{
string key = pathRegex.GroupNameFromNumber(i);
if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
{
if (!string.IsNullOrEmpty(group.Value))
{
data.Values[key] = group.Value;
}
}
}
}
if (!data.Values.ContainsKey("action"))
{
data.Values.Add("action", "Index");
}
data.DataTokens["Namespaces"] = this._namespaces;
data.DataTokens["area"] = data.Values["area"] ?? this._subDomain;
return data;
}
}
return RouteTable.Routes["Default"].GetRouteData(httpContext);
}
/// <summary>
/// Creates the regex.
/// </summary>
/// <param name="source">The source.</param>
/// <returns>Returns the Regex for the source.</returns>
private Regex CreateRegex(string source)
{
// Perform replacements
source = source.Replace("/", @"\/?");
source = source.Replace(".", @"\.?");
source = source.Replace("-", @"\-?");
source = source.Replace("{", @"(?<");
source = source.Replace("}", @">([a-zA-Z0-9_]*))");
return new Regex("^" + source + "$");
}
}
}
当我注册区域时,我这样做:
context.Routes.Add("Signup_default",
new DomainRoute("signup", "{controller}/{action}/{id}",
new RouteValueDictionary(new { area = "Signup", controller = "Home", action = "Index", id = UrlParameter.Optional }),
new string[] { "Admin.Web.Areas.Signup.Controllers" }));
因此,问题与DomainRoute
'GetRouteData
方法的执行方式有关。
每当我尝试访问该类signup.localhost
的实例时,就是我在注册 Backstage 区域时使用的实例。DomainRoute
我尝试禁用后台区域,然后注册区域工作。
它使用的实例DomainRoute
首先出现在RouteTable
.
我错过了什么?