1

Using ASP.NET Core MVC, is there a way to return BadRequest for a HTTP request that includes a query parameter that is not used by the controller?

I'm not trying to return an error on some specific query parameters being present, I want to reject all requests that include query parameters that the server doesn't parse to something meaningful.

So, in other words, it's OK for valid query parameters to be absent, but not OK for invalid/unrecognized query parameters to be present.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
runeks
  • 1,745
  • 2
  • 17
  • 26
  • Why would you want to do this (i.e. the normal web way is to just ignore the extra parameters)? https://stackoverflow.com/a/41577487/34092 may be of interest. – mjwills Apr 01 '19 at 09:02
  • Can you provide a sample case? – Kamran Poladov Apr 01 '19 at 09:03
  • You could use Respons.QueryString, break it down, create a white list of valid parameters, and so on. But that would seem like a fool's errand. Just ignore them. – LongChalk Apr 01 '19 at 09:14
  • 3
    I want this behaviour for the same reasons many command line programs exit with an error if you give it an unrecognized parameter. One advantage is that the user (e.g. a script) is notified that a command was unrecognized (deprecated/removed/changed), thereby signalling that it should be updated, rather than producing incorrect output (because the command has no effect). If a frontend sends query parameters that the server doesn't recognize, it means the frontend need to be updated, and the frontend tests that do this should fail with a 400 status code instead of passing. – runeks Apr 03 '19 at 16:31

1 Answers1

4

You could use action filter to get both the action parameters and request query string queryParameters.Then make a judgement whether the query parameters are all used in action.

public override void OnActionExecuting(ActionExecutingContext context)
    {

        var parameters = context.ActionDescriptor.Parameters;
        var queryParameters = context.HttpContext.Request.Query;

        if (queryParameters.Select(kvp => kvp.Key).All(queryParameter => parameters.Any(p => p.Name == queryParameter)))
        {
            base.OnActionExecuting(context);
        }
        else
        {
            context.Result = new BadRequestObjectResult("Querystring does not match");
        }

    }

In controller:

[TypeFilter(typeof(TestQueryActionFilter))]
public void MyAction(int id, string name)
Ryan
  • 19,118
  • 10
  • 37
  • 53
  • this won't work if you have a "request object" that has the bindings ("FromQuery" etc). hoping to find a solution for that convention. – karczilla Sep 27 '22 at 15:57