查询string在使用属性路由时不起作用
我正在使用System.Web.Http.RouteAttribute
和System.Web.Http.RoutePrefixAttribute
来为我的Web API 2应用程序启用更干净的URL。 对于我的大部分请求,我可以使用路由(例如Controller/param1/param2
)或者我可以使用查询string(例如Controller?param1=bob¶m2=mary
)。
不幸的是,我的一个控制器(也只有一个)失败了。 这是我的控制器:
[RoutePrefix("1/Names")] public class NamesController : ApiController { [HttpGet] [Route("{name}/{sport}/{drink}")] public List<int> Get(string name, string sport, string drink) { // Code removed... } [HttpGet] [Route("{name}/{drink}")] public List<int> Get(string name, string drink) { // Code removed... } }
当我请求使用路由时,两者都正常工作。 但是,如果我使用查询string,它会失败,告诉我,该path不存在。
我已经尝试添加以下内容到我的WebApiConfig.cs
类的Register(HttpConfiguration config)
函数(在Default路由之前和之后),但它什么也没做:
config.Routes.MapHttpRoute( name: "NameRoute", routeTemplate: "{verId}/Names/{name}/{sport}/{drink}", defaults: new { name = RouteParameter.Optional, sport = RouteParameter.Optional, drink = RouteParameter.Optional }, constraints: new { verId = @"\d+" });
所以为了清楚起见,我希望能够做到这一点:
localhost:12345/1/Names/Ted/rugby/coke localhost:12345/1/Names/Ted/coke
和,
localhost:12345/1/Names?name=Ted&sport=rugby&drink=coke localhost:12345/1/Names?name=Ted&drink=coke
但遗憾的是查询string版本不起作用! 🙁
更新
我已经完全删除了第二个动作,现在试图只使用可选参数的单个动作。 我已经改变了我的路线属性为[Route("{name}/{drink}/{sport?}")]
Tonybuild议让运动为空,但现在阻止localhost:12345/1/Names/Ted/coke
从一个有效的路由出于某种原因。 查询string的行为与以前相同。
更新2我现在在我的控制器中有一个单独的动作:
[RoutePrefix("1/Names")] public class NamesController : ApiController { [HttpGet] [Route("{name}/{drink}/{sport?}")] public List<int> Get(string name, string drink, string sport = "") { // Code removed... } }
但仍然使用查询string找不到合适的path,而使用路由方法。
我正面临着“如何将search参数作为查询string?”的问题,同时我正在尝试为当前项目构buildWeb API。 谷歌search后,以下工作适合我:
Api控制器操作:
[HttpGet, Route("search/{categoryid=categoryid}/{ordercode=ordercode}")] public Task<IHttpActionResult> GetProducts(string categoryId, string orderCode) { }
我通过邮递员试过的url:
http://localhost/PD/search?categoryid=all-products&ordercode=star-1932 http://localhost/PD is my hosted api
经过了很多艰辛的操作和谷歌search,我想出了一个“修复”。 我不知道这是不是理想/最好的做法/简单的错误,但它解决了我的问题。
我所做的只是添加[Route("")]
,除了我已经使用的路线属性。 这基本上允许Web API 2路由允许查询string,因为这现在是一个有效的路由。
现在是一个例子:
[HttpGet] [Route("")] [Route("{name}/{drink}/{sport?}")] public List<int> Get(string name, string drink, string sport = "") { // Code removed... }
这使得localhost:12345/1/Names/Ted/coke
和localhost:12345/1/Names?name=Ted&drink=coke
有效。
使用属性路由,您需要指定默认值,以便它们是可选的。
[Route("{name}/{sport=Football}/{drink=Coke}")]
指定一个值将使它成为可选的,所以你不必包含它,它会传递值来指定。
我没有testing这个查询string,但它应该工作相同。
我只是重读了这个问题,我发现你有两个Get动词,但是我相信这会导致冲突,因为路由不知道要使用哪一个,可能使用可选的参数将有所帮助。 你也可以指定一个可以为null,并在方法中检查如何继续。
[Route("{name}/{sport?}/{drink?}")]
然后检查方法中的variables,看它们是否为空,并根据需要进行处理。
希望这有助于一些? 大声笑
如果不是这个网站,也许会有更多关于属性路由的细节。
http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
从该网站剪辑:
可选参数和默认值您可以通过向参数添加问号来指定参数是可选的,即:
[Route("countries/{name?}")] public Country GetCountry(string name = "USA") { }
目前,动作select必须在可选参数上指定一个默认值才能成功,但我们可以调查解除这个限制。 (请让我们知道这是否重要。)
默认值可以用类似的方式指定:
[Route("countries/{name=USA}")] public Country GetCountry(string name) { }
可选参数'?' 并且缺省值必须在参数定义中的内联约束之后出现。
只是我的一个侧面说明。 为了使queryString参数工作,您需要为您的方法参数提供一个默认值,以使其成为可选参数 。 就像通常调用C#方法时一样。
[RoutePrefix("api/v1/profile")] public class ProfileController : ApiController { ... [HttpGet] [Route("{profileUid}")] public IHttpActionResult GetProfile(string profileUid, long? someOtherId) { // ... } ... }
这使我可以像这样调用端点:
/api/v1/profile/someUid /api/v1/profile/someUid?someOtherId=123
使用Route("search/{categoryid=categoryid}/{ordercode=ordercode}")
将使您能够使用querystrings和内联路由参数,如mosharaf hossain所回答的。 写这个答案,因为这应该是最好的答案和最好的办法。 如果您有多个获取/放置/post/删除,使用Route("")
将导致问题。
既然你有[Route("{name}/{drink}/{sport?}")]
作为属性路由,这个代码将永远不会被命中。
config.Routes.MapHttpRoute( name: "NameRoute", routeTemplate: "{verId}/Names/{name}/{sport}/{drink}", defaults: new { name = RouteParameter.Optional, sport = RouteParameter.Optional, drink = RouteParameter.Optional }, constraints: new { verId = @"\d+" });
所以只有属性路线[Route("{name}/{drink}/{sport?}")]
在这里将会被尊重。 由于您的请求localhost:12345/1/Names?name=Ted&sport=rugby&drink=coke
,所以在URL中不会有名称,运动或饮料匹配此属性路线。 匹配路由时我们不考虑查询string参数。
为了解决这个问题,你需要在你的属性path中设置所有3个选项。 然后它会匹配请求。
这是@bhargav kishore mummadireddy的答案的一个轻微的偏差,但是一个重要的偏差。 他的答案将默认querystring值为一个实际的非空值。 这个答案将默认为空。
它允许您通过path路由或使用查询string来调用控制器。 本质上,它将查询string的默认值设置为空,意味着它将始终被路由。
这对我很重要,因为如果没有指定查询string,而是让ASP.NET返回“无法在此控制器上find此方法”错误,我想返回400(错误请求)。
[RoutePrefix("api/AppUsageReporting")] public class AppUsageReportingController : ApiController { [HttpGet] // Specify default routing parameters if the parameters aren't specified [Route("UsageAggregationDaily/{userId=}/{startDate=}/{endDate=}")] public async Task<HttpResponseMessage> UsageAggregationDaily(string userId, DateTime? startDate, DateTime? endDate) { if (String.IsNullOrEmpty(userId)) { return Request.CreateResponse(HttpStatusCode.BadRequest, $"{nameof(userId)} was not specified."); } if (!startDate.HasValue) { return Request.CreateResponse(HttpStatusCode.BadRequest, $"{nameof(startDate)} was not specified."); } if (!endDate.HasValue) { return Request.CreateResponse(HttpStatusCode.BadRequest, $"{nameof(endDate)} was not specified."); } } }
我使用FromUri属性作为解决scheme
[Route("UsageAggregationDaily")] public async Task<HttpResponseMessage> UsageAggregationDaily([FromUri] string userId = null, [FromUri] DateTime? startDate = null, [FromUri] DateTime? endDate = null)
- ASP.NET MVC 4应用程序调用远程WebAPI
- 拒绝在框架中显示,因为它将“X-Frame-Options”设置为“SAMEORIGIN”
- “System.Net.Http.HttpContent”不包含“ReadAsAsync”的定义,也没有扩展方法
- HTTP错误500.19和错误代码:0x80070021
- 在Asp.Net的/ bin文件夹中,Roslyn“需要”什么/为什么?
- 如何将Web API添加到现有的ASP.NET MVC 4 Web应用程序项目?
- Asp.net Web API返回非描述性错误500
- Web API和Web服务有什么区别?
- 将Web API添加到现有的MVC Web应用程序后发生404错误