.NET Nakama

Improving your .NET skills

Create and Run a Hello World, CRUD Web API

October 04, 2020 (~26 Minute Read)
BASICS WEB API REST CRUD

Introduction

The time has come, let’s build a simple “Hello, World!” REST Web API having dummy CRUD (Create, Retrieve, Update, and Delete) operations. We will investigate the differences between the available hosting model options (Kestrel, IIS Express, In-Process, Out-of-Process) when running/serving the web-project-application and investigate the code structure of an API controller (routes, data-bind, etc.).

Create a ASP.NET Core Web API

In this tutorial, we will learn the basics when building a web API with ASP.NET Core. We will use Visual Studio 2019 (Community) IDE. Follow the instructions below to create and run an ASP.NET Core Web API, having a dummy scaffolded API Controller with CRUD operations.

Running an ASP.NET Core Web API

In order to start serving a Web API, an HTTP server is required to handle the HTTP requests. In Visual Studio 2019 (for Windows) there are two available options (profiles) by default, in order to start running/serving the web-project-application (Figure 2). To start running the application, select the preferred option and click on the green “play” button. Let’s investigate the differences between these options (hosting models) to have a better understanding of its selection.

Select how to start running/serving the web-project-application.
Figure 2. - Select how to start running/serving the web-project-application.
  • TutorialWebApi (or your project name)
    • ASP.NET Core provides a cross-platform HTTP server implementation named as Kestrel, which listens for HTTP requests and provides them to the application as a set of request features composed into an HttpContext (Request, Response, User, etc.).
    • Kestrel server is the default HTTP server for projects running on macOS and Linux.
    • Kestrel can be used either
      • As an HTTP server processing requests directly from a network, or
      • With a reverse proxy server, such as Internet Information Services (IIS), Nginx, Apache, etc. The reverse proxy server receives HTTP requests from the Internet and forwards them to Kestrel.
  • IIS Express
    • IIS is an extensible web server software created by Microsoft for use with Windows OS.
    • IIS Express is a lightweight, self-contained version of IIS optimized for developers. IIS Express makes it easy to use the most current version of IIS to develop and test websites.
    • Using IIS, the application runs either

Using Kestrel by Itself

Kestrel server processes the requests directly from a network, as shown in Figure 3. To use Kestrel as an HTTP server in Visual Studio, follow the steps described below.

Using Kestrel server to directly process requests
Figure 3. - Using Kestrel server to directly process requests (Source).
  • Select your project name as shown in Figure 2 (e.g. “TutorialWebApi” in our example) and then start running the application.
  • A terminal window will be opened that executes our application (see Figure 4). We can see that our web application is served on http://localhost:5000 and https://localhost:5001.
  • Additionally, our default browser will be opened with https://localhost:5001/weatherforecast.
  • We can see details about the request/response by opening the Developer-Tools by clicking F12 and then reloading the page (F5). Then, depending on your browser, open the network tab to see that the server response header is “Kestrel” as shown in Figure 5.
Terminal execution example when using Kestrel server to directly process requests.
Figure 4. - Terminal execution example when using Kestrel server to directly process requests.
The response server header when using Kestrel server to directly process requests.
Figure 5. - The response server header when using Kestrel server to directly process requests.

Using Kestrel with a Reverse Proxy Server

The reverse proxy server (such as IIS, Nginx, or Apache) receives HTTP requests from the Internet and forwards them to Kestrel (Figure 6). For that reason, our application should be configured in order to work behind a proxy (e.g. read Forwarded Headers, Security, etc.) and the proxy should be configured respectively. The following tutorial shows how to host an ASP.NET Core application on Linux with Nginx and on Linux with Apache, as a reverse proxy server.

Using a reverse proxy server to forward request to Kestrel
Figure 6. - Using a reverse proxy server to forward request to Kestrel (Source).

Using IIS Express In-Process

Using in-process hosting, an ASP.NET Core application runs in the same process as its IIS worker process (w3wp.exe or iisexpress.exe) as shown in Figure 7. In-process hosting provides improved performance over out-of-process hosting because requests aren’t proxied over the loopback adapter (i.e. a network interface that returns outgoing network traffic back to the same machine).

The ASP.NET Core Module (as shown in Figure 7) is a native IIS module that handles native IIS requests between IIS and the in-process IIS HTTP Server or Kestrel.

Using IIS Express In-Process without Kestrel
Figure 7. - Using IIS Express In-Process without Kestrel (Source).

To run IIS Express as an in-process HTTP server in Visual Studio 2019, follow the steps described below:

  • Select “IIS Express” as shown in Figure 2 and then start running the application.
  • In the Output window of Visual Studio 2019 (Figure 8) we can see that IIS Express in started as part of our application and that our web application is served on http://localhost:52711/ and https://localhost:44390/.
  • Our default browser will be opened with https://localhost:44390/weatherforecast.
  • We can see details about the request/response by opening the Developer-Tools by clicking F12 and then reloading the page (F5). Then, depending on your browser, open the network tab to see that the server response header is “Microsoft-IIS/10.0” as shown in Figure 9.
Output example when running IIS Express as an in-process HTTP server.
Figure 8. - Output example when running IIS Express as an in-process HTTP server.
The response server header when using IIS Express as an in-process HTTP server.
Figure 9. - The response server header when using IIS Express as an in-process HTTP server.

Using IIS Express Out-of-Process

Using out-of-process host, the ASP.NET Core application runs in a process separate from the IIS worker process, using the Kestrel server instead of the IIS HTTP Server (IISHttpServer) as shown in Figure 10. The ASP.NET Core Module handles the process management. The module starts the process of the ASP.NET Core application when the first request arrives and restarts the application if it shuts down or crashes.

Using IIS Express out-of-process using the Kestrel server.
Figure 10. - Using IIS Express out-of-process using the Kestrel server (Source).

To configure an application to run in out-of-process hosting:

  • Select “IIS Express” as shown in Figure 2.
  • Double click on the project name (in Solution explorer) e.g. “TutorialWebApi” to open the project file (.csproj).
  • Set the value of the <AspNetCoreHostingModel> property to OutOfProcess (as shown in the following example). The value of <AspNetCoreHostingModel> is case insensitive, so the valid values are “inprocess” and “outofprocess”.
<Project Sdk="Microsoft.NET.Sdk.Web">
	<Project Sdk="Microsoft.NET.Sdk.Web">
	<PropertyGroup>
		<TargetFramework>netcoreapp3.1</TargetFramework>
		<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
	</PropertyGroup>
</Project>
  • Start running the application.
  • In the Output window of Visual Studio 2019 (Figure 11) we can see that our web application is served on http://127.0.0.1:3059 (the port number it will be different in each run).
  • But, our default browser will be opened with https://localhost:44390/weatherforecast.
  • We can see details about the request/response by opening the Developer-Tools by clicking F12 and then reloading the page (F5). Then, depending on your browser, open the network tab to see that the server response header is “Kestrel” as shown in Figure 12.
  • Note that the “internal” URL (http://127.0.0.1:3059) cannot be directly accessed. In such a case we will get an HTTP 400 Error and we will see the following error in the Output window “fail: Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware[0]” (see Figure 11).
Output example when running IIS Express as an out-of-process HTTP server.
Figure 11. - Output example when running IIS Express as an out-of-process HTTP server.
Figure 12: The response server header when using IIS Express as an out-of-process HTTP server.
Figure 12. - The response server header when using IIS Express as an out-of-process HTTP server.

API Controller Code Structure

The generated API controller “HelloWorldController.cs” provides a scaffold for the basic REST CRUD operations. As we have seen in .NET Nakama (2020, August) REST is an architectural style that is based on using simple URL and by using the four different HTTP verbs (GET, POST, PUT, and DELETE) to perform actions.

The ApiController URL (Routing)

Let’s start by changing the “Get()” function in the “HelloWorldController.cs” file, to return the array “string[] { “Hello”, “World!” }” (see Figure 13 ). Now, run the application in your preferred hosting model option. Your default browser will be opened with the URL https://localhost:44390/weatherforecast. This is the default of the “ASP.NET Core Web Application” template. We will learn how to change this option in a future article.

For now, we have to be able to understand from our code, in which URL our API is running. From the “[Route(“api/[controller]”)]” attribute we see that our API URL (after our domain name) with start with “api/” and it will have a “[controller]”, which will be the controller class name, minus the “Controller” suffix (if suffix exists). Figure 13 presents how the API URL is created based on the controller name. In the “Route” attribute we are defining the base path for this controller. So, our API URL will be:

https://localhost:44390/api/helloworld
The API URL creation based on the controller name.
Figure 13. - The API URL creation based on the controller name.

Read Resources (GET)

To read-return data from our API, the GET HTTP verb will be used. ASP.NET Core provides the “HttpGet” attribute, in which we can set a route template to the base route. In Figure 14 we can see two examples of the GET resources:

  • To GET a list of all resources.
    • The “[HttpGet]” attribute did not have a route template. So, the URL will be the same as the base routes URL.
    • For that reason, in our previous section (Figure 13) the array { “Hello”, “World!” } was returned by using the controller’s base URL.
  • To GET details of a specific resource by providing its id.
    • In the “[HttpGet(“{id}”)]” attribute, the “{id}” is a placeholder variable that will provide the value of "{id}" from the URL to the method in its id parameter.
    • The defined route template “{id}” will be appended to the base route URL, for example, https://localhost:44390/api/helloworld/5
    • We have to keep in mind that the name of the placeholder variable (e.g. “{id}”) will have to match with the name of the method parameter (e.g. “id”).
    • Let’s change the code a bit, to the return the provided id from URL (to see that everything is working). Stop and Start the application and provide different numbers in the URL.
Getting a list of resources or a specific one by its id.
Figure 14. - Getting a list of resources or a specific one by its id.

Create Resource (POST)

To create a resource (e.g. customer, product, order, etc.) the POST HTTP verb is used. For that purpose, the ASP.NET Core provides the “HttpPost” attribute. Figure 15, shows the scaffold generated code to create a resource via POST.

  • The “[HttpPost]” attribute did not have a route template. So, the URL will be the same as the base routes URL.
  • In the method parameter there is something new… the “[FromBody]” attribute. By using the “FromBody” at the “string value”, the request body will be bind to the “value” variable as a string.
  • Now we can write the actual code that creates the resource depending on our application. The most common case is to create-add the resource in a database.
The scaffold generated code to create a resource via POST.
Figure 15. - The scaffold generated code to create a resource via POST.

We can bind incoming data from other sources, such as:

  • [FromQuery]: Gets values from the query string.
  • [FromForm]: Gets values from posted form fields.
  • [FromHeader]: Gets values from HTTP headers.

Update-Replace Resource (PUT)

Updating-Replacing a resource takes effect to the whole resource data and not a part of it (e.g. the whole customer and not only the last name). For such cases, the PUT HTTP verb is used. The related ASP.NET Core attribute is the “HttpPut”. Figure 16, shows the scaffold generated code to update-replace a resource via PUT.

  • To update-replace the value of a specific resource we would need two things, a) the identifier (id) of the resource that we will update-replace and b) the new value.
  • In the “[HttpPut(“{id}”)]” attribute, the “{id}” is a placeholder variable that will provide the value of "{id}" in the URL to the method in its id parameter.
  • The defined route template “{id}” will be appended to the base route URL, for example, https://localhost:44390/api/helloworld/5
  • Using the “[FromBody]” attribute we are binding the request body to the “value” variable as a string.
  • Now we can write the actual code that update-replace the resource depending on our application.
The scaffold generated code to update-replace a resource via PUT.
Figure 16. - The scaffold generated code to update-replace a resource via PUT.

Delete Resource (DELETE)

To delete a specific resource the DELETE HTTP verb is used. ASP.NET Core provides the “HttpDelete” attribute for that purpose. Figure 17, shows the scaffold generated code to delete a resource via DELETE.

  • To delete a specific resource we would only need its identifier (id).
  • In the “[HttpDelete(“{id}”)]” attribute, the “{id}” is a placeholder variable that will provide the value of "{id}" in the URL to the method in its id parameter.
  • The defined route template “{id}” will be appended to the base route URL, for example, https://localhost:44390/api/helloworld/5
  • In the brackets we can write the actual code that deletes the resource depending on our application.
The scaffold generated code to delete a resource via DELETE.
Figure 17. - The scaffold generated code to delete a resource via DELETE.

Summary

This article starts by creating a dummy scaffolded API Controller with CRUD operations, which we will improve step-by-step in the following articles. However, we have investigated the generated code structure of an API controller in relation to the CRUD operations. We learned how to specify and get the identifier of a resource from the URL and how to bind the request body to an object parameter. In addition, we saw the need to validate our input data, in such a manner that would be centralized and reusable, in order to provide consistent API response errors.

Visual Studio provides several ways to run-serve an ASP.NET Core Web API project depending on our platform and hosting model preferences (in-process or out-of-process). We have investigated the differences between these options to have a better understanding of its selection. This is very helpful to run our application locally as in our selected deployment hosting model.

If you liked this article (or not), do not hesitate to leave comments, questions, suggestions, complaints, or just say Hi in the section below. Don't be a stranger 😉!

Dont't forget to follow my feed and be a .NET Nakama. Have a nice day 😁.