Search code examples
c#apiasp.net-coremodel-bindinghttp-get

ASP.Net Core 6 HttpGet API ==> How to bind [FromQuery] parameter to C# object data type


I'm trying to pass a value to an endpoint created with ASP.Net Core 6 API with the following details:

Controller, Action & Model

[ApiController]
[Route("api/test")]
public class TestController
{
    [HttpGet]
    public bool Get([FromQuery] Filter filter)
    {
        return true;
    }
}

public class Filter
{
    public object Equal { get; set; }
}

Request URL

https://localhost:7134/api/test?Equal=50

As you can see the Equal property is of type object.

Note
Here is a simplified version of the situation I'm facing, and the Filter model is not changeable by me.

The Question
How can I bind 50 to the Equal property of the filter object without writing a custom model binder?


Solution

  • As a result, I was able to accomplish the goal by using the trick that Json Serializers have.

    Controller, Action & Model

    [ApiController]
    [Route("api/test")]
    public class TestController : Controller
    {
        [HttpGet]
        public bool Get([FromQuery] Filter filter)
        {
            filter = Request.Query.ExtractFilter();
            return true;
        }
    }
    
    public class Filter
    {
        public object Equal { get; set; }
    }
    

    The Extension Method

    public static class QueryCollectionExtensions
    {
        public static Filter ExtractFilter(
            this IEnumerable<KeyValuePair<string, StringValues>> queryCollection)
        {
            Filter result = new();
    
            if (!queryCollection.TryGetByKey("filter", out StringValues filter))
            {
                return result;
            }
    
            if (!filter.Any())
            {
                return result;
            }
    
            result = JsonConvert.DeserializeObject<Filter>(filter);
    
            return result;
        }
    
        public static bool TryGetByKey(
            this IEnumerable<KeyValuePair<string, StringValues>> queryCollection,
            string key, out StringValues values)
        {
            values = string.Empty;
    
            KeyValuePair<string, StringValues> keyValuePair = queryCollection
                .FirstOrDefault((KeyValuePair<string, StringValues> x) => x.Key == key);
    
            if (keyValuePair.Equals(default(KeyValuePair<string, StringValues>)))
            {
                return false;
            }
    
            values = keyValuePair.Value;
    
            return true;
        }
    }
    

    Request URLs

    https://localhost:7134/api/test?filter={"Equal":50}
    https://localhost:7134/api/test?filter={"Equal":"abc"}