diff --git a/docs/06-authentication-and-authorization.md b/docs/06-authentication-and-authorization.md
index 3bea9069..a3e2f238 100644
--- a/docs/06-authentication-and-authorization.md
+++ b/docs/06-authentication-and-authorization.md
@@ -263,6 +263,48 @@ builder.Services.AddHttpClient
(client => client.BaseAddress = new
.AddHttpMessageHandler();
```
+### Optional: Optimize JSON interactions with .NET 6 JSON CodeGeneration
+
+Starting with .NET 6, the System.Text.Json.JsonSerializer supports working with optimized code generated for serializing and deserializing JSON payloads. Code is generated at build time, resulting in a significant performance improvement for the serialization and deserialization of JSON data. This is configured by taking the following steps:
+
+1. Create a partial Context class that inherits from `System.Text.Json.Serialization.JsonSerializerContext`
+2. Decorate the class with the `System.Text.Json.JsonSourceGenerationOptions` attribute
+3. Add `JsonSerializable` attributes to the class definition for each type that you would like to have code generated
+
+We have already written this context for you and it is located in the `BlazingPizza.Shared.Order.cs" file
+
+```csharp
+[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Default, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
+[JsonSerializable(typeof(Order))]
+[JsonSerializable(typeof(OrderWithStatus))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(Pizza))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(Topping))]
+public partial class OrderContext : JsonSerializerContext {}
+```
+
+You can now optimize the calls to the HttpClient in the `OrdersClient` class by passing an `OrderContext.Default` parameter pointing to the type sought as the second parameter. Updating the methods in the `OrdersClient` class should look like the following:
+
+```csharp
+public async Task> GetOrders() =>
+ await httpClient.GetFromJsonAsync("orders", OrderContext.Default.ListOrderWithStatus);
+
+public async Task GetOrder(int orderId) =>
+ await httpClient.GetFromJsonAsync($"orders/{orderId}", OrderContext.Default.OrderWithStatus);
+
+public async Task PlaceOrder(Order order)
+{
+ var response = await httpClient.PostAsJsonAsync("orders", order, OrderContext.Default.Order);
+ response.EnsureSuccessStatusCode();
+ var orderId = await response.Content.ReadFromJsonAsync();
+ return orderId;
+}
+```
+
+### Deploy OrdersClient to pages
+
Update each page where an `HttpClient` is used to manage orders to use the new typed `OrdersClient`. Inject an `OrdersClient` instead of an `HttpClient` and use the new client to make the API call. Wrap each call in a `try-catch` that handles exceptions of type `AccessTokenNotAvailableException` by calling the provided `Redirect()` method.
*Checkout.razor*
diff --git a/src/nuget.config b/nuget.config
similarity index 84%
rename from src/nuget.config
rename to nuget.config
index c128a804..023d22cf 100644
--- a/src/nuget.config
+++ b/nuget.config
@@ -1,8 +1,8 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/save-points/00-get-started/BlazingPizza.Client/BlazingPizza.Client.csproj b/save-points/00-get-started/BlazingPizza.Client/BlazingPizza.Client.csproj
index 04df2ddd..08e409ff 100644
--- a/save-points/00-get-started/BlazingPizza.Client/BlazingPizza.Client.csproj
+++ b/save-points/00-get-started/BlazingPizza.Client/BlazingPizza.Client.csproj
@@ -1,7 +1,8 @@
- net5.0
+ $(TargetFrameworkVersion)
+ true
diff --git a/save-points/00-get-started/BlazingPizza.Client/Program.cs b/save-points/00-get-started/BlazingPizza.Client/Program.cs
index 48147d6f..c5023d76 100644
--- a/save-points/00-get-started/BlazingPizza.Client/Program.cs
+++ b/save-points/00-get-started/BlazingPizza.Client/Program.cs
@@ -1,21 +1,11 @@
-using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
-using Microsoft.Extensions.DependencyInjection;
-using System;
-using System.Net.Http;
-using System.Threading.Tasks;
+using BlazingPizza.Client;
+using Microsoft.AspNetCore.Components.Web;
+using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
-namespace BlazingPizza.Client
-{
- public class Program
- {
- public static async Task Main(string[] args)
- {
- var builder = WebAssemblyHostBuilder.CreateDefault(args);
- builder.RootComponents.Add("#app");
+var builder = WebAssemblyHostBuilder.CreateDefault(args);
+builder.RootComponents.Add("#app");
+builder.RootComponents.Add("head::after");
- builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
+builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
- await builder.Build().RunAsync();
- }
- }
-}
+await builder.Build().RunAsync();
diff --git a/save-points/00-get-started/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj b/save-points/00-get-started/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj
index 5f51ee3c..b50155b9 100644
--- a/save-points/00-get-started/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj
+++ b/save-points/00-get-started/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj
@@ -1,7 +1,8 @@
- net5.0
+ $(TargetFrameworkVersion)
+ true
diff --git a/save-points/00-get-started/BlazingPizza.ComponentsLibrary/LocalStorage.cs b/save-points/00-get-started/BlazingPizza.ComponentsLibrary/LocalStorage.cs
index f36b098e..25567243 100644
--- a/save-points/00-get-started/BlazingPizza.ComponentsLibrary/LocalStorage.cs
+++ b/save-points/00-get-started/BlazingPizza.ComponentsLibrary/LocalStorage.cs
@@ -1,17 +1,15 @@
using Microsoft.JSInterop;
-using System.Threading.Tasks;
-namespace BlazingPizza.ComponentsLibrary
+namespace BlazingPizza.ComponentsLibrary;
+
+public static class LocalStorage
{
- public static class LocalStorage
- {
- public static ValueTask GetAsync(IJSRuntime jsRuntime, string key)
- => jsRuntime.InvokeAsync("blazorLocalStorage.get", key);
+ public static ValueTask GetAsync(IJSRuntime jsRuntime, string key)
+ => jsRuntime.InvokeAsync("blazorLocalStorage.get", key);
- public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value)
- => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value);
+ public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value)
+ => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value);
- public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key)
- => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key);
- }
+ public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key)
+ => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key);
}
diff --git a/save-points/00-get-started/BlazingPizza.ComponentsLibrary/Map/Marker.cs b/save-points/00-get-started/BlazingPizza.ComponentsLibrary/Map/Marker.cs
index 63006067..cae70a4e 100644
--- a/save-points/00-get-started/BlazingPizza.ComponentsLibrary/Map/Marker.cs
+++ b/save-points/00-get-started/BlazingPizza.ComponentsLibrary/Map/Marker.cs
@@ -1,13 +1,12 @@
-namespace BlazingPizza.ComponentsLibrary.Map
+namespace BlazingPizza.ComponentsLibrary.Map;
+
+public class Marker
{
- public class Marker
- {
- public string Description { get; set; }
+ public string Description { get; set; }
- public double X { get; set; }
+ public double X { get; set; }
- public double Y { get; set; }
+ public double Y { get; set; }
- public bool ShowPopup { get; set; }
- }
-}
+ public bool ShowPopup { get; set; }
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.ComponentsLibrary/Map/Point.cs b/save-points/00-get-started/BlazingPizza.ComponentsLibrary/Map/Point.cs
index 03841826..34194163 100644
--- a/save-points/00-get-started/BlazingPizza.ComponentsLibrary/Map/Point.cs
+++ b/save-points/00-get-started/BlazingPizza.ComponentsLibrary/Map/Point.cs
@@ -1,9 +1,8 @@
-namespace BlazingPizza.ComponentsLibrary.Map
+namespace BlazingPizza.ComponentsLibrary.Map;
+
+public class Point
{
- public class Point
- {
- public double X { get; set; }
+ public double X { get; set; }
- public double Y { get; set; }
- }
-}
+ public double Y { get; set; }
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Server/BlazingPizza.Server.csproj b/save-points/00-get-started/BlazingPizza.Server/BlazingPizza.Server.csproj
index fd7e3c51..227890e1 100644
--- a/save-points/00-get-started/BlazingPizza.Server/BlazingPizza.Server.csproj
+++ b/save-points/00-get-started/BlazingPizza.Server/BlazingPizza.Server.csproj
@@ -1,7 +1,8 @@
- net5.0
+ $(TargetFrameworkVersion)
+ true
diff --git a/save-points/00-get-started/BlazingPizza.Server/NotificationsController.cs b/save-points/00-get-started/BlazingPizza.Server/NotificationsController.cs
deleted file mode 100644
index bb3b96ff..00000000
--- a/save-points/00-get-started/BlazingPizza.Server/NotificationsController.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System.Linq;
-using System.Security.Claims;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-
-namespace BlazingPizza.Server
-{
- [Route("notifications")]
- [ApiController]
- [Authorize]
- public class NotificationsController : Controller
- {
- private readonly PizzaStoreContext _db;
-
- public NotificationsController(PizzaStoreContext db)
- {
- _db = db;
- }
-
- [HttpPut("subscribe")]
- public async Task Subscribe(NotificationSubscription subscription)
- {
- // We're storing at most one subscription per user, so delete old ones.
- // Alternatively, you could let the user register multiple subscriptions from different browsers/devices.
- var userId = GetUserId();
- var oldSubscriptions = _db.NotificationSubscriptions.Where(e => e.UserId == userId);
- _db.NotificationSubscriptions.RemoveRange(oldSubscriptions);
-
- // Store new subscription
- subscription.UserId = userId;
- _db.NotificationSubscriptions.Attach(subscription);
-
- await _db.SaveChangesAsync();
- return subscription;
- }
-
- private string GetUserId()
- {
- return HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
- }
- }
-}
diff --git a/save-points/00-get-started/BlazingPizza.Server/OidcConfigurationController.cs b/save-points/00-get-started/BlazingPizza.Server/OidcConfigurationController.cs
index c074debf..3d385048 100644
--- a/save-points/00-get-started/BlazingPizza.Server/OidcConfigurationController.cs
+++ b/save-points/00-get-started/BlazingPizza.Server/OidcConfigurationController.cs
@@ -1,26 +1,21 @@
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.AspNetCore.Mvc;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-namespace BlazingPizza.Server
+namespace BlazingPizza.Server;
+
+public class OidcConfigurationController : Controller
{
- public class OidcConfigurationController : Controller
+ public OidcConfigurationController(IClientRequestParametersProvider clientRequestParametersProvider)
{
- public OidcConfigurationController(IClientRequestParametersProvider clientRequestParametersProvider)
- {
- ClientRequestParametersProvider = clientRequestParametersProvider;
- }
+ ClientRequestParametersProvider = clientRequestParametersProvider;
+ }
- public IClientRequestParametersProvider ClientRequestParametersProvider { get; }
+ public IClientRequestParametersProvider ClientRequestParametersProvider { get; }
- [HttpGet("_configuration/{clientId}")]
- public IActionResult GetClientRequestParameters([FromRoute]string clientId)
- {
- var parameters = ClientRequestParametersProvider.GetClientParameters(HttpContext, clientId);
- return Ok(parameters);
- }
+ [HttpGet("_configuration/{clientId}")]
+ public IActionResult GetClientRequestParameters([FromRoute] string clientId)
+ {
+ var parameters = ClientRequestParametersProvider.GetClientParameters(HttpContext, clientId);
+ return Ok(parameters);
}
-}
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Server/OrdersController.cs b/save-points/00-get-started/BlazingPizza.Server/OrdersController.cs
index 2b8bc99b..37e37cc5 100644
--- a/save-points/00-get-started/BlazingPizza.Server/OrdersController.cs
+++ b/save-points/00-get-started/BlazingPizza.Server/OrdersController.cs
@@ -1,29 +1,25 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Claims;
-using System.Threading.Tasks;
+using System.Security.Claims;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
-namespace BlazingPizza.Server
+namespace BlazingPizza.Server;
+
+[Route("orders")]
+[ApiController]
+// [Authorize]
+public class OrdersController : Controller
{
- [Route("orders")]
- [ApiController]
- // [Authorize]
- public class OrdersController : Controller
- {
- private readonly PizzaStoreContext _db;
+ private readonly PizzaStoreContext _db;
- public OrdersController(PizzaStoreContext db)
- {
- _db = db;
- }
+ public OrdersController(PizzaStoreContext db)
+ {
+ _db = db;
+ }
- [HttpGet]
- public async Task>> GetOrders()
- {
- var orders = await _db.Orders
+ [HttpGet]
+ public async Task>> GetOrders()
+ {
+ var orders = await _db.Orders
// .Where(o => o.UserId == GetUserId())
.Include(o => o.DeliveryLocation)
.Include(o => o.Pizzas).ThenInclude(p => p.Special)
@@ -31,13 +27,13 @@ public async Task>> GetOrders()
.OrderByDescending(o => o.CreatedTime)
.ToListAsync();
- return orders.Select(o => OrderWithStatus.FromOrder(o)).ToList();
- }
+ return orders.Select(o => OrderWithStatus.FromOrder(o)).ToList();
+ }
- [HttpGet("{orderId}")]
- public async Task> GetOrderWithStatus(int orderId)
- {
- var order = await _db.Orders
+ [HttpGet("{orderId}")]
+ public async Task> GetOrderWithStatus(int orderId)
+ {
+ var order = await _db.Orders
.Where(o => o.OrderId == orderId)
// .Where(o => o.UserId == GetUserId())
.Include(o => o.DeliveryLocation)
@@ -45,70 +41,69 @@ public async Task> GetOrderWithStatus(int orderId)
.Include(o => o.Pizzas).ThenInclude(p => p.Toppings).ThenInclude(t => t.Topping)
.SingleOrDefaultAsync();
- if (order == null)
- {
- return NotFound();
- }
-
- return OrderWithStatus.FromOrder(order);
+ if (order == null)
+ {
+ return NotFound();
}
- [HttpPost]
- public async Task> PlaceOrder(Order order)
- {
- order.CreatedTime = DateTime.Now;
- order.DeliveryLocation = new LatLong(51.5001, -0.1239);
- // order.UserId = GetUserId();
-
- // Enforce existence of Pizza.SpecialId and Topping.ToppingId
- // in the database - prevent the submitter from making up
- // new specials and toppings
- foreach (var pizza in order.Pizzas)
- {
- pizza.SpecialId = pizza.Special.Id;
- pizza.Special = null;
-
- foreach (var topping in pizza.Toppings)
- {
- topping.ToppingId = topping.Topping.Id;
- topping.Topping = null;
- }
- }
+ return OrderWithStatus.FromOrder(order);
+ }
- _db.Orders.Attach(order);
- await _db.SaveChangesAsync();
+ [HttpPost]
+ public async Task> PlaceOrder(Order order)
+ {
+ order.CreatedTime = DateTime.Now;
+ order.DeliveryLocation = new LatLong(51.5001, -0.1239);
+ // order.UserId = GetUserId();
+
+ // Enforce existence of Pizza.SpecialId and Topping.ToppingId
+ // in the database - prevent the submitter from making up
+ // new specials and toppings
+ foreach (var pizza in order.Pizzas)
+ {
+ pizza.SpecialId = pizza.Special.Id;
+ pizza.Special = null;
- // In the background, send push notifications if possible
- var subscription = await _db.NotificationSubscriptions.Where(e => e.UserId == GetUserId()).SingleOrDefaultAsync();
- if (subscription != null)
+ foreach (var topping in pizza.Toppings)
{
- _ = TrackAndSendNotificationsAsync(order, subscription);
+ topping.ToppingId = topping.Topping.Id;
+ topping.Topping = null;
}
-
- return order.OrderId;
}
- private string GetUserId()
- {
- return HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
- }
+ _db.Orders.Attach(order);
+ await _db.SaveChangesAsync();
- private static async Task TrackAndSendNotificationsAsync(Order order, NotificationSubscription subscription)
+ // In the background, send push notifications if possible
+ var subscription = await _db.NotificationSubscriptions.Where(e => e.UserId == GetUserId()).SingleOrDefaultAsync();
+ if (subscription != null)
{
- // In a realistic case, some other backend process would track
- // order delivery progress and send us notifications when it
- // changes. Since we don't have any such process here, fake it.
- await Task.Delay(OrderWithStatus.PreparationDuration);
- await SendNotificationAsync(order, subscription, "Your order has been dispatched!");
-
- await Task.Delay(OrderWithStatus.DeliveryDuration);
- await SendNotificationAsync(order, subscription, "Your order is now delivered. Enjoy!");
+ _ = TrackAndSendNotificationsAsync(order, subscription);
}
- private static Task SendNotificationAsync(Order order, NotificationSubscription subscription, string message)
- {
- // This will be implemented later
- return Task.CompletedTask;
- }
+ return order.OrderId;
+ }
+
+ private string GetUserId()
+ {
+ return HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
+ }
+
+ private static async Task TrackAndSendNotificationsAsync(Order order, NotificationSubscription subscription)
+ {
+ // In a realistic case, some other backend process would track
+ // order delivery progress and send us notifications when it
+ // changes. Since we don't have any such process here, fake it.
+ await Task.Delay(OrderWithStatus.PreparationDuration);
+ await SendNotificationAsync(order, subscription, "Your order has been dispatched!");
+
+ await Task.Delay(OrderWithStatus.DeliveryDuration);
+ await SendNotificationAsync(order, subscription, "Your order is now delivered. Enjoy!");
+ }
+
+ private static Task SendNotificationAsync(Order order, NotificationSubscription subscription, string message)
+ {
+ // This will be implemented later
+ return Task.CompletedTask;
}
-}
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Server/PizzaApiExtensions.cs b/save-points/00-get-started/BlazingPizza.Server/PizzaApiExtensions.cs
new file mode 100644
index 00000000..524ca759
--- /dev/null
+++ b/save-points/00-get-started/BlazingPizza.Server/PizzaApiExtensions.cs
@@ -0,0 +1,57 @@
+using System.Security.Claims;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.EntityFrameworkCore;
+
+namespace BlazingPizza.Server;
+
+public static class PizzaApiExtensions
+{
+
+ public static WebApplication MapPizzaApi(this WebApplication app)
+ {
+
+ // Subscribe to notifications
+ app.MapPut("/notifications/subscribe", [Authorize] async (
+ HttpContext context,
+ PizzaStoreContext db,
+ NotificationSubscription subscription) => {
+
+ // We're storing at most one subscription per user, so delete old ones.
+ // Alternatively, you could let the user register multiple subscriptions from different browsers/devices.
+ var userId = GetUserId(context);
+ var oldSubscriptions = db.NotificationSubscriptions.Where(e => e.UserId == userId);
+ db.NotificationSubscriptions.RemoveRange(oldSubscriptions);
+
+ // Store new subscription
+ subscription.UserId = userId;
+ db.NotificationSubscriptions.Attach(subscription);
+
+ await db.SaveChangesAsync();
+ return Results.Ok(subscription);
+
+ });
+
+ // Specials
+ app.MapGet("/specials", async (PizzaStoreContext db) => {
+
+ var specials = await db.Specials.ToListAsync();
+ return Results.Ok(specials);
+
+ });
+
+ // Toppings
+ app.MapGet("/toppings", async (PizzaStoreContext db) => {
+ var toppings = await db.Toppings.OrderBy(t => t.Name).ToListAsync();
+ return Results.Ok(toppings);
+ });
+
+ return app;
+
+ }
+
+ private static string GetUserId(HttpContext context)
+ {
+ return context.User.FindFirstValue(ClaimTypes.NameIdentifier);
+ }
+
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Server/PizzaStoreContext.cs b/save-points/00-get-started/BlazingPizza.Server/PizzaStoreContext.cs
index f79c1c66..1505c7af 100644
--- a/save-points/00-get-started/BlazingPizza.Server/PizzaStoreContext.cs
+++ b/save-points/00-get-started/BlazingPizza.Server/PizzaStoreContext.cs
@@ -1,39 +1,38 @@
-using IdentityServer4.EntityFramework.Options;
+using Duende.IdentityServer.EntityFramework.Options;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
-namespace BlazingPizza.Server
+namespace BlazingPizza.Server;
+
+public class PizzaStoreContext : ApiAuthorizationDbContext
{
- public class PizzaStoreContext : ApiAuthorizationDbContext
- {
- public PizzaStoreContext(
+ public PizzaStoreContext(
DbContextOptions options,
IOptions operationalStoreOptions) : base(options, operationalStoreOptions)
- {
- }
+ {
+ }
- public DbSet Orders { get; set; }
+ public DbSet Orders { get; set; }
- public DbSet Pizzas { get; set; }
+ public DbSet Pizzas { get; set; }
- public DbSet Specials { get; set; }
+ public DbSet Specials { get; set; }
- public DbSet Toppings { get; set; }
+ public DbSet Toppings { get; set; }
- public DbSet NotificationSubscriptions { get; set; }
+ public DbSet NotificationSubscriptions { get; set; }
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
- // Configuring a many-to-many special -> topping relationship that is friendly for serialization
- modelBuilder.Entity().HasKey(pst => new { pst.PizzaId, pst.ToppingId });
- modelBuilder.Entity().HasOne().WithMany(ps => ps.Toppings);
- modelBuilder.Entity().HasOne(pst => pst.Topping).WithMany();
+ // Configuring a many-to-many special -> topping relationship that is friendly for serialization
+ modelBuilder.Entity().HasKey(pst => new { pst.PizzaId, pst.ToppingId });
+ modelBuilder.Entity().HasOne().WithMany(ps => ps.Toppings);
+ modelBuilder.Entity().HasOne(pst => pst.Topping).WithMany();
- // Inline the Lat-Long pairs in Order rather than having a FK to another table
- modelBuilder.Entity().OwnsOne(o => o.DeliveryLocation);
- }
+ // Inline the Lat-Long pairs in Order rather than having a FK to another table
+ modelBuilder.Entity().OwnsOne(o => o.DeliveryLocation);
}
}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Server/PizzasController.cs b/save-points/00-get-started/BlazingPizza.Server/PizzasController.cs
deleted file mode 100644
index c082552c..00000000
--- a/save-points/00-get-started/BlazingPizza.Server/PizzasController.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-
-namespace BlazingPizza.Server
-{
- [Route("pizzas")]
- [ApiController]
- public class PizzasController : Controller
- {
- private readonly PizzaStoreContext _db;
-
- public PizzasController(PizzaStoreContext db)
- {
- _db = db;
- }
- }
-}
diff --git a/save-points/00-get-started/BlazingPizza.Server/Program.cs b/save-points/00-get-started/BlazingPizza.Server/Program.cs
index 40a47641..e185db50 100644
--- a/save-points/00-get-started/BlazingPizza.Server/Program.cs
+++ b/save-points/00-get-started/BlazingPizza.Server/Program.cs
@@ -1,33 +1,66 @@
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
+using BlazingPizza.Server;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.EntityFrameworkCore;
-namespace BlazingPizza.Server
+var builder = WebApplication.CreateBuilder(args);
+
+builder.Services.AddControllersWithViews()
+ .AddJsonOptions(options => {
+ options.JsonSerializerOptions.AddContext();
+ });
+builder.Services.AddRazorPages();
+
+builder.Services.AddDbContext(options =>
+ options.UseSqlite("Data Source=pizza.db"));
+
+builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true)
+ .AddEntityFrameworkStores();
+
+builder.Services.AddIdentityServer()
+ .AddApiAuthorization();
+
+builder.Services.AddAuthentication()
+ .AddIdentityServerJwt();
+
+var app = builder.Build();
+
+// Initialize the database
+var scopeFactory = app.Services.GetRequiredService();
+using (var scope = scopeFactory.CreateScope())
{
- public class Program
+ var db = scope.ServiceProvider.GetRequiredService();
+ if (db.Database.EnsureCreated())
{
- public static void Main(string[] args)
- {
- var host = CreateHostBuilder(args).Build();
-
- // Initialize the database
- var scopeFactory = host.Services.GetRequiredService();
- using (var scope = scopeFactory.CreateScope())
- {
- var db = scope.ServiceProvider.GetRequiredService();
- if (db.Database.EnsureCreated())
- {
- SeedData.Initialize(db);
- }
- }
-
- host.Run();
- }
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.UseStartup();
- });
+ SeedData.Initialize(db);
}
}
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseWebAssemblyDebugging();
+}
+else
+{
+ app.UseExceptionHandler("/Error");
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+}
+
+app.UseHttpsRedirection();
+app.UseBlazorFrameworkFiles();
+app.UseStaticFiles();
+
+app.UseRouting();
+
+app.UseAuthentication();
+app.UseIdentityServer();
+app.UseAuthorization();
+
+app.MapPizzaApi();
+
+app.MapRazorPages();
+app.MapControllers();
+app.MapFallbackToFile("index.html");
+
+app.Run();
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Server/SeedData.cs b/save-points/00-get-started/BlazingPizza.Server/SeedData.cs
index 7c86a5b2..f02e2b77 100644
--- a/save-points/00-get-started/BlazingPizza.Server/SeedData.cs
+++ b/save-points/00-get-started/BlazingPizza.Server/SeedData.cs
@@ -1,193 +1,192 @@
-namespace BlazingPizza.Server
+namespace BlazingPizza.Server;
+
+public static class SeedData
{
- public static class SeedData
+ public static void Initialize(PizzaStoreContext db)
{
- public static void Initialize(PizzaStoreContext db)
+ var toppings = new Topping[]
{
- var toppings = new Topping[]
+ new Topping()
{
- new Topping()
- {
Name = "Extra cheese",
Price = 2.50m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "American bacon",
Price = 2.99m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "British bacon",
Price = 2.99m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Canadian bacon",
Price = 2.99m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Tea and crumpets",
Price = 5.00m
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Fresh-baked scones",
Price = 4.50m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Bell peppers",
Price = 1.00m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Onions",
Price = 1.00m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Mushrooms",
Price = 1.00m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Pepperoni",
Price = 1.00m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Duck sausage",
Price = 3.20m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Venison meatballs",
Price = 2.50m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Served on a silver platter",
Price = 250.99m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Lobster on top",
Price = 64.50m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Sturgeon caviar",
Price = 101.75m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Artichoke hearts",
Price = 3.40m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Fresh tomatoes",
Price = 1.50m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Basil",
Price = 1.50m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Steak (medium-rare)",
Price = 8.50m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Blazing hot peppers",
Price = 4.20m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Buffalo chicken",
Price = 5.00m,
- },
- new Topping()
- {
+ },
+ new Topping()
+ {
Name = "Blue cheese",
Price = 2.50m,
- },
- };
+ },
+ };
- var specials = new PizzaSpecial[]
+ var specials = new PizzaSpecial[]
+ {
+ new PizzaSpecial()
{
- new PizzaSpecial()
- {
Name = "Basic Cheese Pizza",
Description = "It's cheesy and delicious. Why wouldn't you want one?",
BasePrice = 9.99m,
ImageUrl = "img/pizzas/cheese.jpg",
- },
- new PizzaSpecial()
- {
+ },
+ new PizzaSpecial()
+ {
Id = 2,
Name = "The Baconatorizor",
Description = "It has EVERY kind of bacon",
BasePrice = 11.99m,
ImageUrl = "img/pizzas/bacon.jpg",
- },
- new PizzaSpecial()
- {
+ },
+ new PizzaSpecial()
+ {
Id = 3,
Name = "Classic pepperoni",
Description = "It's the pizza you grew up with, but Blazing hot!",
BasePrice = 10.50m,
ImageUrl = "img/pizzas/pepperoni.jpg",
- },
- new PizzaSpecial()
- {
+ },
+ new PizzaSpecial()
+ {
Id = 4,
Name = "Buffalo chicken",
Description = "Spicy chicken, hot sauce and bleu cheese, guaranteed to warm you up",
BasePrice = 12.75m,
ImageUrl = "img/pizzas/meaty.jpg",
- },
- new PizzaSpecial()
- {
+ },
+ new PizzaSpecial()
+ {
Id = 5,
Name = "Mushroom Lovers",
Description = "It has mushrooms. Isn't that obvious?",
BasePrice = 11.00m,
ImageUrl = "img/pizzas/mushroom.jpg",
- },
- new PizzaSpecial()
- {
+ },
+ new PizzaSpecial()
+ {
Id = 6,
Name = "The Brit",
Description = "When in London...",
BasePrice = 10.25m,
ImageUrl = "img/pizzas/brit.jpg",
- },
- new PizzaSpecial()
- {
+ },
+ new PizzaSpecial()
+ {
Id = 7,
Name = "Veggie Delight",
Description = "It's like salad, but on a pizza",
BasePrice = 11.50m,
ImageUrl = "img/pizzas/salad.jpg",
- },
- new PizzaSpecial()
- {
+ },
+ new PizzaSpecial()
+ {
Id = 8,
Name = "Margherita",
Description = "Traditional Italian pizza with tomatoes and basil",
BasePrice = 9.99m,
ImageUrl = "img/pizzas/margherita.jpg",
- },
- };
+ },
+ };
- db.Toppings.AddRange(toppings);
- db.Specials.AddRange(specials);
- db.SaveChanges();
- }
+ db.Toppings.AddRange(toppings);
+ db.Specials.AddRange(specials);
+ db.SaveChanges();
}
-}
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Server/SpecialsController.cs b/save-points/00-get-started/BlazingPizza.Server/SpecialsController.cs
deleted file mode 100644
index a176844c..00000000
--- a/save-points/00-get-started/BlazingPizza.Server/SpecialsController.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.EntityFrameworkCore;
-
-namespace BlazingPizza.Server
-{
- [Route("specials")]
- [ApiController]
- public class SpecialsController : Controller
- {
- private readonly PizzaStoreContext _db;
-
- public SpecialsController(PizzaStoreContext db)
- {
- _db = db;
- }
-
- [HttpGet]
- public async Task>> GetSpecials()
- {
- return (await _db.Specials.ToListAsync()).OrderByDescending(s => s.BasePrice).ToList();
- }
- }
-}
diff --git a/save-points/00-get-started/BlazingPizza.Server/Startup.cs b/save-points/00-get-started/BlazingPizza.Server/Startup.cs
deleted file mode 100644
index ed3fca06..00000000
--- a/save-points/00-get-started/BlazingPizza.Server/Startup.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using Microsoft.AspNetCore.Authentication;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-
-namespace BlazingPizza.Server
-{
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- public IConfiguration Configuration { get; }
-
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddControllersWithViews();
- services.AddRazorPages();
-
- services.AddDbContext(options =>
- options.UseSqlite("Data Source=pizza.db"));
-
- services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true)
- .AddEntityFrameworkStores();
-
- services.AddIdentityServer()
- .AddApiAuthorization();
-
- services.AddAuthentication()
- .AddIdentityServerJwt();
- }
-
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- app.UseWebAssemblyDebugging();
- }
- else
- {
- app.UseExceptionHandler("/Error");
- // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
- app.UseHsts();
- }
-
- app.UseHttpsRedirection();
- app.UseBlazorFrameworkFiles();
- app.UseStaticFiles();
-
- app.UseRouting();
-
- app.UseAuthentication();
- app.UseIdentityServer();
- app.UseAuthorization();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- endpoints.MapRazorPages();
- endpoints.MapFallbackToFile("index.html");
- });
- }
- }
-}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Server/ToppingsController.cs b/save-points/00-get-started/BlazingPizza.Server/ToppingsController.cs
deleted file mode 100644
index 6a677639..00000000
--- a/save-points/00-get-started/BlazingPizza.Server/ToppingsController.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.EntityFrameworkCore;
-
-namespace BlazingPizza.Server
-{
- [Route("toppings")]
- [ApiController]
- public class ToppingsController : Controller
- {
- private readonly PizzaStoreContext _db;
-
- public ToppingsController(PizzaStoreContext db)
- {
- _db = db;
- }
-
- [HttpGet]
- public async Task>> GetToppings()
- {
- return await _db.Toppings.OrderBy(t => t.Name).ToListAsync();
- }
- }
-}
diff --git a/save-points/00-get-started/BlazingPizza.Shared/Address.cs b/save-points/00-get-started/BlazingPizza.Shared/Address.cs
index e5c0ef0d..a671359a 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/Address.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/Address.cs
@@ -1,21 +1,24 @@
-using System.ComponentModel.DataAnnotations;
+namespace BlazingPizza;
-namespace BlazingPizza
+public class Address
{
- public class Address
- {
- public int Id { get; set; }
+ public int Id { get; set; }
- public string Name { get; set; }
+ [Required, MaxLength(100)]
+ public string Name { get; set; }
- public string Line1 { get; set; }
+ [Required, MaxLength(100)]
+ public string Line1 { get; set; }
- public string Line2 { get; set; }
+ [MaxLength(100)]
+ public string Line2 { get; set; }
- public string City { get; set; }
+ [Required, MaxLength(50)]
+ public string City { get; set; }
- public string Region { get; set; }
+ [Required, MaxLength(20)]
+ public string Region { get; set; }
- public string PostalCode { get; set; }
- }
+ [Required, MaxLength(20)]
+ public string PostalCode { get; set; }
}
diff --git a/save-points/00-get-started/BlazingPizza.Shared/BlazingPizza.Shared.csproj b/save-points/00-get-started/BlazingPizza.Shared/BlazingPizza.Shared.csproj
index 911c57c5..fb17e53b 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/BlazingPizza.Shared.csproj
+++ b/save-points/00-get-started/BlazingPizza.Shared/BlazingPizza.Shared.csproj
@@ -1,10 +1,15 @@
- net5.0
+ $(TargetFrameworkVersion)
BlazingPizza
+ true
+
+
+
+
diff --git a/save-points/00-get-started/BlazingPizza.Shared/LatLong.cs b/save-points/00-get-started/BlazingPizza.Shared/LatLong.cs
index 9b8c3811..a65971f8 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/LatLong.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/LatLong.cs
@@ -1,27 +1,26 @@
-namespace BlazingPizza
+namespace BlazingPizza;
+
+public class LatLong
{
- public class LatLong
+ public LatLong()
{
- public LatLong()
- {
- }
+ }
- public LatLong(double latitude, double longitude) : this()
- {
- Latitude = latitude;
- Longitude = longitude;
- }
+ public LatLong(double latitude, double longitude) : this()
+ {
+ Latitude = latitude;
+ Longitude = longitude;
+ }
- public double Latitude { get; set; }
+ public double Latitude { get; set; }
- public double Longitude { get; set; }
+ public double Longitude { get; set; }
- public static LatLong Interpolate(LatLong start, LatLong end, double proportion)
- {
- // The Earth is flat, right? So no need for spherical interpolation.
- return new LatLong(
+ public static LatLong Interpolate(LatLong start, LatLong end, double proportion)
+ {
+ // The Earth is flat, right? So no need for spherical interpolation.
+ return new LatLong(
start.Latitude + (end.Latitude - start.Latitude) * proportion,
start.Longitude + (end.Longitude - start.Longitude) * proportion);
- }
}
-}
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Shared/NotificationSubscription.cs b/save-points/00-get-started/BlazingPizza.Shared/NotificationSubscription.cs
index 04259c2f..5c99e3f4 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/NotificationSubscription.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/NotificationSubscription.cs
@@ -1,17 +1,14 @@
-using System.ComponentModel.DataAnnotations;
+namespace BlazingPizza;
-namespace BlazingPizza
+public class NotificationSubscription
{
- public class NotificationSubscription
- {
- public int NotificationSubscriptionId { get; set; }
+ public int NotificationSubscriptionId { get; set; }
- public string UserId { get; set; }
+ public string UserId { get; set; }
- public string Url { get; set; }
+ public string Url { get; set; }
- public string P256dh { get; set; }
+ public string P256dh { get; set; }
- public string Auth { get; set; }
- }
+ public string Auth { get; set; }
}
diff --git a/save-points/00-get-started/BlazingPizza.Shared/Order.cs b/save-points/00-get-started/BlazingPizza.Shared/Order.cs
index fb003bd6..b47efad0 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/Order.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/Order.cs
@@ -1,25 +1,32 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
+using System.Text.Json.Serialization;
-namespace BlazingPizza
+namespace BlazingPizza;
+
+public class Order
{
- public class Order
- {
- public int OrderId { get; set; }
+ public int OrderId { get; set; }
- public string UserId { get; set; }
+ public string UserId { get; set; }
- public DateTime CreatedTime { get; set; }
+ public DateTime CreatedTime { get; set; }
- public Address DeliveryAddress { get; set; } = new Address();
+ public Address DeliveryAddress { get; set; } = new Address();
- public LatLong DeliveryLocation { get; set; }
+ public LatLong DeliveryLocation { get; set; }
- public List Pizzas { get; set; } = new List();
+ public List Pizzas { get; set; } = new List();
- public decimal GetTotalPrice() => Pizzas.Sum(p => p.GetTotalPrice());
+ public decimal GetTotalPrice() => Pizzas.Sum(p => p.GetTotalPrice());
- public string GetFormattedTotalPrice() => GetTotalPrice().ToString("0.00");
- }
+ public string GetFormattedTotalPrice() => GetTotalPrice().ToString("0.00");
}
+
+[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Default, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
+[JsonSerializable(typeof(Order))]
+[JsonSerializable(typeof(OrderWithStatus))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(Pizza))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(Topping))]
+public partial class OrderContext : JsonSerializerContext { }
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Shared/OrderWithStatus.cs b/save-points/00-get-started/BlazingPizza.Shared/OrderWithStatus.cs
index 021de78c..fbfac7af 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/OrderWithStatus.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/OrderWithStatus.cs
@@ -1,79 +1,78 @@
-using BlazingPizza.ComponentsLibrary.Map;
-using System;
-using System.Collections.Generic;
+using System.Text.Json.Serialization;
+using BlazingPizza.ComponentsLibrary.Map;
-namespace BlazingPizza
-{
- public class OrderWithStatus
- {
- public readonly static TimeSpan PreparationDuration = TimeSpan.FromSeconds(10);
- public readonly static TimeSpan DeliveryDuration = TimeSpan.FromMinutes(1); // Unrealistic, but more interesting to watch
- public Order Order { get; set; }
+namespace BlazingPizza;
- public string StatusText { get; set; }
+public class OrderWithStatus
+{
+ public readonly static TimeSpan PreparationDuration = TimeSpan.FromSeconds(10);
+ public readonly static TimeSpan DeliveryDuration = TimeSpan.FromMinutes(1); // Unrealistic, but more interesting to watch
- public bool IsDelivered => StatusText == "Delivered";
+ public Order Order { get; set; }
- public List MapMarkers { get; set; }
+ public string StatusText { get; set; }
- public static OrderWithStatus FromOrder(Order order)
- {
- // To simulate a real backend process, we fake status updates based on the amount
- // of time since the order was placed
- string statusText;
- List mapMarkers;
- var dispatchTime = order.CreatedTime.Add(PreparationDuration);
+ public bool IsDelivered => StatusText == "Delivered";
- if (DateTime.Now < dispatchTime)
- {
- statusText = "Preparing";
- mapMarkers = new List
- {
- ToMapMarker("You", order.DeliveryLocation, showPopup: true)
- };
- }
- else if (DateTime.Now < dispatchTime + DeliveryDuration)
- {
- statusText = "Out for delivery";
+ public List MapMarkers { get; set; }
- var startPosition = ComputeStartPosition(order);
- var proportionOfDeliveryCompleted = Math.Min(1, (DateTime.Now - dispatchTime).TotalMilliseconds / DeliveryDuration.TotalMilliseconds);
- var driverPosition = LatLong.Interpolate(startPosition, order.DeliveryLocation, proportionOfDeliveryCompleted);
- mapMarkers = new List
- {
- ToMapMarker("You", order.DeliveryLocation),
- ToMapMarker("Driver", driverPosition, showPopup: true),
- };
- }
- else
- {
- statusText = "Delivered";
- mapMarkers = new List
- {
- ToMapMarker("Delivery location", order.DeliveryLocation, showPopup: true),
- };
- }
+ public static OrderWithStatus FromOrder(Order order)
+ {
+ // To simulate a real backend process, we fake status updates based on the amount
+ // of time since the order was placed
+ string statusText;
+ List mapMarkers;
+ var dispatchTime = order.CreatedTime.Add(PreparationDuration);
- return new OrderWithStatus
- {
- Order = order,
- StatusText = statusText,
- MapMarkers = mapMarkers,
- };
+ if (DateTime.Now < dispatchTime)
+ {
+ statusText = "Preparing";
+ mapMarkers = new List
+ {
+ ToMapMarker("You", order.DeliveryLocation, showPopup: true)
+ };
}
+ else if (DateTime.Now < dispatchTime + DeliveryDuration)
+ {
+ statusText = "Out for delivery";
- private static LatLong ComputeStartPosition(Order order)
+ var startPosition = ComputeStartPosition(order);
+ var proportionOfDeliveryCompleted = Math.Min(1, (DateTime.Now - dispatchTime).TotalMilliseconds / DeliveryDuration.TotalMilliseconds);
+ var driverPosition = LatLong.Interpolate(startPosition, order.DeliveryLocation, proportionOfDeliveryCompleted);
+ mapMarkers = new List
+ {
+ ToMapMarker("You", order.DeliveryLocation),
+ ToMapMarker("Driver", driverPosition, showPopup: true),
+ };
+ }
+ else
{
- // Random but deterministic based on order ID
- var rng = new Random(order.OrderId);
- var distance = 0.01 + rng.NextDouble() * 0.02;
- var angle = rng.NextDouble() * Math.PI * 2;
- var offset = (distance * Math.Cos(angle), distance * Math.Sin(angle));
- return new LatLong(order.DeliveryLocation.Latitude + offset.Item1, order.DeliveryLocation.Longitude + offset.Item2);
+ statusText = "Delivered";
+ mapMarkers = new List
+ {
+ ToMapMarker("Delivery location", order.DeliveryLocation, showPopup: true),
+ };
}
- static Marker ToMapMarker(string description, LatLong coords, bool showPopup = false)
- => new Marker { Description = description, X = coords.Longitude, Y = coords.Latitude, ShowPopup = showPopup };
+ return new OrderWithStatus
+ {
+ Order = order,
+ StatusText = statusText,
+ MapMarkers = mapMarkers,
+ };
}
-}
+
+ private static LatLong ComputeStartPosition(Order order)
+ {
+ // Random but deterministic based on order ID
+ var rng = new Random(order.OrderId);
+ var distance = 0.01 + rng.NextDouble() * 0.02;
+ var angle = rng.NextDouble() * Math.PI * 2;
+ var offset = (distance * Math.Cos(angle), distance * Math.Sin(angle));
+ return new LatLong(order.DeliveryLocation.Latitude + offset.Item1, order.DeliveryLocation.Longitude + offset.Item2);
+ }
+
+ static Marker ToMapMarker(string description, LatLong coords, bool showPopup = false)
+ => new Marker { Description = description, X = coords.Longitude, Y = coords.Latitude, ShowPopup = showPopup };
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Shared/Pizza.cs b/save-points/00-get-started/BlazingPizza.Shared/Pizza.cs
index ec1108a9..2a7a1c29 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/Pizza.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/Pizza.cs
@@ -1,42 +1,44 @@
-using System.Collections.Generic;
-using System.Linq;
+using System.Text.Json.Serialization;
-namespace BlazingPizza
+namespace BlazingPizza;
+
+///
+/// /// Represents a customized pizza as part of an order
+///
+public class Pizza
{
- ///
- /// Represents a customized pizza as part of an order
- ///
- public class Pizza
- {
- public const int DefaultSize = 12;
- public const int MinimumSize = 9;
- public const int MaximumSize = 17;
+ public const int DefaultSize = 12;
+ public const int MinimumSize = 9;
+ public const int MaximumSize = 17;
- public int Id { get; set; }
+ public int Id { get; set; }
- public int OrderId { get; set; }
+ public int OrderId { get; set; }
- public PizzaSpecial Special { get; set; }
+ public PizzaSpecial Special { get; set; }
- public int SpecialId { get; set; }
+ public int SpecialId { get; set; }
- public int Size { get; set; }
+ public int Size { get; set; }
- public List Toppings { get; set; }
+ public List Toppings { get; set; }
- public decimal GetBasePrice()
- {
- return ((decimal)Size / (decimal)DefaultSize) * Special.BasePrice;
- }
+ public decimal GetBasePrice()
+ {
+ return ((decimal)Size / (decimal)DefaultSize) * Special.BasePrice;
+ }
- public decimal GetTotalPrice()
- {
- return GetBasePrice() + Toppings.Sum(t => t.Topping.Price);
- }
+ public decimal GetTotalPrice()
+ {
+ return GetBasePrice() + Toppings.Sum(t => t.Topping.Price);
+ }
- public string GetFormattedTotalPrice()
- {
- return GetTotalPrice().ToString("0.00");
- }
+ public string GetFormattedTotalPrice()
+ {
+ return GetTotalPrice().ToString("0.00");
}
}
+
+[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)]
+[JsonSerializable(typeof(Pizza))]
+public partial class PizzaContext : JsonSerializerContext { }
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Shared/PizzaSpecial.cs b/save-points/00-get-started/BlazingPizza.Shared/PizzaSpecial.cs
index 2f2b3383..1fd9006a 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/PizzaSpecial.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/PizzaSpecial.cs
@@ -1,20 +1,19 @@
-namespace BlazingPizza
+namespace BlazingPizza;
+
+///
+/// Represents a pre-configured template for a pizza a user can order
+///
+public class PizzaSpecial
{
- ///
- /// Represents a pre-configured template for a pizza a user can order
- ///
- public class PizzaSpecial
- {
- public int Id { get; set; }
+ public int Id { get; set; }
- public string Name { get; set; }
+ public string Name { get; set; }
- public decimal BasePrice { get; set; }
+ public decimal BasePrice { get; set; }
- public string Description { get; set; }
+ public string Description { get; set; }
- public string ImageUrl { get; set; }
+ public string ImageUrl { get; set; }
- public string GetFormattedBasePrice() => BasePrice.ToString("0.00");
- }
-}
+ public string GetFormattedBasePrice() => BasePrice.ToString("0.00");
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Shared/PizzaTopping.cs b/save-points/00-get-started/BlazingPizza.Shared/PizzaTopping.cs
index f5a6c1ac..1c062732 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/PizzaTopping.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/PizzaTopping.cs
@@ -1,11 +1,11 @@
-namespace BlazingPizza
+namespace BlazingPizza;
+
+public class PizzaTopping
{
- public class PizzaTopping
- {
- public Topping Topping { get; set; }
-
- public int ToppingId { get; set; }
-
- public int PizzaId { get; set; }
- }
-}
+ public Topping Topping { get; set; }
+
+ public int ToppingId { get; set; }
+
+ public int PizzaId { get; set; }
+
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Shared/Topping.cs b/save-points/00-get-started/BlazingPizza.Shared/Topping.cs
index 61bdeb92..4eb67ae9 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/Topping.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/Topping.cs
@@ -1,13 +1,13 @@
-namespace BlazingPizza
+namespace BlazingPizza;
+
+public class Topping
{
- public class Topping
- {
- public int Id { get; set; }
+ public int Id { get; set; }
+
+ public string Name { get; set; }
- public string Name { get; set; }
+ public decimal Price { get; set; }
- public decimal Price { get; set; }
+ public string GetFormattedPrice() => Price.ToString("0.00");
- public string GetFormattedPrice() => Price.ToString("0.00");
- }
-}
+}
\ No newline at end of file
diff --git a/save-points/00-get-started/BlazingPizza.Shared/UserInfo.cs b/save-points/00-get-started/BlazingPizza.Shared/UserInfo.cs
index 4996ef80..babb4315 100644
--- a/save-points/00-get-started/BlazingPizza.Shared/UserInfo.cs
+++ b/save-points/00-get-started/BlazingPizza.Shared/UserInfo.cs
@@ -1,9 +1,9 @@
-namespace BlazingPizza
+namespace BlazingPizza;
+
+public class UserInfo
{
- public class UserInfo
- {
- public bool IsAuthenticated { get; set; }
+ public bool IsAuthenticated { get; set; }
+
+ public string Name { get; set; }
- public string Name { get; set; }
- }
-}
+}
\ No newline at end of file
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Client/BlazingPizza.Client.csproj b/save-points/01-Components-and-layout/BlazingPizza.Client/BlazingPizza.Client.csproj
index a833c6be..f9ebe283 100644
--- a/save-points/01-Components-and-layout/BlazingPizza.Client/BlazingPizza.Client.csproj
+++ b/save-points/01-Components-and-layout/BlazingPizza.Client/BlazingPizza.Client.csproj
@@ -1,7 +1,8 @@
- net5.0
+ $(TargetFrameworkVersion)
+ true
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Client/Pages/Index.razor b/save-points/01-Components-and-layout/BlazingPizza.Client/Pages/Index.razor
index 68649ba9..03d6e160 100644
--- a/save-points/01-Components-and-layout/BlazingPizza.Client/Pages/Index.razor
+++ b/save-points/01-Components-and-layout/BlazingPizza.Client/Pages/Index.razor
@@ -24,6 +24,6 @@
protected override async Task OnInitializedAsync()
{
- specials = await HttpClient.GetFromJsonAsync>("specials");
+ specials = await HttpClient.GetFromJsonAsync("specials", BlazingPizza.OrderContext.Default.ListPizzaSpecial);
}
}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Client/Program.cs b/save-points/01-Components-and-layout/BlazingPizza.Client/Program.cs
index 48147d6f..c5023d76 100644
--- a/save-points/01-Components-and-layout/BlazingPizza.Client/Program.cs
+++ b/save-points/01-Components-and-layout/BlazingPizza.Client/Program.cs
@@ -1,21 +1,11 @@
-using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
-using Microsoft.Extensions.DependencyInjection;
-using System;
-using System.Net.Http;
-using System.Threading.Tasks;
+using BlazingPizza.Client;
+using Microsoft.AspNetCore.Components.Web;
+using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
-namespace BlazingPizza.Client
-{
- public class Program
- {
- public static async Task Main(string[] args)
- {
- var builder = WebAssemblyHostBuilder.CreateDefault(args);
- builder.RootComponents.Add("#app");
+var builder = WebAssemblyHostBuilder.CreateDefault(args);
+builder.RootComponents.Add("#app");
+builder.RootComponents.Add("head::after");
- builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
+builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
- await builder.Build().RunAsync();
- }
- }
-}
+await builder.Build().RunAsync();
diff --git a/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj b/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj
index 5f51ee3c..cb996b1b 100644
--- a/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj
+++ b/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj
@@ -1,7 +1,8 @@
- net5.0
+ $(TargetFrameworkVersion)
+ true
diff --git a/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/LocalStorage.cs b/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/LocalStorage.cs
index f36b098e..be8226ec 100644
--- a/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/LocalStorage.cs
+++ b/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/LocalStorage.cs
@@ -1,17 +1,15 @@
using Microsoft.JSInterop;
-using System.Threading.Tasks;
-namespace BlazingPizza.ComponentsLibrary
+namespace BlazingPizza.ComponentsLibrary;
+
+public static class LocalStorage
{
- public static class LocalStorage
- {
- public static ValueTask GetAsync(IJSRuntime jsRuntime, string key)
+ public static ValueTask GetAsync(IJSRuntime jsRuntime, string key)
=> jsRuntime.InvokeAsync("blazorLocalStorage.get", key);
- public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value)
+ public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value)
=> jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value);
- public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key)
+ public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key)
=> jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key);
- }
-}
+}
\ No newline at end of file
diff --git a/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/Map/Marker.cs b/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/Map/Marker.cs
index 63006067..4761dcd6 100644
--- a/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/Map/Marker.cs
+++ b/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/Map/Marker.cs
@@ -1,13 +1,11 @@
-namespace BlazingPizza.ComponentsLibrary.Map
+namespace BlazingPizza.ComponentsLibrary.Map;
+public class Marker
{
- public class Marker
- {
- public string Description { get; set; }
+ public string Description { get; set; }
- public double X { get; set; }
+ public double X { get; set; }
- public double Y { get; set; }
+ public double Y { get; set; }
- public bool ShowPopup { get; set; }
- }
-}
+ public bool ShowPopup { get; set; }
+}
\ No newline at end of file
diff --git a/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/Map/Point.cs b/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/Map/Point.cs
index 03841826..054e56ec 100644
--- a/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/Map/Point.cs
+++ b/save-points/01-Components-and-layout/BlazingPizza.ComponentsLibrary/Map/Point.cs
@@ -1,9 +1,9 @@
-namespace BlazingPizza.ComponentsLibrary.Map
+namespace BlazingPizza.ComponentsLibrary.Map;
+
+public class Point
{
- public class Point
- {
- public double X { get; set; }
+ public double X { get; set; }
- public double Y { get; set; }
- }
+ public double Y { get; set; }
}
+// Compare this snippet from save-points\01-Components-and-layout\BlazingPizza.ComponentsLibrary\Map\Marker.cs:
\ No newline at end of file
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/BlazingPizza.Server.csproj b/save-points/01-Components-and-layout/BlazingPizza.Server/BlazingPizza.Server.csproj
index fd7e3c51..227890e1 100644
--- a/save-points/01-Components-and-layout/BlazingPizza.Server/BlazingPizza.Server.csproj
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/BlazingPizza.Server.csproj
@@ -1,7 +1,8 @@
- net5.0
+ $(TargetFrameworkVersion)
+ true
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/AddressEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/AddressEntityType.cs
new file mode 100644
index 00000000..82db81b6
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/AddressEntityType.cs
@@ -0,0 +1,92 @@
+//
+using System;
+using System.Reflection;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class AddressEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "BlazingPizza.Address",
+ typeof(Address),
+ baseEntityType);
+
+ var id = runtimeEntityType.AddProperty(
+ "Id",
+ typeof(int),
+ propertyInfo: typeof(Address).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Address).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ valueGenerated: ValueGenerated.OnAdd,
+ afterSaveBehavior: PropertySaveBehavior.Throw);
+
+ var city = runtimeEntityType.AddProperty(
+ "City",
+ typeof(string),
+ propertyInfo: typeof(Address).GetProperty("City", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Address).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 50);
+
+ var line1 = runtimeEntityType.AddProperty(
+ "Line1",
+ typeof(string),
+ propertyInfo: typeof(Address).GetProperty("Line1", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Address).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 100);
+
+ var line2 = runtimeEntityType.AddProperty(
+ "Line2",
+ typeof(string),
+ propertyInfo: typeof(Address).GetProperty("Line2", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Address).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true,
+ maxLength: 100);
+
+ var name = runtimeEntityType.AddProperty(
+ "Name",
+ typeof(string),
+ propertyInfo: typeof(Address).GetProperty("Name", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Address).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 100);
+
+ var postalCode = runtimeEntityType.AddProperty(
+ "PostalCode",
+ typeof(string),
+ propertyInfo: typeof(Address).GetProperty("PostalCode", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Address).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 20);
+
+ var region = runtimeEntityType.AddProperty(
+ "Region",
+ typeof(string),
+ propertyInfo: typeof(Address).GetProperty("Region", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Address).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 20);
+
+ var key = runtimeEntityType.AddKey(
+ new[] { id });
+ runtimeEntityType.SetPrimaryKey(key);
+
+ return runtimeEntityType;
+ }
+
+ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
+ {
+ runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
+ runtimeEntityType.AddAnnotation("Relational:Schema", null);
+ runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
+ runtimeEntityType.AddAnnotation("Relational:TableName", "Address");
+ runtimeEntityType.AddAnnotation("Relational:ViewName", null);
+ runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
+
+ Customize(runtimeEntityType);
+ }
+
+ static partial void Customize(RuntimeEntityType runtimeEntityType);
+ }
+}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/DeviceFlowCodesEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/DeviceFlowCodesEntityType.cs
new file mode 100644
index 00000000..1dd4563b
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/DeviceFlowCodesEntityType.cs
@@ -0,0 +1,114 @@
+//
+using System;
+using System.Reflection;
+using Duende.IdentityServer.EntityFramework.Entities;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class DeviceFlowCodesEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes",
+ typeof(DeviceFlowCodes),
+ baseEntityType);
+
+ var userCode = runtimeEntityType.AddProperty(
+ "UserCode",
+ typeof(string),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("UserCode", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw,
+ maxLength: 200);
+
+ var clientId = runtimeEntityType.AddProperty(
+ "ClientId",
+ typeof(string),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("ClientId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 200);
+
+ var creationTime = runtimeEntityType.AddProperty(
+ "CreationTime",
+ typeof(DateTime),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("CreationTime", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var data = runtimeEntityType.AddProperty(
+ "Data",
+ typeof(string),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("Data", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 50000);
+
+ var description = runtimeEntityType.AddProperty(
+ "Description",
+ typeof(string),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("Description", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true,
+ maxLength: 200);
+
+ var deviceCode = runtimeEntityType.AddProperty(
+ "DeviceCode",
+ typeof(string),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("DeviceCode", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 200);
+
+ var expiration = runtimeEntityType.AddProperty(
+ "Expiration",
+ typeof(DateTime?),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("Expiration", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var sessionId = runtimeEntityType.AddProperty(
+ "SessionId",
+ typeof(string),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("SessionId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true,
+ maxLength: 100);
+
+ var subjectId = runtimeEntityType.AddProperty(
+ "SubjectId",
+ typeof(string),
+ propertyInfo: typeof(DeviceFlowCodes).GetProperty("SubjectId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(DeviceFlowCodes).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true,
+ maxLength: 200);
+
+ var key = runtimeEntityType.AddKey(
+ new[] { userCode });
+ runtimeEntityType.SetPrimaryKey(key);
+
+ var index = runtimeEntityType.AddIndex(
+ new[] { deviceCode },
+ unique: true);
+
+ var index0 = runtimeEntityType.AddIndex(
+ new[] { expiration });
+
+ return runtimeEntityType;
+ }
+
+ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
+ {
+ runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
+ runtimeEntityType.AddAnnotation("Relational:Schema", null);
+ runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
+ runtimeEntityType.AddAnnotation("Relational:TableName", "DeviceCodes");
+ runtimeEntityType.AddAnnotation("Relational:ViewName", null);
+ runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
+
+ Customize(runtimeEntityType);
+ }
+
+ static partial void Customize(RuntimeEntityType runtimeEntityType);
+ }
+}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityRoleClaimstringEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityRoleClaimstringEntityType.cs
new file mode 100644
index 00000000..8946b261
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityRoleClaimstringEntityType.cs
@@ -0,0 +1,85 @@
+//
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class IdentityRoleClaimstringEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "Microsoft.AspNetCore.Identity.IdentityRoleClaim",
+ typeof(IdentityRoleClaim),
+ baseEntityType);
+
+ var id = runtimeEntityType.AddProperty(
+ "Id",
+ typeof(int),
+ propertyInfo: typeof(IdentityRoleClaim).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityRoleClaim).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ valueGenerated: ValueGenerated.OnAdd,
+ afterSaveBehavior: PropertySaveBehavior.Throw);
+
+ var claimType = runtimeEntityType.AddProperty(
+ "ClaimType",
+ typeof(string),
+ propertyInfo: typeof(IdentityRoleClaim).GetProperty("ClaimType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityRoleClaim).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+
+ var claimValue = runtimeEntityType.AddProperty(
+ "ClaimValue",
+ typeof(string),
+ propertyInfo: typeof(IdentityRoleClaim).GetProperty("ClaimValue", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityRoleClaim).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+
+ var roleId = runtimeEntityType.AddProperty(
+ "RoleId",
+ typeof(string),
+ propertyInfo: typeof(IdentityRoleClaim).GetProperty("RoleId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityRoleClaim).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var key = runtimeEntityType.AddKey(
+ new[] { id });
+ runtimeEntityType.SetPrimaryKey(key);
+
+ var index = runtimeEntityType.AddIndex(
+ new[] { roleId });
+
+ return runtimeEntityType;
+ }
+
+ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEntityType, RuntimeEntityType principalEntityType)
+ {
+ var runtimeForeignKey = declaringEntityType.AddForeignKey(new[] { declaringEntityType.FindProperty("RoleId") },
+ principalEntityType.FindKey(new[] { principalEntityType.FindProperty("Id") }),
+ principalEntityType,
+ deleteBehavior: DeleteBehavior.Cascade,
+ required: true);
+
+ return runtimeForeignKey;
+ }
+
+ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
+ {
+ runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
+ runtimeEntityType.AddAnnotation("Relational:Schema", null);
+ runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
+ runtimeEntityType.AddAnnotation("Relational:TableName", "AspNetRoleClaims");
+ runtimeEntityType.AddAnnotation("Relational:ViewName", null);
+ runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
+
+ Customize(runtimeEntityType);
+ }
+
+ static partial void Customize(RuntimeEntityType runtimeEntityType);
+ }
+}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityRoleEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityRoleEntityType.cs
new file mode 100644
index 00000000..2f1fec2b
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityRoleEntityType.cs
@@ -0,0 +1,78 @@
+//
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class IdentityRoleEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "Microsoft.AspNetCore.Identity.IdentityRole",
+ typeof(IdentityRole),
+ baseEntityType);
+
+ var id = runtimeEntityType.AddProperty(
+ "Id",
+ typeof(string),
+ propertyInfo: typeof(IdentityRole).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityRole).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw);
+
+ var concurrencyStamp = runtimeEntityType.AddProperty(
+ "ConcurrencyStamp",
+ typeof(string),
+ propertyInfo: typeof(IdentityRole).GetProperty("ConcurrencyStamp", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityRole).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true,
+ concurrencyToken: true);
+
+ var name = runtimeEntityType.AddProperty(
+ "Name",
+ typeof(string),
+ propertyInfo: typeof(IdentityRole).GetProperty("Name", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityRole).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true,
+ maxLength: 256);
+
+ var normalizedName = runtimeEntityType.AddProperty(
+ "NormalizedName",
+ typeof(string),
+ propertyInfo: typeof(IdentityRole).GetProperty("NormalizedName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityRole).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true,
+ maxLength: 256);
+
+ var key = runtimeEntityType.AddKey(
+ new[] { id });
+ runtimeEntityType.SetPrimaryKey(key);
+
+ var index = runtimeEntityType.AddIndex(
+ new[] { normalizedName },
+ unique: true);
+ index.AddAnnotation("Relational:Name", "RoleNameIndex");
+
+ return runtimeEntityType;
+ }
+
+ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
+ {
+ runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
+ runtimeEntityType.AddAnnotation("Relational:Schema", null);
+ runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
+ runtimeEntityType.AddAnnotation("Relational:TableName", "AspNetRoles");
+ runtimeEntityType.AddAnnotation("Relational:ViewName", null);
+ runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
+
+ Customize(runtimeEntityType);
+ }
+
+ static partial void Customize(RuntimeEntityType runtimeEntityType);
+ }
+}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserClaimstringEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserClaimstringEntityType.cs
new file mode 100644
index 00000000..55418a1e
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserClaimstringEntityType.cs
@@ -0,0 +1,85 @@
+//
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class IdentityUserClaimstringEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "Microsoft.AspNetCore.Identity.IdentityUserClaim",
+ typeof(IdentityUserClaim),
+ baseEntityType);
+
+ var id = runtimeEntityType.AddProperty(
+ "Id",
+ typeof(int),
+ propertyInfo: typeof(IdentityUserClaim).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserClaim).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ valueGenerated: ValueGenerated.OnAdd,
+ afterSaveBehavior: PropertySaveBehavior.Throw);
+
+ var claimType = runtimeEntityType.AddProperty(
+ "ClaimType",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserClaim).GetProperty("ClaimType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserClaim).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+
+ var claimValue = runtimeEntityType.AddProperty(
+ "ClaimValue",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserClaim).GetProperty("ClaimValue", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserClaim).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+
+ var userId = runtimeEntityType.AddProperty(
+ "UserId",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserClaim).GetProperty("UserId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserClaim).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var key = runtimeEntityType.AddKey(
+ new[] { id });
+ runtimeEntityType.SetPrimaryKey(key);
+
+ var index = runtimeEntityType.AddIndex(
+ new[] { userId });
+
+ return runtimeEntityType;
+ }
+
+ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEntityType, RuntimeEntityType principalEntityType)
+ {
+ var runtimeForeignKey = declaringEntityType.AddForeignKey(new[] { declaringEntityType.FindProperty("UserId") },
+ principalEntityType.FindKey(new[] { principalEntityType.FindProperty("Id") }),
+ principalEntityType,
+ deleteBehavior: DeleteBehavior.Cascade,
+ required: true);
+
+ return runtimeForeignKey;
+ }
+
+ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
+ {
+ runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
+ runtimeEntityType.AddAnnotation("Relational:Schema", null);
+ runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
+ runtimeEntityType.AddAnnotation("Relational:TableName", "AspNetUserClaims");
+ runtimeEntityType.AddAnnotation("Relational:ViewName", null);
+ runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
+
+ Customize(runtimeEntityType);
+ }
+
+ static partial void Customize(RuntimeEntityType runtimeEntityType);
+ }
+}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserLoginstringEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserLoginstringEntityType.cs
new file mode 100644
index 00000000..3ca029bd
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserLoginstringEntityType.cs
@@ -0,0 +1,86 @@
+//
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class IdentityUserLoginstringEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "Microsoft.AspNetCore.Identity.IdentityUserLogin",
+ typeof(IdentityUserLogin),
+ baseEntityType);
+
+ var loginProvider = runtimeEntityType.AddProperty(
+ "LoginProvider",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserLogin).GetProperty("LoginProvider", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserLogin).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw,
+ maxLength: 128);
+
+ var providerKey = runtimeEntityType.AddProperty(
+ "ProviderKey",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserLogin).GetProperty("ProviderKey", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserLogin).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw,
+ maxLength: 128);
+
+ var providerDisplayName = runtimeEntityType.AddProperty(
+ "ProviderDisplayName",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserLogin).GetProperty("ProviderDisplayName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserLogin).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+
+ var userId = runtimeEntityType.AddProperty(
+ "UserId",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserLogin).GetProperty("UserId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserLogin).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var key = runtimeEntityType.AddKey(
+ new[] { loginProvider, providerKey });
+ runtimeEntityType.SetPrimaryKey(key);
+
+ var index = runtimeEntityType.AddIndex(
+ new[] { userId });
+
+ return runtimeEntityType;
+ }
+
+ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEntityType, RuntimeEntityType principalEntityType)
+ {
+ var runtimeForeignKey = declaringEntityType.AddForeignKey(new[] { declaringEntityType.FindProperty("UserId") },
+ principalEntityType.FindKey(new[] { principalEntityType.FindProperty("Id") }),
+ principalEntityType,
+ deleteBehavior: DeleteBehavior.Cascade,
+ required: true);
+
+ return runtimeForeignKey;
+ }
+
+ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
+ {
+ runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
+ runtimeEntityType.AddAnnotation("Relational:Schema", null);
+ runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
+ runtimeEntityType.AddAnnotation("Relational:TableName", "AspNetUserLogins");
+ runtimeEntityType.AddAnnotation("Relational:ViewName", null);
+ runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
+
+ Customize(runtimeEntityType);
+ }
+
+ static partial void Customize(RuntimeEntityType runtimeEntityType);
+ }
+}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserRolestringEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserRolestringEntityType.cs
new file mode 100644
index 00000000..70078d7a
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserRolestringEntityType.cs
@@ -0,0 +1,82 @@
+//
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class IdentityUserRolestringEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "Microsoft.AspNetCore.Identity.IdentityUserRole",
+ typeof(IdentityUserRole),
+ baseEntityType);
+
+ var userId = runtimeEntityType.AddProperty(
+ "UserId",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserRole).GetProperty("UserId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserRole).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw);
+
+ var roleId = runtimeEntityType.AddProperty(
+ "RoleId",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserRole).GetProperty("RoleId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserRole).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw);
+
+ var key = runtimeEntityType.AddKey(
+ new[] { userId, roleId });
+ runtimeEntityType.SetPrimaryKey(key);
+
+ var index = runtimeEntityType.AddIndex(
+ new[] { roleId });
+
+ return runtimeEntityType;
+ }
+
+ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEntityType, RuntimeEntityType principalEntityType)
+ {
+ var runtimeForeignKey = declaringEntityType.AddForeignKey(new[] { declaringEntityType.FindProperty("RoleId") },
+ principalEntityType.FindKey(new[] { principalEntityType.FindProperty("Id") }),
+ principalEntityType,
+ deleteBehavior: DeleteBehavior.Cascade,
+ required: true);
+
+ return runtimeForeignKey;
+ }
+
+ public static RuntimeForeignKey CreateForeignKey2(RuntimeEntityType declaringEntityType, RuntimeEntityType principalEntityType)
+ {
+ var runtimeForeignKey = declaringEntityType.AddForeignKey(new[] { declaringEntityType.FindProperty("UserId") },
+ principalEntityType.FindKey(new[] { principalEntityType.FindProperty("Id") }),
+ principalEntityType,
+ deleteBehavior: DeleteBehavior.Cascade,
+ required: true);
+
+ return runtimeForeignKey;
+ }
+
+ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
+ {
+ runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
+ runtimeEntityType.AddAnnotation("Relational:Schema", null);
+ runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
+ runtimeEntityType.AddAnnotation("Relational:TableName", "AspNetUserRoles");
+ runtimeEntityType.AddAnnotation("Relational:ViewName", null);
+ runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
+
+ Customize(runtimeEntityType);
+ }
+
+ static partial void Customize(RuntimeEntityType runtimeEntityType);
+ }
+}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserTokenstringEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserTokenstringEntityType.cs
new file mode 100644
index 00000000..93ba6d31
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/IdentityUserTokenstringEntityType.cs
@@ -0,0 +1,84 @@
+//
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class IdentityUserTokenstringEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "Microsoft.AspNetCore.Identity.IdentityUserToken",
+ typeof(IdentityUserToken),
+ baseEntityType);
+
+ var userId = runtimeEntityType.AddProperty(
+ "UserId",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserToken).GetProperty("UserId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserToken).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw);
+
+ var loginProvider = runtimeEntityType.AddProperty(
+ "LoginProvider",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserToken).GetProperty("LoginProvider", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserToken).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw,
+ maxLength: 128);
+
+ var name = runtimeEntityType.AddProperty(
+ "Name",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserToken).GetProperty("Name", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserToken).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw,
+ maxLength: 128);
+
+ var value = runtimeEntityType.AddProperty(
+ "Value",
+ typeof(string),
+ propertyInfo: typeof(IdentityUserToken).GetProperty("Value", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(IdentityUserToken).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+
+ var key = runtimeEntityType.AddKey(
+ new[] { userId, loginProvider, name });
+ runtimeEntityType.SetPrimaryKey(key);
+
+ return runtimeEntityType;
+ }
+
+ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEntityType, RuntimeEntityType principalEntityType)
+ {
+ var runtimeForeignKey = declaringEntityType.AddForeignKey(new[] { declaringEntityType.FindProperty("UserId") },
+ principalEntityType.FindKey(new[] { principalEntityType.FindProperty("Id") }),
+ principalEntityType,
+ deleteBehavior: DeleteBehavior.Cascade,
+ required: true);
+
+ return runtimeForeignKey;
+ }
+
+ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
+ {
+ runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
+ runtimeEntityType.AddAnnotation("Relational:Schema", null);
+ runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
+ runtimeEntityType.AddAnnotation("Relational:TableName", "AspNetUserTokens");
+ runtimeEntityType.AddAnnotation("Relational:ViewName", null);
+ runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
+
+ Customize(runtimeEntityType);
+ }
+
+ static partial void Customize(RuntimeEntityType runtimeEntityType);
+ }
+}
diff --git a/save-points/01-Components-and-layout/BlazingPizza.Server/Models/KeyEntityType.cs b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/KeyEntityType.cs
new file mode 100644
index 00000000..f6c6b4c7
--- /dev/null
+++ b/save-points/01-Components-and-layout/BlazingPizza.Server/Models/KeyEntityType.cs
@@ -0,0 +1,96 @@
+//
+using System;
+using System.Reflection;
+using Duende.IdentityServer.EntityFramework.Entities;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+#pragma warning disable 219, 612, 618
+#nullable disable
+
+namespace BlazingPizza.Server.Models
+{
+ internal partial class KeyEntityType
+ {
+ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
+ {
+ var runtimeEntityType = model.AddEntityType(
+ "Duende.IdentityServer.EntityFramework.Entities.Key",
+ typeof(Key),
+ baseEntityType);
+
+ var id = runtimeEntityType.AddProperty(
+ "Id",
+ typeof(string),
+ propertyInfo: typeof(Key).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Key).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ afterSaveBehavior: PropertySaveBehavior.Throw);
+
+ var algorithm = runtimeEntityType.AddProperty(
+ "Algorithm",
+ typeof(string),
+ propertyInfo: typeof(Key).GetProperty("Algorithm", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Key).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ maxLength: 100);
+
+ var created = runtimeEntityType.AddProperty(
+ "Created",
+ typeof(DateTime),
+ propertyInfo: typeof(Key).GetProperty("Created", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Key).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var data = runtimeEntityType.AddProperty(
+ "Data",
+ typeof(string),
+ propertyInfo: typeof(Key).GetProperty("Data", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Key).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var dataProtected = runtimeEntityType.AddProperty(
+ "DataProtected",
+ typeof(bool),
+ propertyInfo: typeof(Key).GetProperty("DataProtected", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Key).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var isX509Certificate = runtimeEntityType.AddProperty(
+ "IsX509Certificate",
+ typeof(bool),
+ propertyInfo: typeof(Key).GetProperty("IsX509Certificate", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Key).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+ var use = runtimeEntityType.AddProperty(
+ "Use",
+ typeof(string),
+ propertyInfo: typeof(Key).GetProperty("Use", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(Key).GetField("