Book Image

ASP.NET Core 5 for Beginners

By : Andreas Helland, Vincent Maverick Durano, Jeffrey Chilberto, Ed Price
Book Image

ASP.NET Core 5 for Beginners

By: Andreas Helland, Vincent Maverick Durano, Jeffrey Chilberto, Ed Price

Overview of this book

ASP.NET Core 5 for Beginners is a comprehensive introduction for those who are new to the framework. This condensed guide takes a practical and engaging approach to cover everything that you need to know to start using ASP.NET Core for building cloud-ready, modern web applications. The book starts with a brief introduction to the ASP.NET Core framework and highlights the new features in its latest release, ASP.NET Core 5. It then covers the improvements in cross-platform support, the view engines that will help you to understand web development, and the new frontend technologies available with Blazor for building interactive web UIs. As you advance, you’ll learn the fundamentals of the different frameworks and capabilities that ship with ASP.NET Core. You'll also get to grips with securing web apps with identity implementation, unit testing, and the latest in containers and cloud-native to deploy them to AWS and Microsoft Azure. Throughout the book, you’ll find clear and concise code samples that illustrate each concept along with the strategies and techniques that will help to develop scalable and robust web apps. By the end of this book, you’ll have learned how to leverage ASP.NET Core 5 to build and deploy dynamic websites and services in a variety of real-world scenarios.
Table of Contents (19 chapters)
1
Section 1 – Crawling
7
Section 2 – Walking
12
Section 3 – Running

Understanding websites and web servers

Web servers are an important part of ASP.NET apps since they, by definition, require one to be present to run. It is also the major contributor to the "it works on my machine" challenge for web apps (where it works on your machine, but it doesn't work for your customers).

The history of .NET has been closely linked to the web server being Internet Information Services (IIS). IIS was released several years before .NET, but support for .NET was added in a later version. For a web application to work, there are external parts that need to be in place that are not handled by the code the developer writes. This includes the mapping of a domain name, certificates for encrypting data in traffic, and a range of other things. IIS handles all of these things and more. Unfortunately, this also means that creating an optimal configuration might require more knowledge of server and networking topics than the average .NET developer would have.

IIS is designed to run on a server operating system, and since Visual Studio can be installed on Windows Server, it is entirely possible to set up a production-grade development environment. Microsoft also ships a reduced version called IIS Express as part of Visual Studio that enables you to test ASP.NET apps without installing a server operating system.

IIS Express can do most of the things the developer needs to test ASP.NET apps, with the most important difference being that it is designed for handling local traffic only. If you need to test your web app from a different device than the one you are developing on, IIS Express is not designed to enable that for you.

We will present a couple of configuration components you should be aware of as well as utilities and methods for troubleshooting web-based applications.

Web server configuration

While this book targets developers, there are some things regarding web servers that are valuable to understand in case you need to have a conversation with the people responsible for your infrastructure.

When developing web apps, it is necessary to be able to read the traffic, and it is common that one of the things one does to make this easier is running the app over plain HTTP, allowing you to inspect traffic "over the wire." You should never run this in production. You should acquire TLS/SSL certificates and enable HTTPS for production, and ideally set up your local development environment to also use HTTPS to make the two environments comparable. Visual Studio enables the automatic generation of a trusted certificate that you need to approve once for the initial setup so this should be fairly easy to configure.

Certificate trust

Certificates are issued from a Public Key Infrastructure (PKI) that is built in a hierarchical manner, typically with a minimum of three tiers. For a certificate to be valid, the client device needs to be able to validate this chain. This is done on multiple levels:

  • Is the root Certificate Authority (CA) trusted? This must be installed on the device. Typically, this is part of the operating system with common CAs pre-provisioned.
  • Is the certificate issued to the domain you host your site on? If you have a certificate for northwind.com, this will not work if your site runs at contoso.com.
  • Certificates expire so if your certificate expires in 2020, it will fail to validate in 2021.

There is no easy way for you as a developer to make sure that users accessing your site have the clock configured correctly on their device, but at least make sure the server is set up as it should be.

Session stickiness

Web apps can be stateful or stateless. If they are stateful, it means there is a sort of dialogue going on between the client and the server, where the next piece of communication depends on a previous request or response. If they are stateless, the server will answer every request like it is the first time the two parties are communicating. (You can embed IDs in the request to maintain state across stateless sessions.)

In general, you should strive to make sessions stateless, but sometimes you cannot avoid this. Say you have the following record class:

public data class City {int ZipCode; string Name;}

You have also taken the time to create a list of the top 10 (by population) cities in every state and expose this through an API. The API supports looking up the individual zip code or name, but it also has a method for retrieving all records. This is not a large dataset, but you do some calculations and figure out that you should only send 100 records at a time to not go over any limits for HTTP packet size limitations.

There are multiple ways to solve this. You could write in the docs that the client should append a start and end record (with the end assumed to be start +99 if omitted):

https://contoso.com/Cities?start=x&end=y

You could also make it more advanced by calculating a nextCollectionId parameter that is returned to the client, so they could loop through multiple calls without recalculating start and end:

https://contoso.com/Cities?nextCollectionId=x

There is however a potential issue here occurring on the server level you need to be aware of.

Since your API is popular, you need to add a second web server to handle the load and provide redundancy. (This is often called a web farm and can scale to a large number of servers if you need to.) To distribute the traffic between the two, you put a load balancer in front of them. What happens if the load balancer directs the first request to the first web server and the second request to the second server?

If you don't have any logic to make the nextCollectionId available to both servers, it will probably fail. For a complex API serving millions of requests, you should probably invest time in implementing a solution that will let the web servers access a common cache. For simple apps, what you are looking for might be session stickiness. This is a common setting on load balancers that will make a specific client's requests stick to a specific web server instance, and it is also common that you need to ask the person responsible for the infrastructure to enable it. That way, the second request will go to the same web server as the first request and things will work as expected.

Troubleshooting communication with web servers

You will eventually run into scenarios where you ask yourself why things are not working and what actually goes on with the traffic. There are also use cases where you are implementing the server and need a quick way to test the client side without implementing a client app. A useful tool in this regard is Fiddler from Telerik, which you can find at https://www.telerik.com/fiddler.

This will most likely be useful in subsequent chapters, so you should go ahead and install it now. By default, it will only capture HTTP traffic, so you need to go to Tools | Options | HTTPS and enable the checkmark for Capture HTTPS CONNECTs and Decrypt HTTPS traffic as shown:

Figure 1.9 – Fiddler HTTPS capture settings

Figure 1.9 – Fiddler HTTPS capture settings

A certificate will be generated that you need to accept installing and then you should be able to listen in on encrypted communication as well.

This method is technically what is known as a man-in-the-middle attack, which can also be used with malicious intent. For use during your own development, this is not an issue, but for production troubleshooting, you should use other mechanisms to capture the info you need. The web application will be able to intercept the valid traffic it receives (that it has the certificate for decoding), but with a tool capturing at the network level, you'll potentially collect extra info you should not have.

Fiddler can also be used for crafting HTTP requests manually, so it is a useful utility even if you're not chasing down bugs:

Figure 1.10 – Fiddler HTTP request constructor

Figure 1.10 – Fiddler HTTP request constructor

If it is an error you are able to reproduce yourself by clicking through the website, Visual Studio is your friend. You have the Output window, which will provide process-level information:

Figure 1.11 – Visual Studio output window

Figure 1.11 – Visual Studio output window

Troubleshooting is often complicated and rarely fun but looking directly at the protocol level is a useful skill to have when dealing with web applications, and these tools should help you along the way to resolving your issues.

Choosing a web server option

As noted, IIS Express is included by default in Visual Studio 2019, and if the code you are developing is intended to run on a windows server with the full version of IIS, it is a good choice. However, there are some drawbacks to IIS Express as well:

  • While requiring less overhead than the full IIS, it is "heavy," and if you find yourself running debugging cycles where you constantly start and stop the web server, it can be a slow process.
  • IIS Express is a Windows-only thing. If your code runs on Linux (which is a real scenario with the cross-platform support in .NET Core), it is not available as an option.
  • If you are writing code for containers/microservices, the full IIS adds up to a lot of overhead when you have multiple instances each running their own web server. (With microservices, you usually don't co-locate multiple websites on a web server, which is what IIS is designed for.)

To support more scenarios, .NET Core includes a slimmed-down and optimized web server called Kestrel. Going back to the Hello World web app we created earlier in the chapter, you can open a command line to the root folder and execute the command dotnet run:

Figure 1.12 – Output of dotnet run

Figure 1.12 – Output of dotnet run

If you open the browser to https://localhost:5001, it should be the same as launching IIS Express from Visual Studio.

You don't have to step into the command line to use Kestrel. You can have multiple profiles defined in Visual Studio – both are added by default. By installing a Visual Studio extension called .NET Core Debugging with WSL2, you can also deploy directly to a Linux installation. (Linux configuration will be covered in Chapter 2, Cross-Platform Setup.) You can edit the settings manually by opening launchSettings.json:

{

  "iisSettings": {

    "windowsAuthentication": false,

    "anonymousAuthentication": true,

    "iisExpress": {

      "applicationUrl": "http://localhost:65476",

      "sslPort": 44372

    }

  },

  "profiles": {

    "IIS Express": {

      "commandName": "IISExpress",

      "launchBrowser": true,

      "environmentVariables": {

        "ASPNETCORE_ENVIRONMENT": "Development"

      }

    },

    "Chapter_01_HelloWorld": {

      "commandName": "Project",

      "launchBrowser": true,

      "applicationUrl": "https://localhost:5001;          http://localhost:5000",

      "environmentVariables": {

        "ASPNETCORE_ENVIRONMENT": "Development"

      },

    "WSL 2": {

      "commandName": "WSL2",

      "launchBrowser": true,

      "launchUrl": "https://localhost:5001",

      "environmentVariables": {

        "ASPNETCORE_URLS":

        "https://localhost:5001;http://localhost:5000",

        "ASPNETCORE_ENVIRONMENT": "Development"

      }

    }

  }

}

This file is only used for development purposes on your machine and is not the configuration used for production.

For production use, Kestrel and IIS are the main options. Which one to use depends on where and what you are deploying to. For on-premises scenarios where you have Windows servers, it is still a viable option to deploy to IIS. It comes with useful features out of the box – if you, for instance, want to restrict the app to users that have logged in to Active Directory, you can enable this in IIS without modifying your code. (For fine-grained access control, you will probably want some mechanisms in the code as well.)

If you deploy to containers, Kestrel is an easier path. However, you should not deploy to Kestrel without an ecosystem surrounding it. Kestrel "lives with the code" – there is no administration interface that you can configure when the code is not running. This means that activities such as managing certificates are not covered out of the box. If you deploy to a cloud environment, that usually means you will bring in other components to cover what Kestrel itself does not. Certificate handling is provided either by the container host or a separate service you place in front of the web server.

Now that we have understood the importance of websites and web servers in ASP.NET apps, let's move on and dive into Visual Studio Code.