Friday, December 11, 2020

Use Service Reference in Visual Studio 2019 to consume a REST API with OpenAPI description from a C# console app

In this tutorial I will show you how easy it is to consume a REST API Service using the ‘Service Reference …’ feature in Visual Studio 2019. I will consume a simple service located at https://api4all.azurewebsites.net/

Companion video: https://youtu.be/XqIniGHpcEc

Source Code: https://github.com/medhatelmasry/ConsumeOpenAPI.git

Prerequisites:

  1. You need to have Visual Studio 2019 installed on your Windows computer. In my case, I am using: Microsoft Visual Studio Community 2019 Version 16.8.2
  2. The REST API you are consuming needs to have an OpenAPI programming language-agnostic interface description for REST APIs.
Point your browser to https://api4all.azurewebsites.net/. The landing page is an OpenAPI page that has the following heading:

OpenAPI Endpoint







Copy the link to the swagger.json file in the top-left corner and park it in Notepad.exe for later use.

Let us create a simple “Console App (.NET Core)” application in Visual Studio 2019 to consume the REST API service.
Console App (.NET Core)

Once your console app is created, Add >> Service Reference …

Add >> Service Reference
Choose OpenAPI, then click Next.
OpenAPI

Select URL then paste into the textbox the link to the swagger.json file that you parked in Notepad.exe. Click on Finish.
OpenAPI URL

A "Service reference configuration progress" dialog will appear. Click Close when it is done.
Service reference configuration progress

Looking at "Solution Explorer", you will find a folder named OpenAPI with swagger.json contained inside it.
swagger.json


Build (or compile) your application so that the proxy class that gets created is visible in your application's environment.

If you open your obj folder in File Explorer, you will find that a proxy class named swaggerClient.cs was auto-magically created for you.
swaggerClient.cs

Feel free to open this file in a text editor to have a peek at its contents. Alternatively, you can click on ... in your Service Dependencies dialog and select "View generated code".
View generated code


These are the CRUD methods that are provided  by the swaggerClient object:

Method nameHTTP VerbPurpose
StudentsAllAsyncGETretrieve all students
Students2AsyncGETget student by id
StudentsAsyncPOSTadd a student
Students3AsyncPUTupdate student data
Students4AsyncDELETEdelete student by id

It is obvious that the swaggerClient method names are not very intuitive. The above table will help you figure out the translation.

Add the following instance variable, that represents the BASE_URL, to the Program.cs class:

const string BASE_URL = "https://api4all.azurewebsites.net";

Add the following displayStudents() method to Program.cs:

private static async Task displayStudents() {
  using (var httpClient = new HttpClient()) {
    var client = new swaggerClient(BASE_URL, httpClient);
    var items = await client.StudentsAllAsync().ConfigureAwait(false);
    foreach (var i in items) {
      Console.WriteLine($"{i.StudentId}\t{i.FirstName}\t{i.LastName}\t{i.School}");
    }
  }
}

Replace your Main() method in Program.cs with the following code:

static async Task Main(string[] args) {
   await displayStudents();
}

OpenAPI output

Below are the other methods that complete all other CRUD operations:

private static async Task getStudentById(string id) {
  using (var httpClient = new HttpClient()) {
    var client = new swaggerClient(BASE_URL, httpClient);
    var item = await client.Students2Async(id);
    Console.WriteLine($"{item.StudentId}\t{item.FirstName}\t{item.LastName}\t{item.School}");
  }
}

private static async Task addStudent() {
  using (var httpClient = new HttpClient()) {
    var client = new swaggerClient(BASE_URL, httpClient);
    var student = new Student() {
        StudentId = "A00777776",
        FirstName = "Joe",
        LastName = "Roy",
        School = "Forestry"
    };

    try {
      var response = await client.StudentsAsync(student);
    } catch (ApiException apiEx) {
      // not really error because server returns HTTP Status Code 201
      Console.WriteLine(apiEx.ToString());
    }
  }
}

private static async Task updateStudentById(string id) {
  using (var httpClient = new HttpClient()) {
    var client = new swaggerClient(BASE_URL, httpClient);
    var student = new Student() {
        StudentId = id,
        FirstName = "Pam",
        LastName = "Day",
        School = "Nursing"
    };
    await client.Students3Async(id, student);
  }
}

private static async Task deleteStudentById(string id) {
    using (var httpClient = new HttpClient()) {
      var client = new swaggerClient(BASE_URL, httpClient);
      var item = await client.Students4Async(id);
    }
}

I hope you appreciate how easy and painless it is to consume an OpenAPI REST service using Visual Studio 2019.

No comments:

Post a Comment