0

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

2 Answers 2

1

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!

Sign up to request clarification or add additional context in comments.

7 Comments

I thought about this, but the Web API will find an ambiguosity between the methods GetAll(QueryData) and Get(QueryData), as both take the same parameters and both are bound to HttpGet
You can always add a constraint for id to be int.
There are some resources that have string ids, so unfortunately that won't be an option
You can add a separate route for this controller.
Another thing you can try is to add ID as a QueryData property. It MAY populate it!
|
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.