在不使用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.com
和www.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;
把东西放在一起,玩得开心:)