Search code examples
c#asp.net-core-webapiopenapiasp.net-apicontroller

Nullable responses in an ApiController


I'm creating an ASP.Net Core server (with a matching .Net Core client) and I'd some of the methods to return null values. Unfortunately the Swagger schema doesn't seem to reflect this, and the methods are lacking the "nullable": true attribute.

API method example:

[ApiController]
public class DataController : ControllerBase
{
  public DateTime? GetSomeDateValue(string key)
  {
     DateTime? result = GrabTheResultFromTheDatabase(key); //<- if the key doesn't exist, this can be null and this is expected
     return result;
  }
}

For reference, I'm building the client using the following .csproj definition:

<OpenApiReference Include="..\Backend\BackendService.json" CodeGenerator="NSwagCSharp" Link="OpenAPIs\BackendService.json">
   <Options>/GenerateClientInterfaces:true /AdditionalNamespaceUsages:Base.Entities /GenerateDtoTypes:false</Options>
</OpenApiReference>

How should I set up the controller / NSwagCSharp so the client can handle nullable results?


Solution

  • Turns out Swashbuckle.AspNetCore currently has issues dealing with nullable primitives.

    Using DotSwashbuckle.AspNetCore turned out to be a better approach (at least until the nullability issues are fixed in Swashbuckle.AspNetCore).

    Besides that I had to mark my controller method as capable of returning nullable types for the 204 status code (aka "no content"), otherwise the generated client-side code treats 204 as an exception.

    [HttpGet("[action]")]
    [ProducesResponseType<DateTime?>(StatusCodes.Status200OK)]
    [ProducesResponseType<DateTime?>(StatusCodes.Status204NoContent)]
    public DateTime? GetSomeDateValue(string key) => MyMagicMethodThatReturnsValue(key);
    
    

    It's also possible to disable ASP.NET Core 204 usage which means the ProducesResponseType attributes are no longer required.

    services.AddControllers(opt =>  // or AddMvc()
    {
        // remove formatter that turns nulls into 204 - No Content responses
        opt.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
    })