Generating client code with NSwag for Enumeration class
This is my fourth post in the Series: Enumeration classes – DDD and beyond. If you are new to the Enumeration class, I suggest going through my previous posts.
Ankit Vijay
This is my fourth post in the Series: Enumeration classes – DDD and beyond. If you are new to the Enumeration class, I suggest going through my previous posts.
- Part 1: Introduction to Enumeration Classes
- Part 2: Enumeration class and JSON Serialization
- Part 3: Enumeration class as query string parameter
- Part 4: Generating client code with NSwag for Enumeration class (this post)
- Part 5: Implementing Inheritance with Enumeration class
NUGET AND SOURCE CODE
The Enumeration class and other dependent classes are available as the NuGet packages. You can find the source code for the series at this GitHub link.
WHAT IS NSWAG?
From the NSwag GitHub documentation:
NSwag is a Swagger/OpenAPI 2.0 and 3.0 toolchain for .NET, .NET Core, Web API, ASP.NET Core, TypeScript (jQuery, AngularJS, Angular 2+, Aurelia, KnockoutJS and more) and other platforms, written in C#. The OpenAPI/Swagger specification uses JSON and JSON Schema to describe a RESTful web API. The NSwag project provides tools to generate OpenAPI specifications from existing ASP.NET Web API controllers and client code from these OpenAPI specifications.
If you are new to NSwag, Microsoft documentation here will come handy. Also, please have a look at youtube video created by my former colleague and friend,Rahul, where he has described how to use NSwag and NSwagStudio in detail.
The sample API
Let us go back to our old PaymentType Enumeration class.
{
public static readonly PaymentType DebitCard = new DebitCardType();
public static readonly PaymentType CreditCard = new CreditCardType();
public abstract string Code { get; }
private PaymentType(int value, string name = null) : base(value, name)
{
}
private class DebitCardType : PaymentType
{
public DebitCardType() : base(0, "DebitCard")
{
}
public override string Code => "DC";
}
private class CreditCardType : PaymentType
{
public CreditCardType() : base(1, "CreditCard")
{
}
public override string Code => "CC";
}
}
Consider a simple HttpPost endpoint, which accepts a Transaction object in the body.
{
public PaymentType PaymentType { get; set; }
public decimal Amount { get; set; }
} by GitHub[ApiController][Route("[controller]")]public class TransactionController : ControllerBase{ private static readonly List<Transaction> s_Transactions = new List<Transaction>(); [HttpPost] [Route("create")] public IActionResult CreateTransaction(Transaction transaction) { s_Transactions.Add(transaction); return Ok(); }}view raw02_TransactionController.cs hosted with
[Route("[controller]")]
public class TransactionController : ControllerBase
{
private static readonly List<Transaction> s_Transactions = new List<Transaction>();
[HttpPost]
[Route("create")]
public IActionResult CreateTransaction(Transaction transaction)
{
s_Transactions.Add(transaction);
return Ok();
}
}
As you can see in the above code, Transaction DTO has a property PaymentType..
NSwag does not support System.Text.Json at the time of this writing. As a result, we need to fallback to our trustworthy old friend NewtonsoftJson. We will configure the API to use NewtonsoftJson and add EnumerationJsonConverter, as explained in Part 2 of this series.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.Add(new EnumerationJsonConverter());
});
}
Testing Api on Postman
The Postman request accepts the PaymentType as both as name and value, just like a normal EnumType.


Adding Swagger to Api
To generate client code from NSwag, let us first add Swagger support to our API.
// Import Swashbuckle.AspNetCore.SwaggerUI
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.Add(new EnumerationJsonConverter());
});
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo {Title = "Enumeration NSwagger Sample", Version = "v1"});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("v1/swagger.json", "Enumeration NSwagger Sample");
});
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
The swagger page of our application would look similar to below.

Notice that the PaymentType schema is as a complex object instead of an Enum type.
To fix this, we need to extend our OpenAPI specification by creating a new SchemaFilter that renders an Enumeration class as an Enum type in Swagger.
public class EnumerationToEnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (!context.Type.IsSubclassOf(typeof(Enumeration)))
{
return;
}
var fields = context.Type.GetFields(BindingFlags.Static | BindingFlags.Public);
schema.Enum = fields.Select(field => new OpenApiString(field.Name)).Cast<IOpenApiAny>().ToList();
schema.Type = "string";
schema.Properties = null;
schema.AllOf = null;
}
}
Next, we need to add EnumerationToEnumSchemaFilter to the SwaggerGen options in Startup.cs.
{
options.SwaggerDoc("v1", new OpenApiInfo {Title = "Enumeration NSwagger Sample", Version = "v1"});
options.SchemaFilter<EnumerationToEnumSchemaFilter>();
});
If we run our application now, the PaymentType schema is an Enum type.

Generating client code from NSwagger Studio
Now, we let us generate the client using NSwagger studio. We need to specify the path to swagger.json and click Generate Outputs. Note the schema for PaymentType in OpenAPI specification. It is of an Enum type just like on the Swagger page.

The generated C# client also creates an Enum type.

WRAPPING UP
This post explains how we can render an Enumeration class as an Enum type in our client code generated through NSwag.
I hope this series has given a complete picture of how we can replace Enumeration class at various parts of our system, including but not limited to web Api, persistence, and Domain-Driven-Design.
Upvote
Ankit Vijay
Hi... I’m Ankit Vijay. I hold around 14 years of experience in application development & consulting. I’m a Dotnet Foundation member. I have worked in various roles ranging from Individual Contributor, DevOps, Solution Architect, Consultant, and Dev Lead depending on the nature of the project. I am passionate about technology and write about the topics I love. If you like my blogs, you can follow me on Twitter @ https://twitter.com/vijayankit or GitHub @ https://github.com/ankitvijay

Related Articles