DEV Community

Timothy McGrath
Timothy McGrath

Posted on

TIL: Generate Required & Optional Parameters with NSwag

I use NSwag to generate a Swagger page for each of our .NET Core services, and I also use NSwag to generate a .NET Standard proxy client for other services to use when talking to that service.

However, sometimes the signature of the generated client is not accurate in describing which parameters are required and which parameters cannot be null. This is how to fix that.

This is the example endpoint. userId and age are required and not nullable. faveNumber is optional and nullable.

    [HttpGet()]
    public ActionResult GetValues(
        FromHeader] string userId,
        [FromQuery] int age,
        [FromQuery] int? faveNumber)
    {
        return Ok();
    }
Enter fullscreen mode Exit fullscreen mode

I want the generated client code to create the following method signature:

GetValues(string userId, int age, int? faveNumber = null)
Enter fullscreen mode Exit fullscreen mode

Fix the swagger.json

First, I need to properly describe the endpoint parameters on the endpoint, so that the generated swagger.json describes the parameters correctly:

    "parameters": [
      {
        "name": "userId",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string"
        },
        "x-position": 1
      },
      {
        "name": "age",
        "in": "query",
        "required": true,
        "schema": {
          "type": "integer",
          "format": "int32"
        },
        "x-position": 2
      },
      {
        "name": "faveNumber",
        "in": "query",
        "schema": {
          "type": "integer",
          "format": "int32",
          "nullable": true
        },
        "x-position": 3
      }
    ],
Enter fullscreen mode Exit fullscreen mode

The required and nullable fields are the key to getting a properly generated client. Use Nullable (?) to denote parameters which are nullable, and use BindRequired to denote parameters which must be included:

    [HttpGet()]
    public ActionResult GetValues(
        [BindRequired][FromHeader] string userId,
        [BindRequired][FromQuery] int age,
        [FromQuery] int? faveNumber)
    {
        return Ok();
    }
}
Enter fullscreen mode Exit fullscreen mode

In Startup.cs set the default null reference to NotNull, which will prevent the required fields from accepting null as a value.

    services.AddOpenApiDocument(settings =>
{
settings.DefaultReferenceTypeNullHandling = NJsonSchema.Generation.ReferenceTypeNullHandling.NotNull;
});
Enter fullscreen mode Exit fullscreen mode




Generate the Client

Now that we have a proper swagger.json, use that to build the NSwag client.

Make sure that the "Generate optional parameters" setting is selected. I end up with a generated client with the following method:

    public async System.Threading.Tasks.Task<FileResponse> Values_GetValuesAsync(
string userId,
int age,
int? faveNumber = null))
Enter fullscreen mode Exit fullscreen mode




Summary

When generating an NSwag client, don't just play with the Client generation settings, make sure that the swagger.json that is being generated properly represents the endpoints you've built in code.

Building the correct swagger.json is key to building a correct client.

Top comments (0)