asp.net-web-api – ASP.NET Web API RTM和子域路由
我在使用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; } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – aspnet_compiler找到错误版本的System.Web.WebP
- asp.net-mvc-3 – 请参阅控制器中的验证摘要
- ASP.Net C#ResolveClientUrl里面的类
- asp.net-mvc – 将依赖项注入自定义模型绑定器并使用Ninjec
- asp.net-mvc – Context.User.Identity.Name为null与Signal
- 使用ASP.NET MVC在JS文件中设置jQuery的ajax url
- asp.net-mvc – 地址字段的自定义ASP.NET MVC验证摘要
- asp.net-mvc – 概念类型中的成员数量不匹配 – 但确实如此
- 如何在IIS上解决接近100%的CPU利用率
- asp.net 中用easyui中的treegird的简单使用
- asp.net-mvc – 如何asp.net(mvc)服务器返回错误
- asp.net-mvc – 向MVC ModelMetadata添加新属性
- asp.net-mvc-5 – 使用Glass Mapper的Sitecore 8
- 我如何保护我的ASP.Net源代码从我的开发人员
- ASP.NET MVC4安全性,身份验证和授权
- asp.net – 可以为IIS的HTTP压缩添??加axd扩展吗
- asp.net-mvc-3 – @ Html.TextBoxFor文本框在验证
- 如何从asp.net HyperLink控件调用javascript
- Asp.Net,DropDownList,AutoPostBack和Google Chr
- asp.net-mvc – 使用Entity Framework 6和ViewMo