Create and Run a Hello World, CRUD Web API
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.
- 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
- In the same process (by default) as the IIS worker process (the in-process hosting model) using the IIS HTTP Server, or
- In a process separate from the IIS worker process (the out-of-process hosting model) using the Kestrel server.
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.
- 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.
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 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.
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.
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.
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”.
- 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).
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
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 itsid
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.
- In the “[HttpGet(“{id}”)]” attribute, the “{id}” is a placeholder variable that will provide the value of
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.
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 itsid
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.
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 itsid
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.
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 😁.