Using NSwag to Generate Blazor Server Client for an ASP.NET Core 3.1 API

This week we are going to add a Blazor Server project that will utilize the contacts API we created a few weeks ago. This post is part of the revamp of the ASP.NET Core Basics repo that was kicked off when .NET Core 3.0 was released. For details on how the associated sample got to the current point in the application check out the following posts.

Swagger/OpenAPI with NSwag and ASP.NET Core 3
ASP.NET Core 3: Add Entity Framework Core to Existing Project
New Razor Pages Project Backed with an API
Using NSwag to Generate Angular Client for an ASP.NET Core 3 API
Using NSwag to Generate React Client for an ASP.NET Core 3 API

The sample code before any of the changes in this post can be found here.

Create the Blazor Server Project

Add a new directory for the Blazor Server project and then open a terminal set to that directory. The following command can be used to create a new Blazor Server project.

dotnet new blazorserver

Next, use the following command to add the new project to the solution file which is in the root of the repo. Your filenames and paths will vary of course.

dotnet sln ..\..\BasicsRefresh.sln add ContactsBlazorServerApp.csproj

Using NSwageStudio to Generate an API Client

NSwag provides multiple options for client generation including a CLI option, code, and a Windows application. This post is going to use the Windows application which is called NSwagStudio. Download and install NSwagStudio from here.

Next, make sure your API is running and get the URL of its OpenAPI/Swagger specification URL. For example, I am using a local instance of my API and the URL I need is https://localhost:5001/swagger/v1/swagger.json. If you are using the Swagger UI you can find a link to your swagger.json under the API title.

Now that we have the OpenAPI/Swager specification URL for the API switch over to NSwagStudio. The application will open with a new document ready to go. There are a few options we will need to set. First, we want to use the NetCore30 Runtime. Next, select the OpenAPI/Swagger Specification tab and enter your API’s specification URL in the Specification URL box.

In the Outputs section check the CSharp Client checkbox and then select the CSharp Client tab. For this example, we are taking the defaults for all of the options except for Namespace, which is set to ContactsApi, Generate interfaces for Client classes, which should be check, and Output file path, which is only needed if you use the Generate Files option. Click the Generate Files button and NSwagStudio will create a file that contains all the code needed to access the API described in the OpenAPI/Swager specification selected in the Input section.

The Generate Outputs button can be used if to populate the Output tab with the same code that the Generate Files process creates which provides a nice way to play with settings to and see the output without having to open another file.

Setting Up the Generated Client in the Blazor Server Project

In the sample project, create an APIs directory and dropped the ContactsApi.cs created with NSwagStudio there. The files generated with NSwagStudio are expecting JSON.NET to be present so the sample project will need a reference to the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package.

With the client-generated and in our local Apis directory in the Razor Pages project we can now work on getting it configured and registered for use in our new project. First, open the apppsetting.json file and add a setting for the URL of our API, which is the ContactsApi value in the following sample.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ContactsApi": "https://localhost:5001"
}

Now that the project has the configuration change and a reference to JSON.NET in the ConfigureServices function of the Startup class we need to tell the app to make JSON.NET available via dependency injection by using AddNewtonsoftJson as in the following example.

services.AddRazorPages()
        .AddNewtonsoftJson();

Also in the ConfigureServices function, we need to register our API client.

services.AddHttpClient<IContactsClient, 
                       ContactsClient>(client => 
         client.BaseAddress = new Uri(Configuration.GetSection("ContactsApi").Value));

Create the UI and Usage of the Generated Client

Now that all the setup work is done we can add the contact list UI which will show the usage of the API client. The following is the full code which for the sample is in a new ContactList.razor file in the Pages directory. The specific lines related to the API client are highlighted.

@page "/contactlist"

@using Apis
@inject IContactsClient ContactClient

<h1>Contact List</h1>

@if (_contacts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table className='table table-striped' aria-labelledby="tabelLabel">
        <thead>
            <tr>
                <th>Name</th>
                <th>Address</th>
                <th>City</th>
                <th>State</th>
                <th>Postal Code</th>
                <th>Phone</th>
                <th>Email</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contact in _contacts)
            {
                <tr>
                    <td>@contact.Name</td>
                    <td>@contact.Address</td>
                    <td>@contact.City</td>
                    <td>@contact.State</td>
                    <td>@contact.PostalCode</td>
                    <td>@contact.Phone</td>
                    <td>@contact.Email</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private ICollection<Contact> _contacts;

    protected override async Task OnInitializedAsync()
    {
        _contacts = await ContactClient.GetContactsAsync();
    }
}

Finally to add our new page to the navbar open the NavMenu.razor file found in the Shared directory. Add the following list item to the unordered list.

<li class="nav-item px-3">
    <NavLink class="nav-link" href="contactlist">
        <span class="oi oi-list" aria-hidden="true"></span> Contacts
    </NavLink>
</li>

Wrapping Up

As with the other posts I have been doing utilizing NSwag for client generation this process is pretty easy and simplifies API consumption.

The sample code in its final state can be found here.

Using NSwag to Generate React Client for an ASP.NET Core 3 API

This week we are going to add a React project that will utilize the contacts API we created a few weeks ago. This post is part of the revamp of the ASP.NET Core Basics repo that was kicked off when .NET Core 3.0 was released. For details on how the associated sample got to the current point in the application check out the following posts.

Swagger/OpenAPI with NSwag and ASP.NET Core 3
ASP.NET Core 3: Add Entity Framework Core to Existing Project
New Razor Pages Project Backed with an API
Using NSwag to Generate Angular Client for an ASP.NET Core 3 API

I realize that using an ASP.NET Core backed React project for this sample is overkill and a raw React application would have been all that is needed. I chose to use the ASP.NET Core template as a base for all the projects in this series to be consistent. After the initial application creation, you can think of this example as setting up access to a secondary API in addition to the application’s main API if that helps or the generated client on the React side could be used to wrap the API generated by the template.

The sample code before any of the changes in this post can be found here.

Create the React Project

Add a new directory for the React project and then open a terminal set to that directory. The following command can be used to create a new React project. The target framework isn’t required, but I have a preview of .NET Core 3.1 installed and I wanted to make sure this project is targeting .NET Core 3.0.

dotnet new react -f netcoreapp3.0

Next, use the following command to add the new project to the solution file which is in the root of the repo. Your filenames and paths will vary if you are not using the sample code of course.

dotnet sln ..\..\BasicsRefresh.sln add ContactsReact.csproj

Use NSwagStudio to Generate React Client

NSwag provides multiple options for client generation including a CLI, code, and a Windows application. This post is going to use the Windows application which is called NSwagStudio. Download and install NSwagStudio from here.

Next, make sure your API is running and get the URL of its OpenAPI/Swagger specification URL. For example, I am using a local instance of my API and the URL I need is https://localhost:5001/swagger/v1/swagger.json. If you are using the Swagger UI you can find a link to your swagger.json under the API title.

Now that we have the OpenAPI/Swager specification URL for the API switch over to NSwagStudio. The application will open with a new document ready to go. There are a few options we will need to set. First, select the OpenAPI/Swagger Specification tab and enter your API’s specification URL in the Specification URL box.

In the Outputs section check the TypeScript Client checkbox and then select the TypeScript Client tab. There are a lot of options to play with, but I highlighted the options that were important for this sample. First, make sure Module name and Namespace are both empty. I’m sure there is a way to get the client working with a module or namespace, but I didn’t have any luck.   For Template, we just need a Fetch based client. The final option that needs to be set is the Output file path and this is the location you want the generated file to be. I output to the React project directory under ClientApp\src\app\components\contactApi.ts. After all the options are set click Generate Files.

Create UI and Use Generated Client

Once the above is done once you switch back to Visual Studio you should see the following prompt to add the Microsoft.TypeScript.MSBuild NuGet package. The React template doesn’t use TypeScript and NSwag doesn’t have an option to generate a plain JavaScript client so adding this package will allow the build process to take our TypeScript client and convert it to JavaScript. There is an open issue requesting a JavaScript generator.

The sample API is for contact management so the UI we are going to build is to display a contact list. In the ClientApp/src/component directory add a new file named ContactList.js with the following contents. The lines specific to the usage of the NSwag generated client are highlighted.

import React, { Component } from 'react';
import { ContactsClient } from './contactsApi';  

export class ContactList extends Component {
    static displayName = ContactList.name;

    constructor(props) {
        super(props);
        this.state = { contacts: [], loading: true };
    }

    componentDidMount() {
        this.populateContactData();
    }

    static renderContactsTable(contacts) {
        return (
            <table className='table table-striped' aria-labelledby="tabelLabel">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Address</th>
                        <th>City</th>
                        <th>State</th>
                        <th>Postal Code</th>
                        <th>Phone</th>
                        <th>Email</th>
                    </tr>
                </thead>
                <tbody>
                    {contacts.map(contact =>
                        <tr key={contact.id}>
                            <td>{contact.name}</td>
                            <td>{contact.address}</td>
                            <td>{contact.city}</td>
                            <td>{contact.state}</td>
                            <td>{contact.postalCode}</td>
                            <td>{contact.phone}</td>
                            <td>{contact.email}</td>
                        </tr>
                    )}
                </tbody>
            </table>
        );
    }

    render() {
        let contents = this.state.loading
            ? <p><em>Loading...</em></p>
            : ContactList.renderContactsTable(this.state.contacts);

        return (
            <div>
                <h1 id="tabelLabel" >Contacts</h1>
                {contents}
            </div>
        );
    }

    async populateContactData() {
        let client = new ContactsClient();
        client.getContacts()
              .then(data => this.setState({ contacts: data, loading: false }));
    }
}

As you can see from the populateContactData code above we are creating a new instance of the ContactsClient and calling its getContacts function and using the data we get back from the API to set the state of the component with the data return from the API.

Now that the contact list is ready it needs a link in the navbar. First, in the App.js file, we need to add the contact list to the router. The following is the full file with the added lines highlighted.

import React, { Component } from 'react';
import { Route } from 'react-router';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { FetchData } from './components/FetchData';
import { Counter } from './components/Counter';
import { ContactList } from './components/ContactList';

import './custom.css'

export default class App extends Component {
  static displayName = App.name;

  render () {
    return (
      <Layout>
        <Route exact path='/' component={Home} />
        <Route path='/contacts' component={ContactList} />
        <Route path='/counter' component={Counter} />
        <Route path='/fetch-data' component={FetchData} />
      </Layout>
    );
  }
}

Now to make to add a Contacts link to the navbar open the NavMenu.js file and add the following to the with the other nav items.

<NavItem>
    <NavLink tag={Link} className="text-dark" to="/contacts">Contacts</NavLink>
</NavItem>

Wrapping  Up

I had a bit more trouble getting the NSwag client working this round, but that was more due to my shallow knowledge with React than a problem with NSwag.

The sample projects after all the changes in this post can be found here.

Using NSwag to Generate Angular Client for an ASP.NET Core 3 API

This week we are going to add an Angular project that will utilize the API we created a few weeks ago. This post is part of the revamp of my ASP.NET Core Basics repo that I kicked off when .NET Core 3.0 was released. For details on how we got to the current point in the application check out the following posts.

Swagger/OpenAPI with NSwag and ASP.NET Core 3
ASP.NET Core 3: Add Entity Framework Core to Existing Project
New Razor Pages Project Backed with an API

Do note that I realize that using an ASP.NET Core backed Angular project for this sample is overkill and a plain Angular application would have been all that is needed, but I wanted to use the ASP.NET Core template as a base for all the projects in this series. After the initial application creation, you can think of this example as setting up access to a secondary API in addition to the application’s main API if that helps.

The sample code before any of the changes in this post can be found here.

API Changes

Before we get to the actual Angular side of this post we are going to update the associated API to accept all cross-origin resource sharing (CORS) requests. The ASP.NET Core setup has a lot of options and I recommend being me explicit about what your API will accept if you can. Check out the official Microsoft CORS docs for more information.

All the changes needed will be in the Startup class of the API project. The CORS setup is policy-based and each policy needs a name that I stored in the following class level constant.

private const string AllowAllCors = "AllowAll";

In the ConfigureServices function add the following to register the CORS policy. Again be more restrictive with your policy if you can but for this example, we are opening up the API to allow any request.

services.AddCors(options =>
                 {
                     options.AddPolicy(AllowAllCors,
                                       builder =>
                                       {
                                           builder.AllowAnyHeader();
                                           builder.AllowAnyMethod();
                                           builder.AllowAnyOrigin();
                                       });
                 });

Finally, in the Configure function add the following to get CORS added to the HTTP pipeline processing. I’m not 100% sure if it matters where you added it in the pipeline, but I added it close to the front. I included a bit pipeline in the sample app for reference.

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseCors(AllowAllCors);

app.UseHttpsRedirection();

That is all the changes needed for the API, next we will create a new Angular project.

Create an Angular Project

Add a new directory for the application and then in a terminal navigate to that directory. Then the following command can be used to create the new Angular project. The target framework isn’t required, but I have a preview of .NET Core 3.1 installed and I wanted to make sure this project is targeting .NET Core 3.0.

dotnet new angular -f netcoreapp3.0

Next, use the following command to add the new project to the solution file which is in the root of the repo. Your filenames and paths could vary if you can’t using the same code of course.

dotnet sln ..\..\BasicsRefresh.sln add ContactsAngular.csproj

Use NSwagStudio to Generate Angular Client

NSwag provides multiple options for client generation including a CLI option, code, and a Windows application. This post is going to use the Windows application which is called NSwagStudio. Download and install NSwagStudio from here.

Next, make sure your API is running and get the URL of its OpenAPI/Swagger specification URL. For example, I am using a local instance of my API and the URL I need is https://localhost:5001/swagger/v1/swagger.json. If you are using the Swagger UI you can find a link to your swagger.json under the API title.

Now that we have the OpenAPI/Swager specification URL for the API switch over to NSwagStudio. The application will open with a new document ready to go. There are a few options we will need to set. First, select the OpenAPI/Swagger Specification tab and enter your API’s specification URL in the Specification URL box.

In the Outputs section check the TypeScript Client checkbox and then select the TypeScript Client tab. There are a lot of options to play with, but I highlighted the ones I changed to generate the client for this sample. First I entered a Module name so the generated code will all be in that module. For Template, it is very important to select Angular so that the resulting code will be set up for Angular’s dependency injection. Also, make sure and change the Injection token type to InjectionToken if you are on a newer version of Angular. The final option that needs to be set is the Output file path and this is the location you want the generated file to be. I output the Angular project directory under ClientApp\src\app\apis\contactApi.ts. After all the options are set click Generate Files.

For more information on generating Angular clients check the official docs on the subject.

Create UI and Use Generated Client

The sample API is for contact management so the UI we are going to build is to display a contact list. The new components are going to go in a new contacts directory under ClientApp\src\app. In this directory, we will need two new files one for the HTML, contact-list.component.html, and the other for the backing TypeScript class, contact-list.component.ts.

The following is the full content on the HTML file. I’m not going to go into the Angular specific bit in this post, but even if you don’t know Angular you will get the idea of what is going on. The rendered result will be a table of contacts.

<h1 id="tableLabel">Contacts</h1>

<p *ngIf="!contacts"><em>Loading...</em></p>

<table class='table table-striped' aria-labelledby="tableLabel" *ngIf="contacts">
  <thead>
    <tr>
      <th>Name</th>
      <th>Address</th>
      <th>City</th>
      <th>State</th>
      <th>Postal Code</th>
      <th>Phone</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let contact of contacts">
      <td>{{ contact.name }}</td>
      <td>{{ contact.address }}</td>
      <td>{{ contact.city }}</td>
      <td>{{ contact.state }}</td>
      <td>{{ contact.postalCode }}</td>
      <td>{{ contact.phone }}</td>
      <td>{{ contact.email }}</td>
    </tr>
  </tbody>
</table>

Next is the TypeScript class for the contact list. This is where you get to see the usage of the client that NSwag generated. The related lines are highlighted.

import { Component } from '@angular/core';
import { contacts as Contacts } from "../apis/contactApi";

@Component({
  selector: 'app-contact-list',
  templateUrl: './contact-list.component.html'
})
export class ContactListComponent {
  public contacts: Contacts.IContact[];

  constructor(contactsClient : Contacts.ContactsClient) {
    contactsClient.getContacts().subscribe(result => {
        this.contacts = result;
      },
      error => console.error(error));
  }
}

As you can see from the code above we are injecting the ContactClient and then calling its getContracts and assigning the results to the class’s local contacts variable.

Now that our components are built we need to register them with the application. These changes are in the app.module.ts file found in the ClientApp\src\app directory. The following is the full file excluding the imports that were existing with the changes for our contact related items highlighted.

import { ContactListComponent } from "./contacts/contact-list.component";
import { contacts } from "./apis/contactApi";

@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    HomeComponent,
    CounterComponent,
    FetchDataComponent,
    ContactListComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    HttpClientModule,
    FormsModule, 
    RouterModule.forRoot([
      { path: '', component: HomeComponent, pathMatch: 'full' },
      { path: 'contact-list', component: ContactListComponent },
      { path: 'counter', component: CounterComponent },
      { path: 'fetch-data', component: FetchDataComponent },
    ])
  ],
  providers: [contacts.ContactsClient],
  bootstrap: [AppComponent]
})
export class AppModule { }

The first change was to import both the ContactListComponent and contacts which is the contact client. Next, the ContactListComponent was added to the declarations array. Then we added the ContactListComponent to the RouterModule so that Angular will know how to get us to the contact list page. Finally, we added the ContractsClient to the providers array which will allow Angular to inject the client into our contact list component.

To add our contact list to the nav menu we need to change the nav-menu.component.html file in the ClientApp\src\app\nav-menu directory. Add the following list item to add a Contact link in the navbar.

<li class="nav-item" [routerLinkActive]="['link-active']">
  <a class="nav-link text-dark" [routerLink]="['/contact-list']"
    >Contacts</a
  >
</li>

Wrapping Up

I’m repeating myself, but NSwag’s client generation makes it very simple to get starting consuming APIs, but even over time being able to regenerate a client for an API and have any changes in that API ready to go is really nice.

The sample projects after all the changes in this post can be found here.

Use HTTP Client Factory with NSwag Generated Classes in ASP.NET Core 3

In last week’s post, Using NSwag to Generate C# Client Classes for ASP.NET Core 3, we left off with a usable client, but we were missing out on using some of the features provided by ASP.NET Core such as the HTTP Client Factory and utilizing dependency injection.

Changes to NSwag Client Generation

This post is only going to point out the difference needed to help enable utilization of the ASP.NET Core features mentioned above and won’t be a full walkthrough of using NSwag. If you need a reference for what this post is covering make sure and read last week’s post.

The one change needed from last week’s post is to check Generate interfaces for Client classes.

With the above checked the client class can be regenerated and the files in the consuming application updated.

Using HTTP Client Factory and Dependency Injection

In the consuming application, we need to add the following to line in the ConfigureServices function of the Startup class to add an HTTP Client specifically for our Contacts API and make it available via the dependency injection system.

services.AddHttpClient<IContactsClient, ContactsClient>(client => 
           client.BaseAddress = new Uri("https://localhost:5001"));

For a production application, I would recommend using the configuration system to store the URL for the API instead of hardcoded like it is above.

For example usage, I’m using the IndexModel. First,  add a class-level field to hold our API client and inject the client via the constructor.

private readonly IContactsClient _contactsClient;

public IndexModel(ILogger<IndexModel> logger, IContactsClient contactsClient)
{
    _logger = logger;
    _contactsClient = contactsClient;
}

Now that we have a contacts client at the class-level we can use it get data from our API. The following example uses the client to get all the contacts from the API and stores them in a variable.

public async Task OnGet()
{
    var contacts = await _contactsClient.GetContactsAsync();
}

Wrapping Up

I highly recommend using this style of client vs. using HTTP client directly. If you do some searching you will find that managing the lifetime of HTTP client in .NET before the HTTP client factory was something that is easy to screw up.

The following posted were used as references:

Generating a Typed Client for use with HttpClientFactory using NSwag
How to add generated HttpClient to ASP.NET Core dependency injection

Using NSwag to Generate C# Client Classes for ASP.NET Core 3

This post is going to use one of the tools provided by NSwag to generate C# client classes to provide access to an API. While the NSwag tooling provides multiple ways to discover the definition of an API we will be using the tooling to generate C# classes from an OpenAPI/Swagger specification.

For details on how to use NSwag to provide OpenAPI/Swagger for your APIs check out my Swagger/OpenAPI with NSwag and ASP.NET Core 3 post. You can grab the API I’m using in the post from this GitHub repo if you need an API to play around with. If you do grab the sample API from GitHub not that it does use Entity Framework Core and SQLite which means you will need to create the associated database. Details of how to do that can be found in the Create and Apply Initial Migration section of my ASP.NET Core 3: Add Entity Framework Core to Existing Project post.

Sample Client Application

For this example, we will spin up a Razor Pages application using the .NET CLI with the following command from your favorite terminal application in the directory you want the application created.

dotnet new webapp

NSwag Client Generation

NSwag provides multiple options for client generation including a CLI option, code, and a Windows application. This post is going to use the Windows application which is called NSwagStudio. Download and install NSwagStudio from here.

Next, make sure your API is running and get the URL of its OpenAPI/Swagger specification URL. For example, I am using a local instance of my API and the URL I need is https://localhost:5001/swagger/v1/swagger.json. If you are using the Swagger UI you can find a link to your swagger.json under the API title.

Now that we have the OpenAPI/Swager specification URL for the API we are dealing with open NSwagStudio. The application will open with a new document ready to go. There are a few options we will need to set. First, we want to use the NetCore30 Runtime. Next, select the OpenAPI/Swagger Specification tab and enter your API’s specification URL in the Specification URL box.

In the Outputs section check the CSharp Client checkbox and then select the CSharp Client tab. As you can see from the screenshot below there are a ton of options to tweak. For this example, we are taking the defaults for all of them except for Namespace, which I set to ContactsApi, and Output file path, which is only needed if you use the Generate Files option. Click the Generate Files button and NSwagStudio will create a file that contains all the code needed to access the API described in the OpenAPI/Swager specification selected in the Input section.

Note, the Generate Outputs button can be used if you want to see what the generated code will look in the Output tab on the same level as Settings.

Use Generated Client from the Sample Project

In the sample project, I created an APIs directory and dropped the ContactsApi.cs created with NSwagStudio there. The files generated with NSwagStudio are expecting JSON.NET to be present so the sample project will need a reference to the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package.

Now that the project has a reference to JSON.NET in the ConfigureServices function of the Startup class we need to tell the app to make JSON.NET available via dependency injection with the following change.

services.AddRazorPages()
        .AddNewtonsoftJson();

Now to test out the client I used the following OnGet function in the Index.cshtml.cs file.

public async Task OnGet()
{
    using (var httpClient = new HttpClient())
    {
        var contactsClient = new ContactsClient(httpClient);
        var contacts = await contactsClient.GetContactsAsync();
    }
}

Note the above is only meant to show that the generated client work and isn’t meant to be a production-grade example. For more production-grade scenarios make sure and following Microsoft’s guidance on HTTP client usage.

Wrapping Up

NSwag’s client generation seems to be an easy way to get started consuming API’s. I’m not sure if the CLI would provide more options for how the client code is generated or not with support of HTTPClientFactory and strongly typed HTTP Clients. This will be something I may explorer more in a future post.

Swagger/OpenAPI with NSwag and ASP.NET Core 3

Now that .NET Core 3 is out I thought it would be a good time to revisit exposing API documentation using Swagger/OpenAPI. In the past, I have written posts on using Swashbuckle to expose Swagger documentation, but for this post, I’m going to try out NSwag.

What is OpenAPI vs Swagger?

To quote the Swagger docs:

OpenAPI Specification (formerly Swagger Specification) is an API description format for REST APIs. An OpenAPI file allows you to describe your entire API. API specifications can be written in YAML or JSON. The format is easy to learn and readable to both humans and machines.

Swagger is a set of open-source tools built around the OpenAPI Specification that can help you design, build, document and consume REST APIs.

What is NSwag?

Quoting the NSwag GitHub readme:

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.

One neat thing about NSwag is it also has the tooling to help generate the API consumer side in addition to the OpenAPI specs.

Sample Project

For this post, I created a new API project via the .NET CLI using the following command. Not that all this can be done via the Visual Studio UI if that is your preference.

dotnet new webapi

For me, this project is going to be the start of a new series of posts so I also added a solution file and added the project created above to it. These commands are optional.

dotnet add sln
dotnet sln add src\ContactsApi\ContactsApi.csproj

Add NSwag

Using the CLI in the same directory as the project file use the following command to add a reference to NSwag.AspNetCore to the project.

dotnet add package NSwag.AspNetCore

Next, in your favorite editor open the project/directory we created and open the Startup.cs file. In the ConfigureServices function add services.AddOpenApiDoccument.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddOpenApiDocument();
}

Then at the end of the Configure function add calls to app.UseOpenApi and app.UseSwaggerUi3.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    app.UseOpenApi();
    app.UseSwaggerUi3();
}

Note that NSwag also supports ReDoc if you prefer that over Swagger UI.

Sample Model and Controller

Now that we have NSwag installed let’s create a new endpoint for it to display. As per my norm, I will be doing this using contacts as an example. First I created a Models directory and then added the following Contact class to it.

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Next, in the Controllers directory add a ContactsController, which in the following code returns a list of 5 generic contacts.

[ApiController]
[Route("[controller]")]
public class ContactsController : ControllerBase
{
    private readonly ILogger<ContactsController> _logger;

    public ContactsController(ILogger<ContactsController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<Contact> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new Contact
        {
            Id = index,
            Name = $"Test{index}",
            Address = $"{index} Main St.",
            City = "Nashville",
            State = "TN",
            PostalCode = "37219",
            Phone = "615-555-5555",
            Email = $"test{index}@test.com"
        });
    }
}

Results

Run your project and then in a browser navigate to your base URL /swagger. For example my for my project that is https://localhost:5001/swagger. You should see something like the following that will let you explore your API and even execute requests against your API using the Try it out button you see in the UI.

Wrapping Up

Just like with Swashbuckle, NSwag makes it very easy to get started providing API documentation. This post just covers the very basics and I’m looking forward to digging into some of the more advanced features that NSwag has such as client generation.

Microsoft has a great article on Getting Started with NSwag on their docs site that I recommend reading. This is a preview of something I plan to cover in the future, but there are attributes that can be added to controllers that help NSwag provide better details about what your API can return and Microsoft has a doc on Use web API conventions that makes it easy to apply some of the common conventions.

Trying Out BenchmarkDotNet

In software, there are tons of different ways to accomplish the same thing and one of the metrics we tend to use to determine a course of action is how we feel that one set of code will perform over another.  The thing is determining which code actually performs better is a bit tricky and I feel like in general people make the choice based on a gut feeling more than actual evidence. Even when evidence a developer has involved if it wasn’t properly collected then it isn’t actually helpful. For example, trying to determine the performance of a set of code when running in debug mode isn’t actually a good indicator of how it is going to perform.

What is a developer to do? Well, this is where BenchmarkDotNet comes in. Here is how the project describes itself.

Benchmarking is really hard (especially microbenchmarking), you can easily make a mistake during performance measurements. BenchmarkDotNet will protect you from the common pitfalls (even for experienced developers) because it does all the dirty work for you: it generates an isolated project per each benchmark method, does several launches of this project, run multiple iterations of the method (include warm-up), and so on. Usually, you even shouldn’t care about a number of iterations because BenchmarkDotNet chooses it automatically to achieve the requested level of precision.

This rest of this post is going to cover creating a sample project using BenchmarkDotNet.

Sample Project

We will be using a new .NET Core console application which can be created using the following .NET CLI command.

dotnet new console

Next, run the following command to add the BenchmarkDotNet NuGet package.

dotnet add package BenchmarkDotNet

Now in the Main function of the Program class, we need to tell the application to run the benchmark we are interested in. In this example, we are telling it to run the benchmarks in the Strings class.

public static void Main(string[] args)
{
    BenchmarkRunner.Run<Strings>();
}

Now in the Strings class, we have two functions marked with the Benchmark attribute which is how the package identifies which functions to measure. For this example, we will be measuring the performance of two different ways to do case insensitive string comparisons.

public class Strings
{
    private readonly Dictionary<string, string> _stringsToTest = 
         new Dictionary<string, string>
         {
             { "Test", "test" },
             { "7", "7" },
             { "A long string", "Does not match" },
             { "Testing", "Testing" },
             { "8", "2" }
         };


    [Benchmark]
    public bool EqualsOperator()
    {
        var result = false;

        foreach (var (key, value) in _stringsToTest)
        {
           result = key.ToLower() == value.ToLower();
        }

        return result;
    }

    [Benchmark]
    public bool EqualsFunction()
    {
        var result = false;

        foreach (var (key, value) in _stringsToTest)
        {
            result = string.Equals(key, value,
                                   StringComparison.OrdinalIgnoreCase);
        }

        return result;
    }
}

I’m sure there is a better way to set up data for test runs, but the above works for my first go at it.

Results

Run the application in release mode and you will see output similar to the following.

Wrapping Up

Having a tool that takes all the guesswork out of how operations perform is going to be very valuable. This is one of those tools I really wish I had found years ago. The project is open source and can be found on GitHub.

.NET Core: Windows Compatibility Pack

Windows Compatibility Pack

A little over a year ago Microsoft released the Windows Compatibility Pack for .NET Core that filled in some gaps in .NET Core APIs if your application doesn’t need to run cross-platform. While some of the APIs included in the compatibility pack was added back when support for .NET Standard 2 was released, such as System.Data.SQL client. Some of the APIs will never make it into the .NET Standard because they are Windows only constructs such as registry access.

Since it has been such a long time since the compatibility pack was released I thought this post would be a good reminder. In this post, we will create a new .NET Core application and using the Windows Compatibility Pack to access the registry.

Application Creation

Use the following command from a command prompt to create a new .NET Core console application.

dotnet new console

Use the following command to add a reference to the compatibility pack NuGet package.

dotnet add package Microsoft.Windows.Compatibility

Using the Registry

The following is the full code for the application. This code may not be the best practice, but it does demonstrate the usage of the registry.

class Program
{
    static void Main(string[] args)
    {
        var thing = "World";

        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            using (var regKey = Registry
                                .CurrentUser
                                .CreateSubKey(@"Software\Testing\Test"))
            {
                thing = regKey.GetValue("ThingText")?.ToString() ?? thing;
                regKey.SetValue("ThingText", "Registry");
            }
        }

        Console.WriteLine($"Hello {thing}!");
    }
}

Take special note of the if statement surrounding the registry access as it allows you to check what platform you are running on and vary your implementation, which is very helpful if your application is actually run cross-platform, but you need some slight differences when running on a particular OS.

The application should output “Hellow World!” the first run and “Hello Registry!” the second run.

Wrapping Up

If you were creating a new application it would be best to stay away from platform specific API as much as possible and stick with the APIs defined by the .NET Standard. If you are trying to convert an existing application I could see the compatibility pack speeding your conversion without having to rewrite part of the application that happens to us Windows-based APIs.

GitHub and Azure Pipelines: Build Triggers

In response to my post on GitHub and Azure Pipelines, I got the following question on Reddit.

Does this automatically detect branches? From your screenshot, you’re building master. If you copy to feature-A, does a new pipeline automatically get created and built?

When I initially answered this question I didn’t go deep enough. The answer to does a new pipeline automatically get created and built is no as I replied, but I think the intent of the question is do I have to go set up a new pipeline every time I create a new branch and the answer to that is also no. The existing pipeline will be triggered when any change is checked in on any branch by default. Do note that it won’t be triggered when the branch is created only when a change is checked in.

Limiting Builds

There are a couple of ways to control what branches trigger continuous integration builds. The first is by making edits to the azure-pipeline.yml file in the repo and the second is via an override in the Azure Pipeline.

YAML

The official Build pipeline triggers docs are really good, but I will cover the basic here for including branches and excluding branches. Check for docs for information on path includes/excludes as well as how to control PR validation. As an example here is the yaml file used to define a build in this repo.

pool:
  vmImage: 'Ubuntu 16.04'

variables:
  buildConfiguration: 'Release'

steps:
- script: dotnet build Sqlite --configuration $(buildConfiguration)
  displayName: 'dotnet build $(buildConfiguration)'

In order to control what branches get built, we need to add a trigger section. The smilest example is to list the branches you want to build. Ending wildcards are allowed. See the following example (trigger section taken from the official docs).

pool:
  vmImage: 'Ubuntu 16.04'

variables:
  buildConfiguration: 'Release'

steps:
- script: dotnet build Sqlite --configuration $(buildConfiguration)
  displayName: 'dotnet build $(buildConfiguration)'

trigger:
- master
- releases/*

This would build master and all branches under releases, but nothing else. The following shows how to use includes and excludes together. Again the triggers section is taken from the official docs.

pool:
  vmImage: 'Ubuntu 16.04'

variables:
  buildConfiguration: 'Release'

steps:
- script: dotnet build Sqlite --configuration $(buildConfiguration)
  displayName: 'dotnet build $(buildConfiguration)'

trigger:
  branches:
    include:
    - master
    - releases/*
    exclude:
    - releases/old*

This would build master and everything in under releases that does not start with old. Really go read the official docs on this one to see all the ins and outs.

Azure Pipelines

To override the CI build from Azure DevOp go to the build in question and click Edit.

Next, select Triggers and Continuous integration and check Override YAML.

After checking the override you will see a lot more options light up. As you can see in the following screenshot the same include and exclude options are available with the same options for wildcards.

Wrapping Up

As you can see Azure Pipelines provides a lot of flex ability in how a build gets triggered. On top of what I covered here, there are also options for setting up scheduled builds as well as trigging a build with another build is completed. If you hit a scenario that couldn’t be covered I would love to hear about it in the comments.

GitHub and Azure Pipelines

A few weeks ago Microsoft announced that Visual Studio Team Services was being replaced/rebranded by a collection of services under the brand Azure DevOps. One of the services that make up Azure DevOps is Azure Pipelines which provides a platform for continuous integration and continuous delivery for a huge number of languages on Windows, Linux, and Mac.

As part of this change, Azure Pipelines is now available on the GitHub marketplace. In this post, I am going to pick one of my existing repos and see if I can get it building from GitHub using Azure Pipelines. I’m sure Microsoft or GitHub has documentation, but I’m attempting this without outside sources.

GitHub Marketplace

Make sure you have a GitHub account with a repo you want to build. For this post, I’m going to be using my ASP.NET Core Entity Framework repo. Now that you have the basic prep out of the way head over to the GitHub Marketplace and search for Azure Pipelines or click here.

Scroll to the bottom of the page to the Pricing and setup section. There is a paid option that is the default option. Click the Free option and then click Install it for free.

On the next page, you will get a summary of your order. Click the Complete order and begin installation button.

On the next page, you can select which repos to apply the installation to. For this post, I’m going to select a single repo. After making your choice on repos click the Install button.

Azure DevOps

After clicking install you will be thrown into the account authorization/creation process with Microsoft. After getting authorized you will get to the first set up in the setup process with Azure. You will need to select an organization and a project to continue. If you don’t have these setup yet there are options to create them.

After the process complete you will be land on the New pipeline creation process where you need to select the repo to use. Clicking the repo you want to use will move you to the next step.

The next step is a template selection. My sample is an ASP.NET Core application so I selected the ASP.NET Core template. Selecting a template will move you to the next step.

The next page will show you a yaml file based on the template you selected. Make any changes your project requires (my repo had two projects so I had to change the build to point to which project I wanted to build).

Next, you will be prompted to commit the yaml file to source control. Select your options and click Save and run.

After your configuration gets saved a build will be queued. If all goes well you will see your app being built. If everything works you will see something like this build results page.

Wrapping Up

GitHub and Microsoft have done a great job on this integration. I was surprised at how smooth the setup was. It was also neat to see a project that I created on Windows being built on Linux.

If you have a public repo on GitHub and need a way to build give Azure Pipelines a try.