Milad Rashidi
Milad Rashidi

Reputation: 1376

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?

Upvotes: 3

Views: 4917

Answers (3)

Milad Rashidi
Milad Rashidi

Reputation: 1376

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"}

Upvotes: 1

Dang-gun Roleeyas
Dang-gun Roleeyas

Reputation: 145

How about passing it as another parameter?

e.g. :

    [HttpGet]
    public bool Get([FromQuery] int Equal, [FromQuery] Filter filter)
    {
        if (null == filter)
        {
            filter = new Filter();
        }

        filter.Equal = Equal;

        return true;
    }

Upvotes: 0

James Curran
James Curran

Reputation: 103535

I believe the syntax you want is :

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

Upvotes: 0

Related Questions