ASP.NET Web API带问号查询字符串参数获取失败的解决方法求助
解决ASP.NET Web API问号查询参数无法捕获的问题
哎,这个问题我之前折腾过好一会儿!核心原因其实是HTTP协议里?的原生作用——它是用来分隔路径部分和查询字符串部分的,ASP.NET Web API默认会严格遵循这个规则:?后面的内容会被单独解析为查询参数,不会被路由模板里的{text}占位符捕获,这就是为什么加了?之后你的x1、x2会变成null的原因。
下面给你几个可行的解决思路,你可以根据自己的需求选:
方案一:兼容两种参数传递方式(推荐)
不用改全局设置,直接在控制器方法里同时处理路径参数和查询参数,不管用户带不带?都能拿到值。比如这样写:
public IHttpActionResult Get(string text = null) { string date1 = null; string date2 = null; // 先处理不带?的情况:从text里解析参数 if (!string.IsNullOrEmpty(text)) { var pathParams = HttpUtility.ParseQueryString(text); date1 = pathParams["date1"]; date2 = pathParams["date2"]; } // 如果text里没拿到,再从查询字符串(带?的情况)里取 if (string.IsNullOrEmpty(date1)) { date1 = Request.GetQueryNameValuePairs() .FirstOrDefault(kv => kv.Key.Equals("date1", StringComparison.OrdinalIgnoreCase)) .Value; } if (string.IsNullOrEmpty(date2)) { date2 = Request.GetQueryNameValuePairs() .FirstOrDefault(kv => kv.Key.Equals("date2", StringComparison.OrdinalIgnoreCase)) .Value; } // 这里写你的业务逻辑 return Ok(new { Date1 = date1, Date2 = date2 }); }
这个方法最稳妥,不会影响其他API的正常使用,还能兼容两种访问方式。
方案二:自定义路由,让?后面的内容也被路由捕获
如果你一定要让?后面的内容也被{text}占位符捕获,那需要自定义路由逻辑,绕过Web API默认的?分隔规则。
首先创建一个自定义路由类:
public class CustomHttpRoute : HttpRoute { public CustomHttpRoute(string routeTemplate, HttpRouteValueDictionary defaults, HttpRouteValueDictionary constraints, HttpRouteValueDictionary dataTokens) : base(routeTemplate, defaults, constraints, dataTokens) { } public override IHttpRouteData GetRouteData(string virtualPathRoot, HttpRequestMessage request) { // 获取完整的路径+查询字符串 var fullPath = request.RequestUri.PathAndQuery; if (fullPath.StartsWith(virtualPathRoot)) { fullPath = fullPath.Substring(virtualPathRoot.Length); } // 把?转成URL编码的%3F,让路由系统把它当成路径的一部分 var modifiedPath = fullPath.Replace("?", "%3F"); return base.GetRouteData(virtualPathRoot, new HttpRequestMessage(request.Method, virtualPathRoot + modifiedPath)); } }
然后创建对应的路由处理器:
public class CustomHttpRouteHandler : HttpControllerRouteHandler { protected override IHttpHandler GetHttpHandler(RequestContext requestContext) { return new HttpControllerHandler(requestContext); } }
最后在WebApiConfig.cs里替换默认的路由注册:
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "v1/{controller}/{text}", defaults: new { text = RouteParameter.Optional }, routeHandler: new CustomHttpRouteHandler() );
这样路由系统就会把?和后面的内容当成text参数的一部分,你就可以像之前解析不带?的情况一样处理了。不过要注意,这个方法是全局生效的,可能会影响其他路由的正常查询参数解析,所以要谨慎使用。
不推荐的方案:全局禁用查询字符串解析
如果你想完全禁用Web API对查询字符串的解析,这会导致所有依赖查询参数的API都失效,非常不建议这么做,所以就不展开讲了。
内容的提问来源于stack exchange,提问作者kevin
相关产品推荐
相关产品推荐

