1

Got a mismatch somewhere between my View and Controller which is causing the latter to receive a complex object, full of null values.

[HttpGet("find")]
[ProducesResponseType(typeof(PagableResults<UserDetails>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[SwaggerOperation("FindUsers")]
public async Task<IActionResult> FindUsers([FromQuery]FindUsersSearchFilter searchFilters)

And the searchFilters object is defined like this:

public class FindUsersSearchFilter
{
    public int? Page { get; set; }

    public string Username { get; set; }

    public string Firstname { get; set; }

    public string Surname { get; set; }
}

The View is sending the data in a querystring (because it's a get method) like so:

/find?SearchFilters.Page=1&SearchFilters.Firstname=foo&SearchFilters.Surname=bar&SearchFilters.Username=

However, if you debug the controller action the breakpoint is hit but the FindUsersSearchFilter received by the method has a null value for every property.

Things I've tried:

  • Binding(Prefix="SearchFilters") on the controller action.
  • Binding("Page,Firstname,Surname,Username") on the controller action
  • Manually changing the URL to remove the prefix and change the capitalisation
  • Removing [FromQuery]

At a loss as to where to go next. Any suggestions as to what I've got wrong?

3
  • This kind of a request is usually easier as a POST rather than a GET. Commented Nov 5, 2019 at 14:58
  • @nurdyguy Yeah, but this is very definitely a GET as it's a search function. The complex object is a convenient way to pass multiple parameters. Commented Nov 5, 2019 at 15:06
  • @BobTway I understand what you mean. This can certainly be done either way, just easier and cleaner as a POST. Commented Nov 5, 2019 at 15:08

1 Answer 1

2

The request is wrong. It should be:

/find?Page=1&Firstname=foo&Surname=bar&Username=

When you prefix all your properties with SearchFilters the binding engine is most likely looking for a nested property like searchFilters.SearchFilters.FirstName.

So removing the prefix should make it work.

If you really need to use that syntax in the query; then create another class like this:

public class SearchFilterContainer
{
    public FindUsersSearchFilter SearchFilters { get; set; } = new FindUsersSearchFilter();
}

And pass that in the action as the parameter instead like this:

[HttpGet("find")]
[ProducesResponseType(typeof(PagableResults<UserDetails>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[SwaggerOperation("FindUsers")]
public async Task<IActionResult> FindUsers([FromQuery]SearchFilterContainer searchFilters)

Then inside your controller you can access the model like this searchFilters.SearchFilters.FirstName

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

2 Comments

I am pretty sure it works. As I created a demo app and it works just fine... As for "fails fluid validation" I am not sure what that means. As it is not required by HTTP nor by ASP.NET Core.... If you really need to have that unnecessary prefix then you will have to nest your class inside another class
There I gave you a solution that keeps your prefix.

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.