---
marp: true
paginate: true
math: mathjax
theme: buutti
title: 1. Introduction to ASP.NET
---

# Introduction to ASP.NET

<!-- headingDivider: 5 -->
<!-- class: invert -->

## Getting started with ASP.NET

### ASP.NET

* ASP.NET is a server-side framework developed by Microsoft
* Introduced in 2002
* Successor to Microsoft's Active Server Pages (ASP) technology
* Runs on the .NET platform, and can use all .NET supported programming languages
* A framework for building Internet-connected applications, like
  * Web apps
  * Web APIs
  * Backend for desktop & mobile apps

### ASP.NET Core

* *__ASP.NET Core__* is a complete redesign & rewrite of ASP.NET
  * Introduced in 2016
  * Initially ran on both versions of .NET (Framework and Core)
  * .NET Framework support was eventually dropped
* Open source, cross-platform
* Enhanced security compared to ASP.NET
* We will be focusing on Web APIs and won't be covering the frontend development tools of ASP.NET

<!-- APIs are interfaces that applicaitons use to communicate with each other
Xamarin for mobile
Use of NuGet packages add modularity and decrease the minimum memory footprint of your projects -->

#### Why use ASP.NET Core?

* As a .NET application, supports *__NuGet packages__* that can be added to your projects modularly
* Full support for C#
  * Base Class Library
  * Great community support
    * StackOverflow
    * Open projects on GitHub
* Some companies have a long history with Microsoft frameworks
  * ASP.NET is the logical choice in that case
* .NET is constantly getting updates and new releases
  * Learn to read [the documentation](https://learn.microsoft.com/en-us/aspnet/core/?view=aspnetcore-9.0)!

### Swagger & Swagger UI

<div class='columns32' markdown='1'>
<div markdown='1'>

* [Swagger](https://swagger.io/) (now [OpenAPI](https://swagger.io/docs/specification/v3_0/about/)) is a language-independent specification for describing REST APIs without needing to look at the source code
* [Swagger UI](https://swagger.io/tools/swagger-ui/): Web-based UI for automatically providing information about the API (actions and their capabilities) using the specification above
* The default implementation of Swagger UI in ASP.NET is called  [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) (see [docs](https://learn.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-7.0
))
* Useful for basic debugging and testing

</div>
<div markdown='1'>

![](imgs/2-aspnet-core-basics_0.png)

</div>
</div>

### Exercise 1: Creating an ASP.NET Core Web Application
<!--_class: "exercise invert" -->

1) Open Visual Studio and from the right select *Create a new project*
2) Search for *ASP.NET* and select _ASP.NET Core Web API_ ***(NOTE: Not Web App!)***

<div class='columns12' markdown='1'>
<div markdown='1'>

![](imgs/2-aspnet-core-basics_2.png)

</div>
<div markdown='1'>

![](imgs/2-aspnet-core-basics_1.png)

</div>
</div>

---

<!--_class: "exercise invert" -->

3) Give a *Project name* and set a *Location* for the repository, and check *Place solution and project in the same directory*. Click *Next* in the bottom right corner.
4) Select *.NET 9.0* under *Framework*. *Authentication type* should be *None* for now. Uncheck *Configure for HTTPS*. Click *Create* in the bottom right corner.

<div class='columns' markdown='1'>
<div markdown='1'>

![](imgs/2-aspnet-core-basics_3.png)
* ***Note:***  *Configure for HTTPS* would enforce HTTPS for added security (see [docs](https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-9.0&tabs=visual-studio%2Clinux-sles))

</div>
<div markdown='1'>

![](imgs/2-aspnet-core-basics_4.png)

</div>
</div>


---

<!--_class: "exercise invert" -->

5) Add [Swagger](https://learn.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-8.0&tabs=visual-studio
) to your project. Go to *View > Other Windows > Package Manager Console* and run the following command:
    ```
    Install-Package Swashbuckle.AspNetCore -Version 6.6.2
    ```

![](imgs/2-aspnet-core-basics_4_1.png)

---

<!--_class: "exercise invert" -->

6) Make sure `Program.cs` includes the following lines:
    ```csharp
    builder.Services.AddControllers();

    builder.Services.AddEndpointsApiExplorer(); // add this
    builder.Services.AddSwaggerGen();           // add this

    // ...

    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();                       // add this
        app.UseSwaggerUI();                     // add this
        app.MapOpenApi();
    }
    ```

---

<!--_class: "exercise invert" -->

7) Start debugging from the top (the ▶ button with the text *http*).
   * Click *Yes* twice to trust the certificates.

![](imgs/2-aspnet-core-basics_5.png)

8) Open the Swagger UI in a web browser by going to `http://localhost:<port>/swagger`.
   * The port number is shown on the debug console window that should now be open.
![](imgs/2-aspnet-core-basics_4_2.png)

---

<!--_class: "exercise invert" -->

9) A web page should open, showing SwaggerUI for a weather forecast API. Click it open 🔽.
10) Click *Try it out*, and 11. *Execute* the **GET** request and see what it returns.

<div class='columns' markdown='1'>
<div markdown='1'>

![](imgs/2-aspnet-core-basics_7.png)

</div>
<div markdown='1'>

![](imgs/2-aspnet-core-basics_6.png)
![](imgs/2-aspnet-core-basics_8.png)

</div>
</div>

---

<!--_class: "exercise invert" -->

12) Close the window. Browse through the source files on Solution Explorer on the right and check where the weather forecasts come from.

<div class='centered'>

![w:600](imgs/2-aspnet-core-basics_9.png)

</div>

### ASP.NET Core Web API contents

* In the previous exercise, we chose an API template for our new project, which have some files and dependencies already added
* The weather forecasts come from `WeatherForecastController.cs` in the *Controllers* folder
  * (More on Controllers later...)
* Throughout this training, the aim is to get an understanding of the underlying logic of ASP.NET Core
* You can use the API template for the assignments, though

## The heart of the server: `Program.cs`

### A default server program

* The `Program.cs` file in ASP.NET 7 is where the ***services*** for the web application are configured and the ***middleware*** is defined
* The file starts with defining the builder for the web application
  ```csharp
  var builder = WebApplication.CreateBuilder(args);
  ```
* The program is actually a console application that also hosts a web server
* The default server in ASP.NET applications is [Kestrel](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-9.0) (lightweight, cross-platform)
  * The old default is [IIS](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-9.0) (Windows-specific, nowadays used as a [reverse proxy](https://en.wikipedia.org/wiki/Reverse_proxy) server)

### Services

* The controllers and some other components (like Swagger) are added to the application as ***services***
  * Services are components that are available anywhere within your program via *dependency injection* (introduced in [C# Basics Lecture 15](https://gitea.buutti.com/education/csharp-basics/src/branch/main/15-design-patterns-in-csharp.md))

  ```csharp
  // Add services to the container.

  builder.Services.AddControllers();
  builder.Services.AddEndpointsApiExplorer();
  builder.Services.AddSwaggerGen();
  ```
* As the comment above suggests, more services can be added as needed

### Middlewares

* Handling of each HTTP request is defined as a set of [middlewares](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-9.0)
* Middleware is a software that's added into the middle of an app pipeline to handle requests and responses
* Middleware can decide whether to modify the data/request as needed, and pass the request into the next middleware
  ```csharp
  if (app.Environment.IsDevelopment()){
    app.UseSwagger();
    app.UseSwaggerUI();
    app.MapOpenApi();
  }
  app.UseAuthorization();
  app.MapControllers();
  app.Run();
  ```

## An example controller: `WeatherController.cs`

### Routing and endpoints

* *__Routing__* is how web APIs match the requested URI to a corresponding action
* The URIs that can be used to get a response from the API are called the *__endpoints__* of the API

| Request method | Endpoint                               | Action               |
|:---------------|:---------------------------------------|:---------------------|
| `GET`          | `http://someserver.com/api/products`   | `GetProducts()`      |
| `GET`          | `http://someserver.com/api/products/3` | `GetProduct(int id)` |
| `POST`         | `http://someserver.com/api/products`   | `PostProduct()`      |

### Attributes

* ***Attributes*** ([see C# Basics: Lecture 15](/education/csharp-basics/src/branch/main/15-design-patterns-in-csharp.md#attributes)) are a way of attaching metadata to entities (classes, methods, properties, etc.)
* In ASP.NET, attributes have a strong role in *__routing__*:
  ```csharp
  [ApiController]           // Attribute routing requirement,
                            // automatic HTTP 400 response, and more

  [Route("[controller]")]   // URIs with "/weatherforecast" are routed to this class
  public class WeatherForecastController : ControllerBase
  {
    //...
    [HttpGet]               // HTTP GET requests are routed to this method
    public IEnumerable<WeatherForecast> Get()
    {
      //...
    }
  }
  ```

### Attribute Routing

|                   | Attribute                                        | Request                                      |
|:------------------|:-------------------------------------------------|:---------------------------------------------|
| Class:<br>Method: | `[Route("api")]`<br>`[HttpGet]`                  | `GET <localhost>/api`             |
| Class:<br>Method: | `[Route("api")]`<br>`[HttpGet("products")]`      | `GET <localhost>/api/products`    |
| Class:<br>Method: | `[Route("api")]`<br>`[HttpGet("products/{id}")]` | `GET <localhost>/api/products/12` |
| Class:<br>Method: | `[Route("api")]`<br>`[HttpPost("products")]`     | `POST <localhost>/api/products`   |

### Exercise 2: Setting up Routes
<!--_class: "exercise invert" -->

1) Change the routes in `WeatherForecastController.cs` so that the forecast result is printed at
  `http://localhost:<port>/api/weatherforecast`
instead of
  `http://localhost:<port>/weatherforecast`

You can see the route change in the Swagger UI `GET` method.

### Handling `HttpGet` Requests

* We have now established how to call methods with HTTP requests
* Additional parameters can be passed to the method with the URI:
  ```csharp
  [Route("api")]
  // class declaration
  // ...

  [HttpGet("list/{someText}")]
  public string[] GetArrayOfStrings(string someText)
  {
    return Enumerable.Range(1, 5).Select(index => new string(someText))
      .ToArray();
  }
  ```

<div class='centered'>

![w:400](imgs/2-aspnet-core-basics_10.png)

</div>

---

* The URI parameters can be made optional with '?'
* A default value must be then set for the method parameter:
  ```csharp
  [Route("api")]
  // class declaration
  // ...

  [HttpGet("list/{someText?}")]
  public string[] GetArrayOfStrings(string someText = "default")
  {
    return Enumerable.Range(1, 5).Select(index => new string(someText))
      .ToArray();
  }
  ```

<div class='centered'>

![](imgs/2-aspnet-core-basics_11.png)

</div>

---

* Apply constraints for the parameters by setting them after `:`
* If the URI doesn't fit the constraints, the response will hold a `404` status code
  ```csharp
  [HttpGet("products/{id:int}")]              // Required type: int
  [HttpGet("list/{value:length(3,40)}")]      // Required length: 3-40
  ```

<div class='centered'>

![](imgs/2-aspnet-core-basics_12.png)

</div>

### Exercise 3: Returning Your Own List
<!--_class: "exercise invert" -->

1) Change the `GET` method so that instead of returning an `IEnumerable` of `WeatherForecast` objects, it returns a `List` of `string` objects.
   * Fill the list with e.g. names and make it as long as you want. Test with browser (Swagger UI).
2) Create a new method routed at `http://localhost:<port>/api/numberlist/k`, where `k` is any integer. The method should return an array of integers from `1` to `k`.
   * For example, `http://localhost:<port>/api/numberlist/5` would return `[1,2,3,4,5]`. Test with browser (Swagger UI).

## Sending requests with Postman

### Postman

* HTTP `POST` requests cannot be made with the browser's address bar, only `GET`!
* In websites, `POST` requests are usually made with forms
* In applications, all requests are sent by the client application
* For testing APIs, multiple tools like [Postman](https://www.postman.com/) or [Insomnia](https://insomnia.rest/) exist
* Before we cover handling `POST`, `PUT` and other requests in ASP.NET, let's first see how to make them with Postman

<div class='centered'>

![w:500](imgs/2-aspnet-core-basics_13.png)

</div>

### Benefits of using Postman

* When developing APIs, tools like Postman will almost always surface in the development cycle
* Postman lets you create configured HTTP requests to APIs, and save them to a JSON file
* This is great for testing your APIs without having to write code just for that purpose
* Supports all the necessary HTTP requests, like `GET`, `POST`, `PUT` and `DELETE`

### Exercise 4. Creating requests with Postman
<!--_class: "exercise invert" -->

Run the Weather API program, and test both methods with Postman.

1) To get started, open Postman (You can sign in or skip the login)
   * Close the opened window to go straight to making requests

<div class='centered'>

![w:800](imgs/2-aspnet-core-basics_14.png)

</div>

---
<!--_class: "exercise invert" -->

<div class='columns23' markdown='1'>
<div markdown='1'>

2) Create your request by selecting the method and entering the URL
3) The response with the content body and status code show up below!

</div>
<div markdown='1'>

![](imgs/2-aspnet-core-basics_15.png)

</div>
</div>