Merge branch 'dotnet:main' into 5-Blazor
244
3-razor-pages/README.md
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
# Build a pizza website with Razor Pages
|
||||
|
||||
Welcome back! In the last lesson, you got a crash course in C# language fundamentals. Now, you'll get to put those skills to use and build a website using ASP.NET Core and Razor Pages!
|
||||
|
||||
## What's ASP.NET Core?
|
||||
|
||||
.NET is pretty magical, because you can build all kinds of apps with it – mobile apps, games, desktop apps, web apps, and more. ASP.NET Core is a .NET toolkit for building web sites, apps, and services with .NET.
|
||||
|
||||
## Okay, so what are Razor Pages?
|
||||
|
||||
There are a few different kinds of web apps out there. If you’re building highly interactive web apps – like a game or in-browser experience – you would probably want to use Blazor. You’ll learn about that in Week 5. But the huge majority of web sites out there run most of their logic on the server - think shopping and commerce websites, web sites for small businesses and portfolios, news sites, etc. And that’s what Razor Pages is really good at.
|
||||
|
||||
In Razor Pages applications, you’ll write your logic in a Page Model class, and you’ll write your markup in a Razor file. Razor is a nifty language that blends HTML markup with C# logic, so you can pull in your dynamic information from your Page Model class and display it in Razor. If that sounds complicated, don’t worry, because you’re about to see how easy it is to write a simple Pizza store web app using Razor Pages.
|
||||
|
||||
## Installing the tools
|
||||
|
||||
We'll be using Visual Studio 2022 for whole course. If you don't have Visual Studio 2022 installed, you can follow the [directions here](/1-welcome/how-to-install-vs.md).
|
||||
|
||||
## Creating a Razor Pages project
|
||||
|
||||
1. Start Visual Studio 2022 and select **Create a new project**.
|
||||
|
||||

|
||||
|
||||
1. In the **Create a new project** dialog, select **ASP.NET Core Web App**, and then select **Next**.
|
||||
|
||||

|
||||
|
||||
1. In the **Configure your new project** dialog, enter `RazorPagesPizza` for **Project name**. It's important to name the project *RazorPagesPizza*, including matching the capitalization, so the namespaces will match when you copy and paste example code.
|
||||
|
||||

|
||||
|
||||
1. Select **Next**.
|
||||
|
||||
1. In the **Additional information** dialog, select **.NET 6.0 (Long-term support)** and then select **Create**.
|
||||
|
||||

|
||||
|
||||
The following starter project is created:
|
||||
|
||||

|
||||
|
||||
## Setting up our model class
|
||||
|
||||
In the **Project** menu, select **New Folder**. Name the folder **Models**.
|
||||
|
||||
With the **Models** folder still selected in the Solution Explorer, select **Project** -> **Add Class...** from the menu. Name the new class **Pizza.cs** and click the **Add** button.
|
||||
|
||||
In the **Pizza.cs** file, add the following code:
|
||||
|
||||
```csharp
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace RazorPagesPizza.Models;
|
||||
|
||||
public class Pizza
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[Required]
|
||||
public string? Name { get; set; }
|
||||
public bool IsGlutenFree { get; set; }
|
||||
|
||||
[Range(0.01, 9999.99)]
|
||||
public decimal Price { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
Before proceeding to the next step, build the project by selecting **Build Solution** from the **Build** menu.
|
||||
|
||||
## Scaffolding our Razor Pages project
|
||||
|
||||
Right-click on the **Pages** directory in the Solution Explorer, and select **Add** -> **New Scaffolded Item...**.
|
||||
|
||||
> NOTE: It is important that you right-click the **Pages** directory when you add a new scaffolded item. This is because the **Pages** directory is a special folder in the Solution Explorer that contains all of the Razor Pages files.
|
||||
|
||||

|
||||
|
||||
In the **Add New Scaffold Item** dialog, select **Razor Pages**, **Razor Pages using Entity Framework (CRUD)** and then select **Add**.
|
||||
|
||||

|
||||
|
||||
In the **Add Razor Pages using Entity Framework (CRUD)** dialog, select **Pizza (RazorPagesPizza.Models)** for the model class.
|
||||
|
||||
Click the **+** button to the right of the **Data context class** field. The **New data context type** field will be pre-filled with `RazorPagesPizza.Data.RazorPagesPizzaContext`. Click the **Add** button.
|
||||
|
||||
Verify that the dialog looks like this, then click the **Add** button:
|
||||
|
||||

|
||||
|
||||
You will receive a warning that you are overriding the existing **Index** files. Click the **Yes** button to continue.
|
||||
|
||||

|
||||
|
||||
## Check out the IndexModel class
|
||||
|
||||
Let's take a look at how a sample page in the site works - we'll start with the Index page. As explained earlier, the logic in a Razor Page goes in a Page Model class, and you’ll write your markup in a Razor file. We'll look at how those work, starting with the Index `PageModel`.
|
||||
|
||||
A Razor page's `PageModel` class file defines any page handlers for HTTP requests sent to the page, and data used to render the page. The `PageModel` keeps those concerns separate from the Razor page, your app more modular, and easier to maintain. By convention, the `PageModel` class is named *[PageName]Model* and resides in the same namespace as the Razor page.
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RazorPagesPizza.Data;
|
||||
using RazorPagesPizza.Models;
|
||||
|
||||
namespace RazorPagesPizza
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly RazorPagesPizza.Data.RazorPagesPizzaContext _context;
|
||||
|
||||
public IndexModel(RazorPagesPizza.Data.RazorPagesPizzaContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public IList<Pizza> Pizza { get;set; } = default!;
|
||||
|
||||
public async Task OnGetAsync()
|
||||
{
|
||||
if (_context.Pizza != null)
|
||||
{
|
||||
Pizza = await _context.Pizza.ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A `PageModel` really has two jobs:
|
||||
|
||||
* It assembles all the dynamic content you'll want to show in the page.
|
||||
* It handles all the page interactions, which normally map to HTTP verbs like GET, POST, DELETE, etc.
|
||||
|
||||
The `IndexModel` uses EF Core to work with the database, allowing the `OnGetAsync` method to be pretty short. A database context called `_context` is kind of magically created for us in the class constructor (it's actually using ASP.NET Core's [dependency injection system](https://docs.microsoft.com/aspnet/core/fundamentals/dependency-injection), but it's okay to just treat it as magic for now). EF Core allows us to just work with a C# list of items (our `Pizza` class in this case), and it does the work to synchronize our changes with a database.
|
||||
|
||||
Currently, the `IndexModel` class handles the HTTP GET request with an `OnGetAsync` page handler. You can add handlers for any HTTP verb. The most common handlers are:
|
||||
|
||||
* `OnGetAsync` to initialize state needed for the page.
|
||||
* `OnPostAsync` to handle form submissions. You can see an example in `Create.cshtml.cs`, and learn more about how form submissions work in the references in the **What's Next** section below.
|
||||
|
||||
## And now the Index page's Razor file
|
||||
|
||||
Now that we've got a list of pizzas loaded into a variable (`Pizza` in this case), we can display it in the page. A Razor page supports Razor syntax, which is HTML and C# combined. The C# code defines the dynamic rendering logic for the page on the server. The default Razor language is HTML. Rendering HTML from Razor markup is no different than rendering HTML from an HTML file. HTML markup in .cshtml Razor page files is rendered by the server unchanged. In Razor Pages, HTML can be used as you're used to. At the same time, you can take advantage of powerful and time-saving Razor features as you learn to use them.
|
||||
|
||||
You'll see below that we're transitioning between C# and HTML - starting with some C# to set a few things, then switching over to HTML with our `<h1>` tag. From then on, it's mostly HTML with some dynamic content sprinkled in.
|
||||
|
||||
```csharp
|
||||
@page
|
||||
@model RazorPagesPizza.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
}
|
||||
|
||||
<h1>Index</h1>
|
||||
|
||||
<p>
|
||||
<a asp-page="Create">Create New</a>
|
||||
</p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Pizza[0].Name)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Pizza[0].IsGlutenFree)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Pizza[0].Price)
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.Pizza) {
|
||||
<tr>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Name)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.IsGlutenFree)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Price)
|
||||
</td>
|
||||
<td>
|
||||
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
|
||||
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
|
||||
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
```
|
||||
|
||||
Razor has a pretty lightweight syntax, so if you're familiar with HTML you can start with that and add in dynamic content and logic. There's more information about the [Razor syntax](https://docs.microsoft.com/aspnet/core/mvc/views/) in the docs, of course, and we cover it in a little more detail in the **What's Next** tutorial.
|
||||
|
||||
## Run database migrations
|
||||
|
||||
From the **Tools** menu, select **NuGet Package Manager** > **Package Manager Console**.
|
||||
|
||||

|
||||
|
||||
In the Package Manager Console, or PMC, enter the following commands:
|
||||
|
||||
```powershell
|
||||
Add-Migration InitialCreate
|
||||
Update-Database
|
||||
```
|
||||
|
||||
## Running the web app
|
||||
|
||||
From the **Build** menu, select **Start Debugging**. A console window will open to display debug output, and your browser will open to the web application's URL. It will be something like https://localhost:7242/, where the 7242 is a free port number on your machine.
|
||||
|
||||
You've got a running web application that you built! Let's try it out.
|
||||
|
||||
1. Click the **Create New** link to navigate to the **Create** page. Try to break it by leaving all the fields blank and clicking the **Create** button. You'll see validation errors, which is a good thing!
|
||||
|
||||
1. Enter a valid pizza name (pineapple is allowed!) and price (between 0.01 and 9999.99 - we've got some expensive pizza here) and click the **Create** button.
|
||||
|
||||
1. Play with it a bit by adding a few pizzas and deleting them.
|
||||
|
||||

|
||||
|
||||
## What's next?
|
||||
|
||||
In order to get started quickly, we've kept things as simple as we could, and we've taken advantage of scaffolding to write a lot of code for us. We've got some more advanced tutorials to help you get to the next level, though:
|
||||
|
||||
* [Create a web UI with ASP.NET Core](https://docs.microsoft.com/learn/modules/create-razor-pages-aspnet-core/) will walk you through a very similar Pizza application, but in more detail. You'll learn more about how things are working behind the scenes, and write more of the code by hand.
|
||||
|
||||
* [Create a Razor Pages web app with ASP.NET Core](https://docs.microsoft.com/aspnet/core/tutorials/razor-pages/) goes even deeper, with more advanced data operations like search and adding new fields to your data model.
|
||||
|
||||
## Connect with us
|
||||
|
||||
We're excited to support you on your learning journey! Check out the [.NET Community Page](https://dotnet.microsoft.com/platform/community) to find links to our blogs, YouTube, Twitter, and more.
|
||||
BIN
3-razor-pages/add-scaffold.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
3-razor-pages/additional-info.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
3-razor-pages/config.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
3-razor-pages/new-scaffold-dialog.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
3-razor-pages/np.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
3-razor-pages/overwrite-warning.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
3-razor-pages/pizza-list.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
3-razor-pages/pmc.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
BIN
3-razor-pages/scaffold-settings.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
3-razor-pages/se.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
3-razor-pages/start-window-create-new-project.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
251
4-minimal-api/README.md
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
# Build an HTTP backend with Minimal APIs
|
||||
|
||||
## What is an HTTP API?
|
||||
|
||||
Web servers are often used to serve web pages, but they can also be used to serve other types of data. For example, a web server can be used to provide data for other clients, such as a mobile app, a desktop app, another web server. Sometimes, we'll use front-end single page applications (SPAs) like Angular or React in the browser, but they'll interact with data on the server behind the scenes. Services like these are "Application Programming Interfaces" (APIs), rather than user interfaces like web browsers.
|
||||
|
||||
### HTTP: the instruction set for web APIs
|
||||
|
||||
Suppose the server has a list of pizzas that you want to interact with from your client program. There are some really common things you’ll want to do with a list of data (pizzas in this case) as a programmer:
|
||||
|
||||
- Get a list of all the pizzas
|
||||
- Get the details about one pizza
|
||||
- Add a new pizza to the list
|
||||
- Update the details for a pizza
|
||||
- Remove a pizza from the list
|
||||
|
||||
Because these things are so common, the web was designed with standard commands to handle them: GET, PUT, POST, and DELETE. These are part of the HTTP (short for HyperText Transport Protocol) specification, so anyone building a browser or server knows what to expect. Programmers build APIs for all kinds of things, from operating systems to smart watches to refrigerators, so we often talk about web focused APIs as HTTP APIs.
|
||||
|
||||
### Serialization data with JSON
|
||||
|
||||
To avoid reinventing things over and over, we use some common standards for HTTP APIs. We’ve already talked about HTTP, which handles the commands and communication between clients and servers. Another important thing for HTTP APIs to do in a predictable way is to send data back and forth. The most common way to package up data now is called JSON, short for JavaScript Object Notation. It’s a neat, simple format for packaging up data, but programmers don’t want to spend time converting their information back and forth between properties and classes in their programming language and JSON. This conversion process is called serialization, and fortunately ASP.NET Core can do that for you automatically.
|
||||
|
||||
### Welcome to the internet...
|
||||
|
||||
Another important thing to think about for server exposed to the public internet is security and authorization. Some HTTP APIs require authentication, so only clients with the right credentials can access them. Even public HTTP APIs need to handle security, to manage things like denial of service attacks and exploiting the public APIs to take over the server or get access to information they shouldn’t have. Fortunately, ASP.NET Core can handle things like this for us, too.
|
||||
|
||||
## Keep it simple with Minimal APIs
|
||||
|
||||
By now, you might be thinking that building an API that speaks HTTP, serializes JSON, manages security, etc., is going to be really hard! Fortunately, ASP.NET Core has a really easy way to get started, called Minimal APIs. Believe it or not, this is all you need to build a basic Minimal API:
|
||||
|
||||
```csharp
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var app = builder.Build();
|
||||
app.MapGet("/", () => "Hello World!");
|
||||
app.Run();
|
||||
```
|
||||
|
||||
The first two lines set up the server, the third line returns some information (in this case “Hello World!”), and the fourth line runs it. That third line is called an endpoint, and it just says that whenever a client sends a GET command to our server, it will run some code. We have similar commands for all the other HTTP verbs, so creating a new Pizza on the server would look like this:
|
||||
|
||||
```csharp
|
||||
app.MapPost("/pizzas", (Pizza pizza) => PizzaDB.CreatePizza(pizza));
|
||||
```
|
||||
|
||||
This endpoint accepts a pizza JSON object, turns it into C#, and passes it to a PizzaDB class to save it to a database.
|
||||
|
||||
## Building a Minimal API
|
||||
|
||||
### Create a new Minimal API project
|
||||
|
||||
First, you need to scaffold a project. You've installed .NET 6 and you're ready to go.
|
||||
|
||||
1. Create a web API by running `dotnet new`:
|
||||
|
||||
```bash
|
||||
dotnet new web -o PizzaStore
|
||||
```
|
||||
|
||||
You should see the _PizzaStore_ directory.
|
||||
|
||||
1. Run the app by calling `dotnet run`. It builds the app and hosts it on a port from 5000 to 5300. HTTPS has a port selected for it in the range of 7000 to 7300.
|
||||
|
||||
```bash
|
||||
dotnet run
|
||||
```
|
||||
|
||||
Here's what the output can look like in the terminal:
|
||||
|
||||
```output
|
||||
Building...
|
||||
info: Microsoft.Hosting.Lifetime[14]
|
||||
Now listening on: https://localhost:7200
|
||||
info: Microsoft.Hosting.Lifetime[14]
|
||||
Now listening on: http://localhost:5100
|
||||
info: Microsoft.Hosting.Lifetime[0]
|
||||
Application started. Press Ctrl+C to shut down.
|
||||
info: Microsoft.Hosting.Lifetime[0]
|
||||
Hosting environment: Development
|
||||
info: Microsoft.Hosting.Lifetime[0]
|
||||
Content root path: /<path>/PizzaStore
|
||||
```
|
||||
|
||||
1. In your browser, go to the indicated port. According to the terminal `http://localhost:{PORT}`, you should see the text "Hello World!"
|
||||
|
||||
Congratulations! You've created an API by using a minimal API template.
|
||||
|
||||
## Add automatic API documentation with Swagger
|
||||
|
||||
Use Swagger to ensure that you have a self-documenting API, where the docs change when you change the code. This also builds a really convenient web interface for your API, so you can test out the application as you build it.
|
||||
|
||||
1. Install the *Swashbuckle* package:
|
||||
|
||||
```bash
|
||||
dotnet add package Swashbuckle.AspNetCore
|
||||
```
|
||||
|
||||
1. Next, configure your project to use Swagger. Open _Program.cs_ and add replace it with the following code:
|
||||
|
||||
```csharp
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "PizzaStore API", Description = "Making the Pizzas you love", Version = "v1" });
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "PizzaStore API V1");
|
||||
});
|
||||
|
||||
app.MapGet("/", () => "Hello World!");
|
||||
|
||||
app.Run();
|
||||
```
|
||||
|
||||
This is actually just adding a few lines of code:
|
||||
|
||||
- The `using` statement at the top makes it easier to use the *Swashbuckle* package without having to type out long namespaces for the commands.
|
||||
- The two `builder.Services.Add` lines add the two services that *Swashbuckle* needs to generate the documentation.
|
||||
- The `UseSwagger` and `UseSwaggerUI` lines add the Swagger and Swagger UI endpoints.
|
||||
|
||||
1. Rerun the project and go to the app's address, `http://localhost:{PORT}/swagger`.
|
||||
|
||||
You should see the following output:
|
||||
|
||||

|
||||
|
||||
### Add a Pizza model and service
|
||||
|
||||
First you need some data. To store and manage data, you'll use an in-memory store. For this example, we're just going to use a simple list of pizzas. Don't worry too much about this pizza service, it's just a quick example that holds a list of pizzas so we our API has some data to work with.
|
||||
|
||||
1. Create the file _Db.cs_ and give it the following content:
|
||||
|
||||
```csharp
|
||||
namespace PizzaStore.DB;
|
||||
|
||||
public record Pizza
|
||||
{
|
||||
public int Id {get; set;}
|
||||
public string ? Name { get; set; }
|
||||
}
|
||||
|
||||
public class PizzaDB
|
||||
{
|
||||
private static List<Pizza> _pizzas = new List<Pizza>()
|
||||
{
|
||||
new Pizza{ Id=1, Name="Cheese" },
|
||||
new Pizza{ Id=2, Name="Pepperoni" },
|
||||
new Pizza{ Id=3, Name="Pineapple extravaganza"}
|
||||
};
|
||||
|
||||
public static List<Pizza> GetPizzas()
|
||||
{
|
||||
return _pizzas;
|
||||
}
|
||||
|
||||
public static Pizza ? GetPizza(int id)
|
||||
{
|
||||
return _pizzas.SingleOrDefault(pizza => pizza.Id == id);
|
||||
}
|
||||
|
||||
public static Pizza CreatePizza(Pizza pizza)
|
||||
{
|
||||
_pizzas.Add(pizza);
|
||||
return pizza;
|
||||
}
|
||||
|
||||
public static Pizza UpdatePizza(Pizza update)
|
||||
{
|
||||
_pizzas = _pizzas.Select(pizza =>
|
||||
{
|
||||
if (pizza.Id == update.Id)
|
||||
{
|
||||
pizza.Name = update.Name;
|
||||
}
|
||||
return pizza;
|
||||
}).ToList();
|
||||
return update;
|
||||
}
|
||||
|
||||
public static void RemovePizza(int id)
|
||||
{
|
||||
_pizzas = _pizzas.FindAll(pizza => pizza.Id == id).ToList();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now that you have your data store, let's have the API use it next.
|
||||
|
||||
### Connect data to routes
|
||||
|
||||
To connect your in-memory store to the API:
|
||||
|
||||
1. **Add the namespace.** This addition is as simple as adding the proper `using` statement.
|
||||
1. **Set up the routes.** Make sure you add all the route mappings that are needed to create, read, update, and delete.
|
||||
1. **Invoke it in the routes.** Finally, you need to call the in-memory store per each route and pass in any parameters or body from the request, if applicable.
|
||||
|
||||
Now, connect data in your API.
|
||||
|
||||
1. At the top of the _Program.cs_ file, add the following line of code:
|
||||
|
||||
```csharp
|
||||
using PizzaStore.DB;
|
||||
```
|
||||
|
||||
1. Just before `app.Run()`, add the following code:
|
||||
|
||||
```csharp
|
||||
app.MapGet("/pizzas/{id}", (int id) => PizzaDB.GetPizza(id));
|
||||
app.MapGet("/pizzas", () => PizzaDB.GetPizzas());
|
||||
app.MapPost("/pizzas", (Pizza pizza) => PizzaDB.CreatePizza(pizza));
|
||||
app.MapPut("/pizzas", (Pizza pizza) => PizzaDB.UpdatePizza(pizza));
|
||||
app.MapDelete("/pizzas/{id}", (int id) => PizzaDB.RemovePizza(id));
|
||||
```
|
||||
|
||||
This is the actual API part of the application! As you can see, there's not a lot of code. We're just mapping the routes to code that calls into our in-memory store.
|
||||
|
||||
1. Run the app by using `dotnet run`:
|
||||
|
||||
```bash
|
||||
dotnet run
|
||||
```
|
||||
|
||||
1. In your browser, go to `http://localhost:{PORT}/swagger`.
|
||||
|
||||
You should see the following page rendering:
|
||||
|
||||

|
||||
|
||||
What's great about this Swagger UI is that you can use it to test out the API. Click on any of the API endpoints to expand it, and click the `Try it out` button. You'll see a form that makes it easy to try submitting requests to the API and seeing the response.
|
||||
|
||||
## What's next?
|
||||
|
||||
This is a quick first look at building a backend with Minimal APIs. To go through this same example in more detail, and with more explanation, check out the [Minimal API learning path on Microsoft Learn](https://docs.microsoft.com/learn/paths/aspnet-core-minimal-api/)!
|
||||
|
||||
In the next lesson, you'll learn about building a game with Blazor! Stay tuned!
|
||||
|
||||
## Connect with us
|
||||
|
||||
We're excited to support you on your learning journey! Check out the [.NET Community Page](https://dotnet.microsoft.com/platform/community) to find links to our blogs, YouTube, Twitter, and more.
|
||||
BIN
4-minimal-api/swagger-crud.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
4-minimal-api/swagger.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
65
6-publish/README.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Publish your web app to Azure 🥳
|
||||
|
||||
Welcome! In this lesson, we'll teach you how to publish your web apps from the previous weeks' activities to Azure! We'll do this using Azure App Service.
|
||||
|
||||
## What is Azure?
|
||||
|
||||
Azure is a cloud platform designed to simplify the process of building modern applications. You can host all kinds of applications on Azure!
|
||||
|
||||
## What is Azure App Services and why are we publishing our apps?
|
||||
|
||||
Azure App Service is an HTTP-based service for hosting web applications, REST APIs, and mobile back ends. This service adds security, load balancing, autoscaling, automated management, and more to your applications. You can also take advantage of its DevOps capabilities, such as continuous deployment from Azure DevOps, GitHub, Docker Hub, and other sources, package management, staging environments, custom domain, and TLS/SSL certificates.
|
||||
You can learn more in the [Azure App Service overview documentation](https://docs.microsoft.com/azure/app-service/overview).
|
||||
|
||||
## Create your free Azure account
|
||||
|
||||
If you are a full time student at an accredited 2 or 4 year university, you can create your account with $100 worth of free Azure credits! For more information on student eligibility, check out this [FAQ](https://docs.microsoft.com/azure/education-hub/azure-dev-tools-teaching/program-faq#azure-for-students). Sign up [here](https://azure.microsoft.com/free/students/).
|
||||
|
||||
Otherwise, you can still create a free Azure account by following these directions.
|
||||
1. Follow [this link](https://azure.microsoft.com/free/dotnet/) to the Azure website to sign up for your free account.
|
||||
2. Click on the green **Start Free** button.
|
||||

|
||||
3. Sign in to your Microsoft account if your are not already signed in.
|
||||
4. Agree to the customer agreement
|
||||
|
||||

|
||||
5. You will then be asked to provide a credit or debit card. This will make a temporary authorization on your card, but you won’t be charged unless you move to pay-as-you-go pricing.
|
||||
6. Click sign up and you're ready to publish your application!
|
||||
|
||||
|
||||
## Let's publish!
|
||||
You can also find these instructions in the [Azure documentation](https://docs.microsoft.com/azure/app-service/quickstart-dotnetcore?tabs=net60&pivots=development-environment-vs).
|
||||
|
||||
1. Choose the web application you'd like to publish! It can be any of the projects that you created in emails 3, 4, or 5. Open up this project in Visual Studio.
|
||||
2. In **Solution Explorer**, right-click your ASP.NET Core project and select **Publish**.
|
||||

|
||||
|
||||
3. In **Publish**, you'll see the following options. Select **Azure** and click the **Next** button.
|
||||

|
||||
4. Choose the **Specific target**, **Azure App Service (Windows)**. Then, click the **Next** button.
|
||||

|
||||
5. If you are not signed in to Azure or if your Visual Studio account is not linked to your Azure account, click **Add an account** or **Sign in**. If you are already signed in, select your account.
|
||||

|
||||
|
||||
6. Select the **+** to the right of **App Service instances**.
|
||||

|
||||
7. For **Subscription**, accept the subscription that is listed or select a new one from the drop-down list.
|
||||
8. For **Resource group**, select **New**. In **New resource group name**, enter *myResourceGroup* and select **OK**.
|
||||
9. For **Hosting Plan**, select **New**.
|
||||
10. In the **Hosting Plan: Create new** dialog, enter the values specified in the following table:
|
||||
| Setting | Suggested value | Description |
|
||||
| ------- | --------------- | ----------- |
|
||||
| Hosting Plan | *MyFirstAzureWebAppPlan* | Name of the App Service Plan |
|
||||
| Location | Select the default | The datacenter where the app is hosted |
|
||||
| Size | *Free* | Pricing tier |
|
||||
|
||||
This will look like the below.
|
||||
|
||||

|
||||
11. Select **Create** to create the Azure resources. Once the wizard completes, the Azure resources are created for you and you're ready to publish your ASP.NET Core project.
|
||||
|
||||

|
||||
12. In the **Publish** dialog, ensure your new App Service app is selected in **App Service instance**, then select **Finish**. Visual Studio creates a publish profile for you for the selected App Service app.
|
||||
13. In the **Publish** page, select **Publish**. If you see a warning message, select **Continue**.Visual Studio builds, packages, and publishes the app to Azure, and then launches the app in the default browser.
|
||||
|
||||
Congratulations 🎉 You've just published your web applications!
|
||||
BIN
6-publish/images/azure-customer-agreement.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
6-publish/images/azure-start-free.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
6-publish/images/create-new-app-service.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
6-publish/images/hosting-plan.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
6-publish/images/publish-new-app-service.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
6-publish/images/sign-in-azure.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
6-publish/images/solution-explorer-publish.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
6-publish/images/specific-target.png
Normal file
|
After Width: | Height: | Size: 28 KiB |