在不使用 MVC 更改 URL 的情况下为特定 URL 创建路由 [英] Create Route for a specific URL without changing the URL with MVC

查看:27
本文介绍了在不使用 MVC 更改 URL 的情况下为特定 URL 创建路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a MVC Web Application that runs on www.domain.com and I need to configure a different URL binding for another domain www.domain2.com for the same web application.

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

The new domain www.domain2.com will have to return a specific Controller Action View like /Category/Cars:

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

如何在不更改 URL 的情况下实现这一点,因此访问者插入 url www.domain2.com 并接收视图 www.domain.com/category/cars 但网址仍然是 www.domain2.com?

How can I achieve this without changing the URL, so the visitor inserts the url www.domain2.com and receives the view www.domain.com/category/cars but the url remains www.domain2.com?

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

I have tried this approach but it's not working:

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

推荐答案

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

Domains are normally not part of routes, which is why your examples don't work. To make routes that work only on specific domains you have to customize routing.

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

By default, all of the routes in your route configuration will be available on all domains that can reach the web site.

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

The simplest solution for this is to create a custom route constraint and use it to control the domains that a specific URL will match.

    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:<port> 不是已配置的域.但是,如果您导航到:

If you fire this up in a new project in Visual Studio, you will notice it shows an error. This is because localhost:<port> is not a configured domain. However, if you navigate to:

/?domain=www.domain.com

您将看到主页.

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

This is because for the debug build only, it allows you to override the "local" domain name for testing purposes. You can configure your local IIS server to use a local static IP address (added to your network card) and add a local hosts file entry to test it locally without the query string parameter.

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

Note that when doing a "Release" build, there is no way to test using a query string parameter, as that would open up a potential security vulnerability.

如果您使用网址:

/?domain=www.domain2.com

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

it will run the CategoryController.Cars action method (if one exists).

请注意,由于 Default 路由涵盖了范围广泛的 URL,因此大部分站点都可用于 both www.domain.comwww.domain2.com.例如,您可以通过以下方式访问关于"页面:

Note that since the Default route covers a wide range of URLs, most of the site will be available to both www.domain.com and www.domain2.com. For example, you will be able to reach the About page both at:

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

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

You can use the IgnoreRoute extension method to block URLs that you don't want (and it accepts route constraints, so this solution will work there, too).

如果您主要希望在域之间共享功能,此解决方案将起作用.如果您希望在一个网站中有 2 个域,但要让它们像单独的网站一样,如果您使用 区域在您的项目中使用上述区域路线的路线约束.

This solution will work if you largely want to share functionality between domains. If you would rather have 2 domains in one web site, but make them act like separate web sites, it would be easier to manage if you use an Area for each "web site" in your project by using the above route constraint for the Area routes.

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 区域.

The above configuration would make every URL (that is 0, 1, 2, or 3 segments long) for www.domain2.com route to a controller in the Domain2 Area.

这篇关于在不使用 MVC 更改 URL 的情况下为特定 URL 创建路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆