Reputation: 26331
I know how to add support for Query parameters on a GET request to the endpoint /resources
, for example. That would be:
[HttpGet]
public async Task<IHttpActionResult> GetAll([FromUri] QueryData queryData) {
//... Do some stuff
}
In my example, QueryData
would be a class containing all my supported query parameters:
public class QueryParam {
public int Page { get; set; }
public int Size { get; set; }
}
So, then I can call the endpoint: /resources?page=2&size=4
, and retrieve those parameters successfully.
But, what about doing the same but on the endpoint: /resources/2
??
2
is a segment of the URL and it specifies the id
of the resource.
At the moment, I am handling the method as follows:
[HttpGet]
public async Task<IHttpActionResult> Get(int id) {
//Do some stuff...
}
This works fine, but then I tried to modify it as:
[HttpGet]
public async Task<IHttpActionResult> Get(int id, [FromUri] QueryData queryData) {
//Do some stuff...
}
I hope it would work as it did on the other method, but it doesn't. Probably, because of the id
, which is not retrieved by query parameters, but instead is part of the URL path.
Is it possible to add query parameters to such an URL, and be able to retrieve both the id
and those parameters?
I'm looking forward to be able to call the endpoint: /resources/2?lang=en
Upvotes: 0
Views: 11910
Reputation: 9789
I was able to get Web API 2.2 properly parsing the route values and query string values with the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using WebAPITest.Models;
namespace WebAPITest.Controllers
{
public class ValuesController : ApiController
{
// GET api/values/5
public async Task<IHttpActionResult> Get(int id, [FromUri] QueryParam queryData)
{
return Ok("value");
}
}
}
Model:
using System;
namespace WebAPITest.Models
{
public class QueryParam
{
public int Page { get; set; }
public int Size { get; set; }
}
}
I adjusted the default ValuesController to use IHttpActionResult
instead of string. If you want to differentiate between routes, you can add attribute routes and decorate each action with their respective HTTP method. You shouldn't have to modify your routes directly or perform any extra parameter parsing within your controller actions.
Upvotes: 0
Reputation: 20033
One way to achieve what you want would be to read the id
manually, like this:
[HttpGet]
public async Task<IHttpActionResult> Get(int id, [FromUri]QueryData queryData) {
id = RouteData.Values["id"];
}
or
[HttpGet]
public async Task<IHttpActionResult> Get([FromUri]QueryData queryData) {
var id = RouteData.Values["id"];
}
If MVC yells about the ambiguity add a route constraint like this:
routes.MapRoute(
"Product",
"Product/{productId}",
new {controller="Product", action="Details"},
new {productId = @"\d+" }
);
Another thing you can try is to add ID as a QueryData property. It MAY populate it!
Upvotes: 1