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

Pat*_*ick 5 c# asp.net-mvc routes url-routing asp.net-mvc-routing

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

新域www.domain2.com必须返回特定的Controller Action View,如/Category/Cars:

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

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

编辑:

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

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

Nig*_*888 6

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

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

最简单的解决方案是创建自定义路由约束并使用它来控制特定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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

用法

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") }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

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

/?domain=www.domain.com
Run Code Online (Sandbox Code Playgroud)

您将看到主页.

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

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

如果您使用URL:

/?domain=www.domain2.com
Run Code Online (Sandbox Code Playgroud)

它将运行CategoryController.Carsaction方法(如果存在).

请注意,由于Default航线涵盖范围广泛的URL,大部分网站将提供给双方 www.domain.comwww.domain2.com.例如,您可以在以下位置访问"关于"页面:

/Home/About?domain=www.domain.com
/Home/About?domain=www.domain2.com
Run Code Online (Sandbox Code Playgroud)

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

如果您主要希望在域之间共享功能,则此解决方案将起作用.如果您希望在一个网站中拥有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") }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Art*_*ick 0

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

      public ActionResult Index()
      {

        if (Request.Url.Host.Equals("domain2"))
            return AnotherAction();

      }
Run Code Online (Sandbox Code Playgroud)