vaclavnovotny / NSwag.Examples

NSwag processor to programmatically define strongly-typed examples for response and request parameters.
MIT License
13 stars 11 forks source link

NullReferenceException in 1.0.14 #25

Closed rootix closed 4 months ago

rootix commented 5 months ago

I upgraded from 1.0.12 to 1.0.14 and now the swagger generation fails with an NullReferenceException in the new RequestExampleProcessor.SetRequestExamples.

The issue in my case seems to be, that context.OperationDescription.Operation.Parameters contains an OpenApiParameter, but context.Parameters does not. This leads to an empty KeyValuePair with Value [,] for the parameter variable, as the default value of a KeyValuePair (the result of the SingleOrDefault) is not null as the HasValue call checks for: https://dotnetfiddle.net/bqq9gQ

vaclavnovotny commented 5 months ago

Hi @rootix,

v1.0.14 does work in my projects, so maybe it is related to configuration or NuGet version mismatch with Swagger or NSwag. Can you please send a sample of your code?

Thanks!

rootix commented 4 months ago

Sorry for the late reply.

I figured it out now, my error. I spent almost an hour trying to create a minimal reproduction case but failed to do so.

Then I tried an exclusion process in my project to figure out why it worked in my reproduction case.

It turned out, that the problem was a endpoint specific request example where I didn't define the parameter name. This worked in 1.0.12, but failed in 1.0.14. The now working signature looks like:

[ProducesResponseType(typeof(SituationEntryResponseDto), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorDto), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
[ProducesResponseType(typeof(ErrorDto), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ErrorDto), StatusCodes.Status500InternalServerError)]
[EndpointSpecificExample(typeof(MinimalSituationEntryCreateDtoExample), typeof(ComplexSituationEntryCreateDtoExample), ParameterName = "request", ExampleType = ExampleType.Request)]
[EndpointSpecificExample(typeof(BusinessExceptionExample), ExampleType = ExampleType.Response, ResponseStatusCode = StatusCodes.Status400BadRequest)]
[EndpointSpecificExample(typeof(BusinessExceptionExample), ExampleType = ExampleType.Response, ResponseStatusCode = StatusCodes.Status404NotFound)]
[EndpointSpecificExample(typeof(EntityValidationExceptionExample), ExampleType = ExampleType.Response, ResponseStatusCode = StatusCodes.Status400BadRequest)]
[EndpointSpecificExample(typeof(ErrorDtoExample500), ExampleType = ExampleType.Response, ResponseStatusCode = StatusCodes.Status500InternalServerError)]
public async Task<SituationEntryResponseDto> UpdateAsync(string key, SituationEntryCreateDto request) 
{
    ....
}

I missed ParameterName = "request" in the first EndpointSpecificExample.

I still think your null handling in the mentioned method is not bullet proof, but if the definition is correct, it works :)

For me, this problem is solved. Thanks for trying to help me and thanks for the library!