【问题标题】:ASP.NET MVC IgnoreRoute() by domainASP.NET MVC IgnoreRoute() 按域
【发布时间】:2018-02-14 18:15:35
【问题描述】:

更新:为了简洁而重新措辞...

对于 ASP.NET MVC 项目,是否可以让 web.config 重写规则优先于 MVC 的 RegisterRoutes() 调用,或者是否可以仅针对特定域调用 IgnoreRoute

我有一个 MVC 应用程序,它接受多个域(mydomain.comotherdomain.com)的流量,该应用程序根据请求的主机提供不同的内容(即它是多租户的)。

我在 web.config 中配置了一个 URL 重写(反向代理),它应该只适用于特定的主机:

<rule name="Proxy" stopProcessing="true">
        <match url="proxy/(.*)" />
        <action type="Rewrite" url="http://proxydomain.com/{R:1}" />
        <conditions logicalGrouping="MatchAll">
            <add input="{HTTP_HOST}" pattern="^(mydomain\.com|www\.mydomain\.com)$" />
        </conditions>
        <serverVariables>
            <set name="HTTP_X_UNPROXIED_URL" value="http://proxydomain.com/{R:1}" />
            <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
            <set name="HTTP_X_ORIGINAL_HOST" value="{HTTP_HOST}" />
            <set name="HTTP_ACCEPT_ENCODING" value="" />
        </serverVariables>
    </rule>

然而,如果应用程序的RegisterRoutes() 方法忽略了 web.config 配置的路由,MVC 应用程序似乎只会使用:

routes.IgnoreRoute("proxy");

然后,不幸的是,将忽略应用于两个域。非常感谢您的建议...

【问题讨论】:

标签: asp.net asp.net-mvc iis azure-web-app-service orchardcms


【解决方案1】:

是否可以仅针对特定域调用 IgnoreRoute?

是的。 但是,由于 .NET 路由默认完全忽略域,因此您需要自定义路由以使 IgnoreRoute 特定于域。

虽然这样做是possible to subclass RouteBase,但最简单的解决方案是创建custom route constraint 并使用它来控制特定路由将匹配的域。路由约束可以与现有的MapRouteMapPageRouteIgnoreRoute 扩展方法一起使用,因此这是对现有配置的最小侵入性修复。

域约束

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

请注意,出于测试目的,当应用程序在调试模式下编译时,上述类接受查询字符串参数。这允许您使用像

这样的 URL
http://localhost:63432/Category/Cars?domain=mydomain.com

在本地测试约束,而无需配置本地 Web 服务器和主机文件。此调试功能未包含在发布版本中,以防止生产应用程序中可能出现的错误(漏洞)。

用法

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // This ignores Category/Cars for www.mydomain.com and mydomain.com
        routes.IgnoreRoute("Category/Cars", 
            new { _ = new DomainConstraint("www.mydomain.com", "mydomain.com") });

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

注意:在所有内置路由扩展(包括IgnoreRoute 和区域路由)上都有一个接受constraints 参数的重载。

参考:https://stackoverflow.com/a/48602769

【讨论】:

  • 我喜欢这种可插拔的方法
  • 这应该被标记为答案,它对我很有用。
【解决方案2】:

请使用 Ignore 代替 IgnoreRoute

routes.Ignore('url pattern here')

【讨论】:

    【解决方案3】:

    是否可以让 web.config 重写规则优先于 MVC 的 RegisterRoutes()

    是的。注意有一些Differences Between IIS URL Rewriting and ASP.NET Routing

    1. URL 重写用于在请求被处理之前操纵 URL 路径 由 Web 服务器处理。 URL重写模块不知道 哪个处理程序最终将处理重写的 URL。在 此外,实际的请求处理程序可能不知道该 URL 已重写。
    2. ASP.NET 路由用于将请求分派到基于处理程序的处理程序 请求的 URL 路径。与 URL 重写相反,路由 模块知道处理程序并选择应该的处理程序 为请求的 URL 生成响应。你可以想到 ASP.NET 路由作为一种高级处理程序映射机制。

    可以为特定域调用IgnoreRoute 吗?

    根据MSDN,可以使用接受url作为参数的版本。 但对于同一个域!考虑到在 ASP.NET MVC 应用程序中使用多个域时存在一些缺点:

    • 所有路由逻辑都是硬编码的:如果你想添加一个新的可能 路线,您必须为其编写代码。
    • 基于VirtualPathData 工作的 ASP.NET MVC 基础架构 班级。只有 URL 路径中的标记用于路由。

    如果您想要一个 MVC 应用程序来处理多个域,并以不同方式路由每个域,您需要使用开箱即用的 MVC 路由处理。但是,using a custom site route inheriting from RouteBase 是可能的。

    现在让我们讨论以下内容:

    routes.IgnoreRoute("proxy"); 将忽略应用于两者 域。

    我认为规则不能完美运行,因为处理到达ASP.NET 路由!可能的原因可以在 web.config 中的ServiceModel 标签中找到。添加serviceHostingEnvironment 代码如下:

    <system.serviceModel>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    

    这将允许路由通过 IIS 来处理。

    还将&lt;match url="proxy/(.*)" /&gt; 更改为&lt;match url="^proxy/(.*)" /&gt;(带有额外的^),这很普遍。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-08
      • 2011-08-12
      • 2010-10-22
      • 2011-03-16
      • 2011-03-10
      • 2013-02-20
      • 2014-01-03
      • 2011-09-05
      相关资源
      最近更新 更多