我尝试路由到基于子域的区域,同时 URL 不包含区域参数。
例如,我希望能够走以下路线
example1.domain.com/login
example1.domain.com/landingpage
example2.domain.com/login
example2.domain.com/landingpage
我想让每个子域路由到不同的区域。我尝试关注这篇文章Is it possible to make an ASP.NET MVC route based on a subdomain?这导致我http://benjii.me/2015/02/subdomain-routing-in-asp-net-mvc/ 。但我似乎不知道如何在 URL 中不包含 Area 参数。
如何获得我正在寻找的正确 URL 架构? {子域名}.domain.com/{action}/{id}
最佳答案
要在区域中使用路由,除了执行其他子域路由之外,还需要将 DataTokens["area"]
参数设置为正确的区域。这是一个例子:
子域路由
public class SubdomainRoute : Route
{
// Passing a null subdomain means the route will match any subdomain
public SubdomainRoute(string subdomain, string url, IRouteHandler routeHandler)
: base(url, routeHandler)
{
this.Subdomain = subdomain;
}
public string Subdomain { get; private set; }
public override RouteData GetRouteData(HttpContextBase httpContext)
{
// A subdomain specified as a query parameter takes precedence over the hostname.
string subdomain = httpContext.Request.Params["subdomain"];
if (subdomain == null)
{
string host = httpContext.Request.Headers["Host"];
int index = host.IndexOf('.');
if (index >= 0)
subdomain = host.Substring(0, index);
}
// Check if the subdomain matches this route
if (this.Subdomain != null && !this.Subdomain.Equals(subdomain, StringComparison.OrdinalIgnoreCase))
return null;
var routeData = base.GetRouteData(httpContext);
if (routeData == null) return null; // The route doesn't match - exit early
// Store the subdomain as a datatoken in case it is needed elsewhere in the app
routeData.DataTokens["subdomain"] = subdomain;
return routeData;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
// Read the current query string and cascade it to the current URL only if it exists
object subdomainParam = requestContext.HttpContext.Request.Params["subdomain"];
if (subdomainParam != null)
values["subdomain"] = subdomainParam;
return base.GetVirtualPath(requestContext, values);
}
}
路由集合扩展
这些扩展方法允许您在应用程序的非区域部分注册路由以使用子域。
public static class RouteCollectionExtensions
{
public static SubdomainRoute MapSubdomainRoute(
this RouteCollection routes,
string subdomain,
string url,
object defaults = null,
object constraints = null,
string[] namespaces = null)
{
return MapSubdomainRoute(routes, null, subdomain, url, defaults, constraints, namespaces);
}
public static SubdomainRoute MapSubdomainRoute(
this RouteCollection routes,
string name,
string subdomain,
string url,
object defaults = null,
object constraints = null,
string[] namespaces = null)
{
var route = new SubdomainRoute(subdomain, url, new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, route);
return route;
}
}
区域注册上下文扩展
这些扩展方法允许您注册区域路由以使用子域。
public static class AreaRegistrationContextExtensions
{
public static SubdomainRoute MapSubdomainRoute(
this AreaRegistrationContext context,
string url,
object defaults = null,
object constraints = null,
string[] namespaces = null)
{
return MapSubdomainRoute(context, null, url, defaults, constraints, namespaces);
}
public static SubdomainRoute MapSubdomainRoute(
this AreaRegistrationContext context,
string name,
string url,
object defaults = null,
object constraints = null,
string[] namespaces = null)
{
if ((namespaces == null) && (context.Namespaces != null))
{
namespaces = context.Namespaces.ToArray<string>();
}
var route = context.Routes.MapSubdomainRoute(name,
context.AreaName, url, defaults, constraints, namespaces);
bool flag = (namespaces == null) || (namespaces.Length == 0);
route.DataTokens["UseNamespaceFallback"] = flag;
route.DataTokens["area"] = context.AreaName;
return route;
}
}
用法
要获取 URL 模式 {subdomain}.domain.com/{action}/{id}
来使用特定的特定区域,您只需将其注册为 的一部分区域注册
.
public class AppleAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Apple";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapSubdomainRoute(
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
}
NOTE: Your example URL has a limitation that you can only use a single controller per area.
controller
is a required route value, so you either need to supply it in the URL ({controller}/{action}/{id}
) or default it as the above example - the latter case means you can only have 1 controller.
当然,您还需要设置 DNS 服务器才能使用子域。
关于asp.net-mvc - 基于子域到区域的路由,同时保持相同的 URL 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46658751/