在不使用MVC更改URL的情况下为特定URL创建路由

我有一个在www.domain.com上运行的MVC Web应用程序,我需要为另一个域www.domain2.com为同一个Web应用程序配置不同的URL绑定。

新域名www.domain2.com必须返回特定的控制器操作视图,例如/Category/Cars

 routes.MapRoute( name: "www.domain2.com", url: "www.domain2.com", defaults: new { controller = "Category", action = "Cars", id = UrlParameter.Optional } ); 

如何在不更改URL的情况下实现此目的,以便访问者插入urlwww.domain2.com并收到视图www.domain.com/category/cars但url仍为www.domain2.com

编辑:

我尝试过这种方法,但它不起作用:

 routes.MapRoute( "Catchdomain2", "{www.domain2.com}", new { controller = "Category", action = "Cars" } ); 

域通常不是路由的一部分,这就是为什么您的示例不起作用的原因。 要制作仅适用于特定域的路由,您必须自定义路由。

默认情况下,路由配置中的所有路由都可以在可以访问该网站的所有域上使用。

最简单的解决方案是创建自定义路由约束并使用它来控制特定URL匹配的域。

DomainConstraint

  public class DomainConstraint : IRouteConstraint { private readonly string[] domains; public DomainConstraint(params string[] domains) { this.domains = domains ?? throw new ArgumentNullException(nameof(domains)); } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { string domain = #if DEBUG // A domain specified as a query parameter takes precedence // over the hostname (in debug compile only). // This allows for testing without configuring IIS with a // static IP or editing the local hosts file. httpContext.Request.QueryString["domain"]; #else null; #endif if (string.IsNullOrEmpty(domain)) domain = httpContext.Request.Headers["HOST"]; return domains.Contains(domain); } } 

用法

 public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // This ignores Category/Cars for www.domain.com and www.foo.com routes.IgnoreRoute("Category/Cars", new { _ = new DomainConstraint("www.domain.com", "www.foo.com") }); // Matches www.domain2.com/ and sends it to CategoryController.Cars routes.MapRoute( name: "HomePageDomain2", url: "", defaults: new { controller = "Category", action = "Cars" }, constraints: new { _ = new DomainConstraint("www.domain2.com") } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // This constraint allows the route to work either // on "www.domain.com" or "www.domain2.com" (excluding any other domain) constraints: new { _ = new DomainConstraint("www.domain.com", "www.domain2.com") } ); } } 

如果在Visual Studio中的新项目中启动它,您会注意到它显示错误。 这是因为localhost:不是已配置的域。 但是,如果您导航到:

 /?domain=www.domain.com 

您将看到主页。

这是因为仅对于调试版本,它允许您覆盖“本地”域名以进行测试。 您可以 将本地IIS服务器配置为使用本地静态IP地址(添加到网卡)并添加本地主机文件条目以在本地测试它而不使用查询字符串参数

请注意,在执行“发布”构建时,无法使用查询字符串参数进行测试,因为这会打开潜在的安全漏洞。

如果您使用URL:

 /?domain=www.domain2.com 

它将运行CategoryController.Cars操作方法(如果存在)。

请注意,由于Default路由涵盖了大量url,因此大多数网站都可供www.domain.comwww.domain2.com 。 例如,您可以在以下位置访问“关于”页面:

 /Home/About?domain=www.domain.com /Home/About?domain=www.domain2.com 

您可以使用IgnoreRoute扩展方法来阻止您不想要的URL(并且它接受路由约束,因此此解决方案也将在那里工作)。

如果您非常希望在域之间共享function ,则此解决方案将起作用。 如果您希望在一个网站中拥有2个域,但让它们像单独的网站一样,如果您通过对区域使用上述路径约束为项目中的每个“网站”使用区域 ,则会更容易管理路线。

 public class Domain2AreaRegistration : AreaRegistration { public override string AreaName { get { return "Domain2"; } } public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( name: "Domain2_default", url: "{controller}/{action}/{id}", defaults: new { action = "Index", id = UrlParameter.Optional }, constraints: new { _ = DomainConstraint("www.domain2.com") } ); } } 

上述配置将使www.domain2.com 每个URL (即0,1,2或3段长)路由到Domain2区域中的控制器。

在应用程序的默认操作中,确保url是第二个域之一,然后返回所需的方法。 就像是:

  public ActionResult Index() { if (Request.Url.Host.Equals("domain2")) return AnotherAction(); } 

同意上面的答案。

如果你想要更漂亮的实现 – 尝试动作filter。 动作示例从那里过滤使用情况。

 public override void OnActionExecuting(ActionExecutingContext filterContext) { var controller = (SomeControllerBase) filterContext.Controller; filterContext.Result = controller.RedirectToAction("index", "home"); } 

从那里获取动作filter内的URL的示例。

 var url = filterContext.HttpContext.Request.Url; 

把东西放在一起,玩得开心:)