Reputation: 4077
I'm using Swagger and SwaggerUi (via the Swashbuckle.AspNetCore Nuget package) for my WebAPI project.
The problem that I am having is that the UI is not forming the request properly for the Try It Out feature. For example, my API has a nullable long
in the method signature at the server. That parameter is called modifiedSince
.
When I click execute, without a value in the modifiedSince text input, the following Url is hit https://localhost:44348/v1/Complication/%7BmodifiedSince%7D
It is picking up the Placeholder text and including that in the URL (inside html-encoded curly braces).
On another endpoint, I have two parameters and the URL is meant to look like this: https://localhost:44348/v1/Logbook/37193/Entry/2121321
But when I click the Try It Out button, SwaggerUi sends https://localhost:44348/v1/Logbook/37193/Entry/%7BentryId%7D?entryId=2121321
and as a result, a null value comes into my server's method for the entryId parameter.
Again, the placeholder of the relevant text input is being added to the url.
I upgraded from 2.5.0 to 3.0.0 in a bid to fix the issue. But it is still occurring.
An example of a Controller action which the Swagger API is hitting is:
/// <summary>
/// Logbooks of user.
/// </summary>
/// <param name="modifiedSince"></param>
/// <returns></returns>
/// <response code="200">Logbooks assigned to the user</response>
/// <response code="204">No logbooks assigned to the user</response>
/// <response code="400">Error state. Error message included in payload.</response>
/// <response code="403">Authentication required.</response>
[HttpGet]
[Route("[action]/{modifiedSince?}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(ApiResponse<IEnumerable<LogbookDto>>), 200)]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ApiResponse<string>), 400)]
[ProducesResponseType(typeof(ApiResponse<string>), 403)]
public async Task<IActionResult> Logbook(long? modifiedSince)
{
var logbookDtos = default(IEnumerable<LogbookDto>);
if (await AuthorizeAsync(User, IdentityConstants.PolicyNames.RacsUser) &&
await Execute(async () => logbookDtos = await _mediator.Send(
new GetLogbooksQuery
{
UserId = _currentUser.UserId
//LastConfigChange = NULL
}))
)
{
if (logbookDtos.Any())
return Ok(new ApiResponse<IEnumerable<LogbookDto>> { Data = logbookDtos, Outcome = new OperationOutcome { Error = false, Message = "" } });
return NoContent();
}
return ErrorResponse(new ApiResponse<string> { Data = Errors, Outcome = new OperationOutcome { Error = true, Message = "" } });
}
Here is a pic from Chrome dev tools to depict what is happening:
Does anyone know what's going on? Have I missed a config somewhere?
Upvotes: 4
Views: 2878
Reputation: 17594
Expanding from the comments:
If it works when you remove the nullable that points to a bug in swashbuckle, you should report it:
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/new
The only thing that I'm a bit fuzzy is that from a JSON Schema perspective a nullable
does not necessarily imply not required
...
You can have field required and allow null as a value
There are some things that C# does that do not directly translate to something in swagger, my recommendation remove the nullable, maybe instead you can use a default value, something like:
public async Task<IActionResult> Logbook(long modifiedSince = -1)
And handle the default case in code
Upvotes: 2