Skip to content

NSwag Studio

A quick way to add API connectivity to an application is by using NSwagStudio to automatically generate the basic scaffolding.

This is a Windows application that can generates API client code from an OpenAPI specification such as those generated by Swagger.

Creating the Client Code

Start the API as NSwagStudio will need to read the Swagger information. Then, (assuming the API is running on the port 7256) we need to do the following:

  1. With the API running, paste the URL (https://localhost:7256/swagger/v1/swagger.json) into the Specification URL field and click the Create local Copy button.

Configure the generated output

Below are all items that should be checked, and a couple that are checked by default but should be un-cheked. Other values that are not checkboxes are listed with the required setting:

  1. In the "Output" section, select "CSharp Client" as the output type.
  2. Configure any additional settings as needed, such as namespace and class name, for this example JobSearch.MVC.Services.Base and:
    1. Generate exception classes
    2. Generate Client classes
    3. Operation Generation Mode = Multiple Operation IDs (comma separated)
    4. Class Name = {controller}client
    5. Client class access modifier = public
    6. Use base URL for the request = unticked
    7. Inject HttpClient via constructor (lifecycle managed by the caller)
    8. Generate interfaces for Client classes
    9. Http Client Type = System.Net.Http.HttpClient
    10. DateTime format for method parameters = s
    11. Date format for method parameters = yyyy-MM-dd
    12. Wrap DTO exceptions in a SwaggerException instance
    13. Generic Array Type (Parameter Types and Response Types) = System.Collections.Generic.IEnumerable
    14. Generic Dictionary Type (Parameter Types and Response Types) = System.Collections.Generic.IDictionary
    15. Generate DTO Types (e.g. Request and Response Classes)
    16. DTO class/emun modifier = public
    17. Generate default values for properties
    18. Generate data annotation attributes
    19. Inline named tuples
    20. Class Style = poco
    21. JSON Library = System.TextJson
    22. JSON Library Version = 10.0 (for .Net 10)
    23. Required properties must be defined in JSON
    24. JSON Polymorphic Serialisation Style = System.TextJson
    25. Required properties must be defined in JSON
    26. Read Accessor of properties (set | init) = set
    27. Primitive Types
      1. Any Type = object
      2. Date Type = System.DateTimeOffset
      3. Date Time Type = System.DateTimeOffset
      4. Time Type = System.TimeSpan
      5. Time Span Type = System.TimeSpan
      6. Generic Array Type = System.Collections.Generic.ICollection
      7. Generic Array Instance Type (empty = ArrayType) = System.Collections.ObjectModel.Collection
      8. Generic Dictionary Type = System.Collections.Generic.IDictionary
      9. Generic Dictionary Instance Type (empty = DictionaryType) = System.Collections.Generic.Dictionary
      10. Generic Array Base Type = System.Collections.ObjectModel.Collection
      11. Generic Dictionary Base Type = System.Collections.Generic.Dictionary
      12. New Line Behaviour = Auto
  3. Set Output file path (empty = no file output) (at the bottom of the tab) to a sub folder of your project called Services\Base with the name ServiceClient.cs, e.g. [Path]\JobSearch.MVC\Services\Base\ServiceClient.cs.1.
  4. Optionally save this configuration to the project root (or a resources folder)
  5. Optional: Click "Generate Outputs" to generate the client code. Inspect this if required
  6. Click the "Generate Files" button to create the file.

The generated API wrapper client file should now appear in the solution explorer and is ready to add to the project. We can now add a few extensions:

Extend the output

Here we can now add a new file IClient to hold a partial interface to extend the one that has just been generated.

Add this to the Services\Base folder alongside the ServiceClient.cs class. This will hold our HttpClient instance

public partial interface IClient
{
    public HttpClient HttpClient { get;  }
}

And alongside this add a new file Client to hold a partial class to extend the generated ServiceClient class:

public partial class Client
{
    public HttpClient HttpClient
    {
        get
        {
               return _httpClient;
        }
    }
}

This will allow us to inject an HttpClient instance when we register the client in the DI container. We can add the code Program.cs to register these services now:

Firstly add a scoped instance of HttpClient to allow this client code to locate the backend API. The second registration is IClient to Client, so anywhere I need to access the API we inject IClient. We previously modified Client to contain a reference to HttpClient:

// Add services to the container.
builder.Services.AddScoped(sp => new HttpClient
{
    BaseAddress = new Uri(builder.Configuration["ApiBaseAddress"] 
                ?? throw new InvalidOperationException("ApiBaseAddress configuration is missing."))
});

builder.Services.AddScoped<IClient, Client>();

We can add the base address for the API in the appsettings.Development.json file:

{
  ...
  "ApiBaseAddress": "https://localhost:7256/",
  "AllowedHosts": "*"
}

Thoughts

NSwagStudio is a great way of getting something up and running quickly, including creation of DTOs, etc. but will need to be re-run every time the API is modified.

Also, as with any tool, you will need to verify the generated code is suitable and correct.

It feels to me like this should be used when crating quick PoC projects or personal tools, but for production level code possibly only used initially when creating the codebase, then refactored into properly structured SOLID classes according to a better project structure.