为特定网址创建路由,而不使用MVC

时间:2018-01-31 12:56:53

标签: c# asp.net-mvc routes url-routing asp.net-mvc-routing

我有一个在www.domain.com上运行的MVC Web应用程序,我需要为同一个Web应用程序的另一个域www.domain2.com配置不同的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 }
);

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

编辑:

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

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

3 个答案:

答案 0 :(得分:6)

域通常部分路由,这就是您的示例不起作用的原因。要制作仅在特定域上工作的路线,您必须自定义路由。

  

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

最简单的解决方案是创建custom route constraint并使用它来控制特定网址匹配的域。

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

/?domain=www.domain.com

您将看到主页。

  

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

     

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

如果您使用网址:

/?domain=www.domain2.com

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

请注意,由于Default路线涵盖了广泛的网址,因此 www.domain.comwww.domain2.com都可以使用该网站的大部分内容。例如,您可以在以下位置访问“关于”页面:

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

您可以使用您不想要的IgnoreRoute extension method 阻止网址(并且它接受路由限制,因此此解决方案也可以在那里使用)。

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

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") }
        );
    }
}

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

答案 1 :(得分:0)

在应用程序的默认操作中,确保url是第二个域之一,然后返回需要的方法。类似的东西:

      public ActionResult Index()
      {

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

      }

答案 2 :(得分:0)

同意上面的答案。

如果你想要更漂亮的实现 - 尝试动作过滤器。 操作示例过滤了there的使用情况。

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

there获取动作过滤器内的网址的示例。

var url = filterContext.HttpContext.Request.Url;

把事情放在一起,玩得开心:)