Header Ads

How to Create RESTful Web APIs CRUD using Serverless C#.NET Watson Webserver

RESTful web APIs are not only popular, but also a pinnacle point of exchanging data between servers and clients. The main reason why RESTful web APIs are popular as oppose to Web Services is that it makes client machine independent of underlying technology in which it is being created. All client machine needs is HTTP library that supports RESTful web API integration. Since, RESTful web APIs only design to exchange data, therefore, they can be developed using any serverless solution. The most popular one is definitely Azure function, but there is another newly developed console based serverless solution using C#.NET dedicated just for RESTful web APIs development called Watson Webserver. Although, you can work with database access frameworks of your choice, but, this library comes with database access object-relational mapper (ORM) framework of its own called WatsonORM.

I highly recommend exploring these two libraries. They are extremely easy to setup, integrate and build your RESTful web APIs on. Deployment is also fairly simple because the web server is console based. Watson webserver provides all the necessary method for developing RESTful web APIs, such as registering API routes, blocking specific IP address, authorization and authentication mechanisms and many more. While WatsonORM provides all the necessary methods to create, read, update and delete (CRUD) database operations.
 
Today, I shall be demonstrating the creation of RESTful Web APIs CRUD operations using Serverless C#.NET based solution Watson Webserver library along with WatsonORM library for integrating SQLite database. I will also demonstrate the integration between Watson webserver and WatsonORM.




Prerequisites:

Before proceeding any further in this article, following are some of the many prerequisites for this article:
  1. Knowledge of RESTful Web APIs.
  2. Knowledge of C# Programming.
  3. Knowledge of .NET Core 6 or above framework.
  4. Knowledge of .NET Console Application Development.
The running working source code solution for this article is being developed in Microsoft Visual Studio 2022 Professional.

Download Now!

Let's begin now.

1) In the first step, create a new "Console App" project that supports .NET core platform and then name it "WatsonApIwithDB". Make sure to check the "Do not use top-level statements" checkbox. Since, this is a local project, Watson webserver is by default configured for "HTTP" requests. You can however, configure it for HTTPS, detail guidelines are provided on the project page.
 


2) To connect the project with Watson webserver and WatsonORM, following list of packages are required to be installed using nuget package manager within visual studio in the below listed order i.e.

  1. Watson
  2. WatsonORM

You also need to install 'Newtonsoft.Json' package if it is not already installed in your project.




3) Now, open "Program.cs" file and add global private static properties such as server host name, server port, Watson settings and Watson webserver objects i.e.

...

static string _hostname = "localhost";
static int _port = 9000;
static WebserverSettings _settings = null;
static WebserverBase _server = null;

...

4) Next step is to initialize the Watson web server with these settings within the "Main" method along with implementation of default route method. The signature to default route method is very important as this is how Watson web server will recognize an API endpoint i.e.

...

static void Main(string[] args)
{
   ...

   //  Settings.
   Program._settings = new WebserverSettings
   {
        Hostname = _hostname,
        Port = _port
   };

   // Settings
   Program._server = new WatsonWebserver.Webserver(Program._settings, DefaultRoute);

   ...
}

...

public static async Task DefaultRoute(HttpContextBase context)
{
   ...        

   // Prepare JSON Response.
   // TODO: 
   string json = string.Empty;

   // Sending Response
   await context.Response.Send(json);

   // Info
   return;
  ...
}

...

5) Now, add the below line of code to start the Watson web server. Notice that at this point in time there is no API end point available, just the default route i.e.


...

// start the server
Program._server.Start();

...


The Watson web server is up and running. Since, server is not authorize, therefore, you can access the default URL from both browser and RESful web API clients i.e.


6) Next step is to implement the API endpoint method "GetAllProducts". At the moment API will not return anything since I have not connected any database i.e.

...

public static async Task GetAllProducts(HttpContextBase context)
{
   ...

   // Process Request.
   // TODO:
   
   // Load products data.
   // TODO:

   // Prepare JSON Response.
   // TODO: 
   string json = string.Empty;

   // Sending Response
   await context.Response.Send(json);

   ...

   // Info
   return;
}

...


7)
Now, register the "GetAllProducts" API endpoint method with the Watson web server with the below line of code before starting the server i.e.

...

// Register API endpoint.
Program._server.Routes.PreAuthentication.Dynamic.Add(HttpMethod.GET, "^/webapi/GetAllProducts/?$", GetAllProducts);

// start the server
Program._server.Start();

...

Watson web server allow API endpoints route registering as static or dynamic. The only difference they have is that for static route registering, provided path has to be absolute. So, when you execute using RESTful web API client you will be able to see below result i.e.


8) Now, authorize the API endpoints, so, they can only be accessible via authorized resources with the below line of code above the route registration i.e.

...

static void Main(string[] args)
{
   ...

   // Setting Web APIs Authentication.
   Program._server.Routes.AuthenticateRequest = AuthenticateRequest;

   // Register API endpoint.
   Program._server.Routes.PostAuthentication.Dynamic.Add(HttpMethod.GET, "^/webapi/GetAllProducts/?$", GetAllProducts);

   // start the server
   Program._server.Start();

   ...
}

public static async Task AuthorizeApiAccess(HttpContextBase context)
{
   ...        

   // Verify Authorization.
   // TODO:

   // Prepare JSON Response.
   // TODO: 
   string json = string.Empty;

   // Sending Response
   await context.Response.Send(json);

   ...

   // Info
   return;
}
...


You need to change the route registering from "PreAuthenticaiton" to "PostAuthentication" otherwise your API endpoint will not be securely authorized and can be publicly accessed. Now, if you try to access the API endpoint without and with the authorization you will get below results i.e.





9) In order to integrate WatsonORM database access layer. Create table classes i.e. "ProductTypeTable" and "ProductTable" with relevant properties i.e.

...

[Table("ProductTypeTable")]
internal class ProductTypeTable
{
    [Column("productTypeId", true, DataTypes.Int, false)]
    public int ProductTypeId { get; set; }

    [Column("productTypeName", false, DataTypes.Nvarchar, 200, false)]
    public string? ProductTypeName { get; set; }

}

[Table("ProductTable")]
internal class ProductTable
{
    [Column("productId", true, DataTypes.Int, false)]
    public int ProductId { get; set; }

    [Column("productCode", false, DataTypes.Nvarchar, 200, false)]
    public string ProductCode { get; set; }

    [Column("productName", false, DataTypes.Nvarchar, 200, false)]
    public string ProductName { get; set; }

    [Column("productPrice", false, DataTypes.Int, false)]
    public int ProductPrice { get; set; }

    [Column("productTypeIdFk", false, DataTypes.Int, false )]
    public virtual int ProductTypeIdFk { get; set; }
}

...


You have to explicitly add table attribute annotation and column attribute annotations, so that WatsonORM can recognize the table and its columns. For relational integrity, like foreign key I have added the keyword virtual, however, WatsonORM especially for SQLite database does not explicitly impose the referential integrity during the creation of the table.

 
10) 
Now, next step is to create out database context class, in which all the database related operations will be implemented along with the initialization of the SQLite database with the designated tables. So, create a class "DbProductsContext" and within this class I have created default constructor and all the relevant database operations such as insert, update, delete specific product, delete all products, select all products and select products by search. I will not go into their details though, but, show you with below lines of code that how you can initialize WatsonORM for SQLite database i.e.

...

internal class DbProductsContext
{
    private readonly string _dbPath = string.Empty;
    private readonly DatabaseSettings _dbSettings = null;
    private readonly WatsonORM _dbWatsonORM = null;

    public DbProductsContext()
    {
        ...

        // Settings
        this._dbPath = "db_products.db";

        // Iitialize Database.
        this._dbSettings = new DatabaseSettings(this._dbPath);
        this._dbWatsonORM = new WatsonORM(this._dbSettings);

        //create Database Tables
        this._dbWatsonORM.InitializeDatabase();

        // Initialize Table        
        this._dbWatsonORM.InitializeTable(typeof(ProductTable));
 
       // Initialize Table                
        this._dbWatsonORM.InitializeTable(typeof(ProductTypeTable));


       ...
    }

}

...


11)
To integrate the WatsonORM database context class with Watson Webserver, go back to Program.cs file and create a global public static readonly variable of type "DbProductsContext" and initialize it as shown below. This public static property is accessible to your project and you can utilize it access the SQLite database. This property needs to be initialized only once, since the default constructor initialize the SQLite database with the tables. i.e.

...

public readonly static DbProductsContext databaseManager = new DbProductsContext();

...


12) Now, when you execute the project, and calls out different authorized RESTful web API endpoints using any RESTful web API client, you will be able to see below results. I have created six different API endpoints to keep things simple, although two remove APIs can be merged in one and two get products APIs can also be merged in one API, but I am keeping things simple for now. i.e.

1) Add Product





2) Get All Products





3) Edit Product

Only product table will be affected, but if new product type name is send in request then product type table will also get updated.







4) Get Products by Search



5) Get Products by Search with Arithmetic Operation


 

6) Delete Specific Product

Only product table will be affected.




 

7) Delete All Products

Only products table will be affected.





Conclusion

In this article, you will learn to about the creation of  RESTful Web APIs CRUD operations using Serverless C#.NET based solution Watson Webserver library along with WatsonORM library for integrating SQLite database. You will learn about the Watson web server, a serverless C#.NET based RESTful web API creation library. You will also learn about WatsonORM, an object-relational mapper for creating database and performing database operation on SQLite database such as insert, update, delete and select. You will learn about the API endpoint route registration. You will also learn about the authorizing and authenticating the API endpoints within Watson web server. You will learn to create a database context class along with creation of table classed that WatsonORM accepts. You will also learn to create WatsonORM database initialization for SQLite database along with the creation of SQLite database table. Finally, you will learn to register the database context object with Watson web server, in order to integrate the WatsnORM with Watson web server. You will also have a glimpse of different authorized RESTful web APIs CRUD operation endpoints that I have implemented.

No comments