You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
aspnet-basics/1-aspnet-introduction.md

417 lines
14 KiB
Markdown

---
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>