0

How to handle unknown parameters in ASP.NET Core? When I use [FromQuery] it just ignores the unknown parameters, but ideally it should return 400 if the parameter is unknown so the caller knows it needs to fix the parameters?

Example: GetRecords tries to use any StartDate or EndDate from query string, use default value if they are not specified.

But if a query like ?StartTime=2021/2/15&EndTime=2021/2/16, the code actually will return all records from DB as it treats like no parameters passed. Ideally it should throw an error to let caller know the parameter names are invalid.

class RecordQuery 
{
    public RecordQuery()
    {
       StartDate = DateTime.MinValue;
       EndDateTime = DateTime.Now;
    }

    //...
}

class Controller
{
    public async Task<ActionResult<RecordsResult>> GetRecords([FromQuery] RecordQuery query)
    {
        // query db where date < query.EndDateTime && date > query.StartDateTime;
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jacky
  • 1
  • 1

2 Answers2

1

When I use [FromQuery] it just ignores the unknown parameters

Actually, this is the default behavior of the querystring parameters. But you could return an Invalid Request status, so that the client knows that what it's trying to do isn't valid.

To implement it, you can use the ActionFilter, get both the action parameters and request query string queryParameters and make a judgement. Codes like below:

public class QueryActionFilter<T> : IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        var model = context.ActionArguments.Values.OfType<T>().Single();
        var modelProperties = model.GetType().GetProperties();

        var queryParameters = context.HttpContext.Request.Query;

        if (!queryParameters.Select(q => q.Key).All(queryParameter => modelProperties.Any(p => p.Name == queryParameter)))
        {
            context.Result = new BadRequestObjectResult("Querystring does not match");
        }
        

    }
}

Then in controller

[TypeFilter(typeof(QueryActionFilter<RecordQuery>))]
public async Task<ActionResult<RecordsResult>> GetRecords([FromQuery] RecordQuery query)
{
    // query db where date < query.EndDateTime && date > query.StartDateTime;
}
mj1313
  • 7,930
  • 2
  • 12
  • 32
  • Hi @Jacky, if my reply is helpful, could you please [accept it as answer](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work), thanks! – mj1313 Feb 26 '21 at 07:22
0

You can see example https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-5.0&tabs=visual-studio#the-puttodoitem-method

if(StartDate == null){
    return BadRequest();
}

Let's do the same thing with another input parameter(s) (query conditions)

If you want validate input parameter(s), use [Required] for model of [FromQuery], see https://stackoverflow.com/a/19279419/3728901 . In your case, it is model RecordQuery .

Vy Do
  • 46,709
  • 59
  • 215
  • 313