简体   繁体   中英

.Net Core API Endpoint not allowing QueryString parameters

Very possible this is a duplicate, but I've looked and can't find an answer. The first answer here looked promising: Query string not working while using attribute routing But I tried that and it didn't work.

[HttpGet, Route("api/machine/byid/{id=id}/{pageNumber=pageNumber}/{pageSize=pageSize}/{fields=fields}")]
public string ById(int id, int pageNumber, int pageSize, string fields)
    // code removed
}

This works:

https://localhost:44303/api/machine/byid/1/2/3/a,b,c

This does not:

https://localhost:44303/api/machine/byid?id=1&pageNumber=2&pageSize=3&fields=a,b,c

The second url returns:

{"type":"https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1","title":"One or more validation errors occurred.","status":400,"traceId":"|bf12950b-472923d3a24062d1.","errors":{"id":["The value 'id' is not valid."],"pageSize":["The value 'pageSize' is not valid."],"pageNumber":["The value 'pageNumber' is not valid."]}}

You would need two routes:

[HttpGet("api/machine/byid")]
public string ById(
    [FromQuery("id")] int id, 
    [FromQuery("pageNumber")] int pageNumber, 
    [FromQuery("pageSize")] int pageSize, 
    [FromQuery("fields")] string fields)
{
}

Follow this link for more informations

The example you provided demonstrates route parameters. There is a distinct difference between route parameters and query parameters.

To accomplish query parameters, you can the [FromQuery] attribute to your method parameters. This will allow for the query parameter example that you provided,

Example : https://localhost:5000/api/persons?firstName=bob&lastName=smith

You can also provide default values for these from within your method parameters. You can string multiple query parameters together in one action.

For route parameters, the parameters are provided via the route itself.

Example : https://localhost:5000/api/persons/23

These parameters are defined from within the [HttpGet("{id}")] attribute on your controller action. You can also constrain the parameter to a certain type, such as an int . This is achieved by adding a colon and specifying the type. Example [HttpGet("{id:int}")] . No further attributes are required to be added within your method parameters for route parameters.

Of course you must also declare these parameters in your method parameters, for both types.

// "/api/persons/23"
[HttpGet("{id}")]
public async Task<IActionResult> GetPersonById(int id)
{
    // Code ...
}

// "/api/persons?firstName=bob&lastName=smith"
[HttpGet]
public async Task<IActionResult> GetPersonByName([FromQuery] string firstName = null, [FromQuery] string lastName = null)
{
    // Code here... both firstName and lastName can now be optional or only one provided
}

The answer by sturcotte06 was close, but was not 100% Core compliant. This works:

[HttpGet, Route("api/machine/byid/{id=id}/{pageNumber=pageNumber}/{pageSize=pageSize}/{fields=fields}")]
public string ById([FromQuery] int id, [FromQuery] int pageNumber, [FromQuery] int pageSize, [FromQuery] string fields)
{
    // code removed
}

I am passing through quite a similar challenge to the one reported here, but Casey's suggestion hasn't worked for me.

    [HttpGet, Route("api/indicators/getindicatorsvalues/{companyId=companyId}/{pathToFile=pathToFile}")]
    [ProducesResponseType(typeof(ComputedIndicatorVM), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetIndicatorsValues([FromQuery] Guid companyId, [FromQuery] string pathToFile)
    {
       //code goes here
    }

    [HttpGet("{id}")]
    [ProducesResponseType(typeof(IndicatorDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetByIdAsync(Guid id)
    {
        //some more code goes here
    }

Calling the 1st endpoint:

URL: https://localhost:5001/api/indicators/GetIndicatorsValues?companyId=cTest&pathToFile=ptfTest

Result: {"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1","title":"One or more validation errors occurred.","status":400,"traceId":"|6c8dcccd-412c0e1f0b9eb222.","errors":{"id":["The value 'GetIndicatorsValues' is not valid."]}}

Calling the 2nd endpoint works just fine:

URL: https://localhost:5001/api/indicators/DFAF6EAE-AB4B-4563-B37E-57DEF730A1D7

It seems by the response of the first endpoint that it is considering GetIndicatorsValues as a param for the second endpoint? Or am I missing something else?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM