bryken
bryken

Reputation: 167

ASP.NET Core 2.1 [FromQuery] not getting param

I'm trying to get a param for my WebAPI from a query param using [FromQuery] using ASP.NET Core 2.1. For the the life of me I cannot figure out what I'm doing wrong.

The particular action looks like this:

[Route("api/[controller]/[action]")]
public class AuthController : Controller
{
    [HttpGet]
    [Authorize(Roles = "admin")]
    public async Task<IActionResult> GenerateCode([FromQuery]string email)
    {
        if (String.IsNullOrEmpty(email))
            return new BadRequestObjectResult(new ApiBadRequestResponse(new string[] { "Email is empty." }));

        var result = await _mediator.Send(new CreateAccessCode.Command
        {
            Email = email
        });

        if (result.Succeeded)
            return new OkObjectResult(new ApiOkResponse(result.Data));

        return new BadRequestObjectResult(new ApiBadRequestResponse(result.Errors));
    }
}

email is always null and I've put a breakpoint in the function so I know its getting called.

The request I'm sending is this:

{{url}}/api/auth/generatecode?email=test

If I create a new project from scratch, [FromQuery] seems to work, I have no idea what I'm doing differently. The action is getting called, but is always return BadResponse due to the first line...

My startup.cs function looks like this:

services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
            .AddMvcOptions(options =>
            {
                options.Filters.Add(new ActionValidationFilter());
            })
            .AddFluentValidation()
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                new CamelCasePropertyNamesContractResolver();
            })
            .AddSessionStateTempDataProvider();

I'm completely lost. This is the first action I have in my WebAPI that is looking for a query param. All other actions are using FromBody and work fine.

Upvotes: 1

Views: 7706

Answers (2)

A little late answer but may be helpful for others

Option 4

You can explicitly name the querystring parameter name within the [FromQuery] attribute

[HttpGet]
[Authorize(Roles = "admin")]
public async Task<IActionResult> GenerateCode([FromQuery(Name="email")] string email)
{

}

Upvotes: 2

p3tch
p3tch

Reputation: 1495

Option 1)
Try changing your [HttpGet] attribute to

[HttpGet("GenerateCode/{email}]

You will need to remove /[action] from your controller's Route attribute if doing this, so it'd just be

[Route("api/[controller]")]

Option 2)
Alternatively, in Startup.cs change app.UseMvc(); to

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "api/{controller=Home}/{action=Index}/{id?}");
});

And remove [Route("api/[controller]/[action]")] from the controller attributes and make sure you don't have the [ApiController] attribute either

This solution will change your entire project's routing, so you'll have to do the same for all your other API controllers

Option 3)
A third solution would be to change [Route("api/[controller]/[action]")] to

[Route("api/[controller]/[action]/{id?}")]

I have tested all 3 solutions and they all with with the URL {{url}}/api/ControllerName/ActionName?email=test

Upvotes: 4

Related Questions