加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-web-api – ASP.NET Web API RTM和子域路由

发布时间:2020-12-16 09:52:06 所属栏目:asp.Net 来源:网络整理
导读:我在使用Web API处理基于子域的路由时遇到问题.简而言之,我正在使用正确的控制器和方法,但是WebAPI没有获取子域外的数据令牌. 我在我的场景中有这个: contoso.myapp.comfabrikam.myapp.com{tenant}.myapp.com 所有解析到相同的ApiController,我希望能够提取
我在使用Web API处理基于子域的路由时遇到问题.简而言之,我正在使用正确的控制器和方法,但是WebAPI没有获取子域外的数据令牌.

我在我的场景中有这个:

contoso.myapp.com
fabrikam.myapp.com
{tenant}.myapp.com

所有解析到相同的ApiController,我希望能够提取{tenant}令牌.

我使用了本文中的代码http://blog.maartenballiauw.be/post/2012/06/18/Domain-based-routing-with-ASPNET-Web-API.aspx

但是在撰写文章和ASP.NET Web Api退出测试版之间,似乎已经发生了一些变化.本文中的代码依赖于RouteTable.Routes,而Web API路由是通过HttpConfiguration.Routes配置的,这是一个HttpRouteCollection而不是通常的RouteCollection(它实际上是从RouteCollection派生的).

所以我将代码改为派生自HttpRoute而不是Route.这是代码:

https://gist.github.com/3766125

我配置这样的路线

config.Routes.Add(new HttpDomainRoute(
            name: "test",domain: "{tenant}.myapp.com",routeTemplate: "test",defaults: new { controller = "SomeController",action = "Test" }
        ));

我的请求被路由到正确的控制器.但是,租户数据令牌永远不会被填充(如果我这样做.请求.GetRouteData()我看到控制器和动作令牌但不是租户).如果我在GetRouteData上放置断点,则永远不会调用它.

我试图跟随反射器的代码路径,看看在HttpRouteCollection级别调用GetRouteData的位置,但似乎该集合是空的.不确定如何桥接常规ASP.NET路由和WEb API路由之间的集成,但它让我感到困惑.

有任何想法吗?

我现在使用的解决方法是在Route上显式调用GetRouteData

this.Request.GetRouteData().Route.GetRouteData(this.Request.RequestUri.ToString(),this.Request)

解决方法

在考虑了这个之后,我有一个解决方法.解决方法的基本思想是使用从Route派生的路由并将其直接添加到RouteCollection.这样,我们传递的路由将不再包含在HttpWebRoute中.

RouteByPassing处理程序用于解决另一个已知问题.希望这可以帮助.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",routeTemplate: "api/{controller}/{id}",defaults: new { id = RouteParameter.Optional }
        );

        RouteTable.Routes.Add("test",new HttpDomainRoute(
            domain: "{tenant}.auth10.com",defaults: new { controller = "Values",action = "GetTenant" }
        ));

        config.MessageHandlers.Add(new RouteByPassingHandler());
    }
}

public class RouteByPassingHandler : DelegatingHandler
{
    protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,System.Threading.CancellationToken cancellationToken)
    {
        HttpMessageInvoker invoker = new HttpMessageInvoker(new HttpControllerDispatcher(request.GetConfiguration()));
        return invoker.SendAsync(request,cancellationToken);
    }
}

public class HttpDomainRoute
    : Route
{
    private Regex domainRegex;
    private Regex pathRegex;

    public HttpDomainRoute(string domain,string routeTemplate,object defaults,object constraints = null)
        : base(routeTemplate,new RouteValueDictionary(defaults),new RouteValueDictionary(constraints),new RouteValueDictionary(),HttpControllerRouteHandler.Instance)
    {
        this.Domain = domain;
    }

    public string Domain { get; set; }

    public override RouteData GetRouteData(HttpContextBase context) 
    {   
        // Build regex
        domainRegex = CreateRegex(this.Domain);
        pathRegex = CreateRegex(this.Url);

        // Request information
        string requestDomain = context.Request.Headers["Host"];
        if (!string.IsNullOrEmpty(requestDomain))
        {
            if (requestDomain.IndexOf(":") > 0)
            {
                requestDomain = requestDomain.Substring(0,requestDomain.IndexOf(":"));
            }
        }
        else
        {
            requestDomain = context.Request.Url.Host;
        }

        string requestPath = context.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + context.Request.PathInfo;

        // Match domain and route
        Match domainMatch = domainRegex.Match(requestDomain);
        Match pathMatch = pathRegex.Match(requestPath);

        // Route data
        RouteData data = null;
        if (domainMatch.Success && pathMatch.Success)
        {
            data = base.GetRouteData(context);

            // Add defaults first
            if (Defaults != null)
            {
                foreach (KeyValuePair<string,object> item in Defaults)
                {
                    data.Values[item.Key] = item.Value;
                }
            }

            // Iterate matching domain groups
            for (int i = 1; i < domainMatch.Groups.Count; i++)
            {
                Group group = domainMatch.Groups[i];
                if (group.Success)
                {
                    string key = domainRegex.GroupNameFromNumber(i);

                    if (!string.IsNullOrEmpty(key) && !char.IsNumber(key,0))
                    {
                        if (!string.IsNullOrEmpty(group.Value))
                        {
                            data.Values[key] = group.Value;
                        }
                    }
                }
            }

            // Iterate matching path groups
            for (int i = 1; i < pathMatch.Groups.Count; i++)
            {
                Group group = pathMatch.Groups[i];
                if (group.Success)
                {
                    string key = pathRegex.GroupNameFromNumber(i);

                    if (!string.IsNullOrEmpty(key) && !char.IsNumber(key,0))
                    {
                        if (!string.IsNullOrEmpty(group.Value))
                        {
                            data.Values[key] = group.Value;
                        }
                    }
                }
            }
        }

        return data;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext,RouteValueDictionary values) 
    {
        return base.GetVirtualPath(requestContext,RemoveDomainTokens(values));
    }

    private Regex CreateRegex(string source)
    {
        // Perform replacements
        source = source.Replace("/",@"/?");
        source = source.Replace(".",@".?");
        source = source.Replace("-",@"-?");
        source = source.Replace("{",@"(?<");
        source = source.Replace("}",@">([a-zA-Z0-9_-]*))");

        return new Regex("^" + source + "$");
    }

    private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
    {
        Regex tokenRegex = new Regex(@"({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?({[a-zA-Z0-9_-]*})*-?.?/?");
        Match tokenMatch = tokenRegex.Match(Domain);
        for (int i = 0; i < tokenMatch.Groups.Count; i++)
        {
            Group group = tokenMatch.Groups[i];
            if (group.Success)
            {
                string key = group.Value.Replace("{","").Replace("}","");
                if (values.ContainsKey(key))
                    values.Remove(key);
            }
        }

        return values;
    }
}

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读