ASP.NET MVC多域名场景:web.config重写优先级与域名专属IgnoreRoute
1. web.config URL重写规则是否优先于MVC的RegisterRoutes?
当然可以,而且默认情况下IIS的URL重写模块就是在MVC路由之前执行的。
原因很简单:ASP.NET的请求管道是分层的,IIS的URL重写属于底层的HTTP模块处理阶段(在BeginRequest事件之前就会触发),而MVC的RegisterRoutes是在ASP.NET路由模块中执行的,这个阶段已经是请求进入ASP.NET应用之后的环节了。也就是说,当请求到达你的MVC应用时,URL已经被web.config里的重写规则修改过了,MVC路由只会处理重写后的URL。
举个例子:如果你的web.config里把otherdomain.com/old-path重写到mydomain.com/new-path,那么MVC路由收到的请求路径是/new-path,完全不会感知到原始的/old-path。这对你的多租户场景来说非常友好,反向代理的重写逻辑可以完全独立于MVC路由工作。
2. 能否仅针对特定域名调用IgnoreRoute()?
默认的IgnoreRoute()是全局生效的,但我们可以通过自定义路由约束来实现仅对特定域名忽略路由的需求,这比在请求管道里硬编码判断要更符合MVC的设计理念。
实现步骤:
首先,创建一个自定义的域名路由约束类,实现IRouteConstraint接口:
public class DomainMatchConstraint : IRouteConstraint { private readonly string _targetDomain; public DomainMatchConstraint(string targetDomain) { _targetDomain = targetDomain.ToLowerInvariant(); } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { // 如果用了反向代理,记得检查X-Forwarded-Host头,避免取到代理服务器的域名 var requestHost = httpContext.Request.Headers["X-Forwarded-Host"] ?? httpContext.Request.Url.Host; return requestHost.Equals(_targetDomain, StringComparison.OrdinalIgnoreCase); } }
然后在RegisterRoutes方法中,给IgnoreRoute添加这个约束:
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{*pathInfo}", new { domainConstraint = new DomainMatchConstraint("otherdomain.com") }); // 你的其他MVC路由注册代码 routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }
这样一来,只有当请求来自otherdomain.com时,所有路径({*pathInfo})都会被MVC路由忽略,不会触发任何控制器的动作。如果你的反向代理已经处理了该域名的请求,这个忽略规则可以确保MVC不会再处理这些请求,避免冲突。
另外,如果你需要更灵活的控制(比如只忽略特定域名下的某些路径),可以调整约束逻辑,或者用MapRoute结合StopRoutingHandler来实现:
routes.MapRoute( name: "IgnoreOtherDomain", url: "{*pathInfo}", defaults: null, constraints: new { domainConstraint = new DomainMatchConstraint("otherdomain.com") }, routeHandler: new StopRoutingHandler() );
效果和IgnoreRoute是一样的,只是写法更灵活。
内容的提问来源于stack exchange,提问作者DannyT

