diff --git a/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj b/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj index cb996b1b..a907e880 100644 --- a/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj +++ b/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj @@ -2,7 +2,8 @@ $(TargetFrameworkVersion) - true + true + enable diff --git a/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Map.razor b/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Map.razor index c2413ac4..4325755e 100644 --- a/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Map.razor +++ b/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Map.razor @@ -5,9 +5,9 @@ @code { string elementId = $"map-{Guid.NewGuid().ToString("D")}"; - + [Parameter] public double Zoom { get; set; } - [Parameter] public List Markers { get; set; } + [Parameter, EditorRequired] public List Markers { get; set; } = new(); protected async override Task OnAfterRenderAsync(bool firstRender) { diff --git a/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Marker.cs b/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Marker.cs index b067719c..d4dcdbad 100644 --- a/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Marker.cs +++ b/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Marker.cs @@ -2,11 +2,11 @@ public class Marker { - public string Description { get; set; } + public string Description { get; set; } = string.Empty; public double X { get; set; } public double Y { get; set; } public bool ShowPopup { get; set; } -} +} \ No newline at end of file diff --git a/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Point.cs b/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Point.cs index 34194163..054e56ec 100644 --- a/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Point.cs +++ b/save-points/03-show-order-status/BlazingPizza.ComponentsLibrary/Map/Point.cs @@ -5,4 +5,5 @@ public class Point public double X { get; set; } public double Y { get; set; } -} \ No newline at end of file +} +// 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/03-show-order-status/BlazingPizza.Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml b/save-points/03-show-order-status/BlazingPizza.Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml index a1b61965..3f740c74 100644 --- a/save-points/03-show-order-status/BlazingPizza.Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml +++ b/save-points/03-show-order-status/BlazingPizza.Server/Areas/Identity/Pages/Shared/_LoginPartial.cshtml @@ -17,7 +17,7 @@ {
- @User.Identity.Name + @User?.Identity?.Name
diff --git a/save-points/03-show-order-status/BlazingPizza.Server/BlazingPizza.Server.csproj b/save-points/03-show-order-status/BlazingPizza.Server/BlazingPizza.Server.csproj index 227890e1..a1043cb6 100644 --- a/save-points/03-show-order-status/BlazingPizza.Server/BlazingPizza.Server.csproj +++ b/save-points/03-show-order-status/BlazingPizza.Server/BlazingPizza.Server.csproj @@ -3,6 +3,7 @@ $(TargetFrameworkVersion) true + enable diff --git a/save-points/03-show-order-status/BlazingPizza.Server/OrdersController.cs b/save-points/03-show-order-status/BlazingPizza.Server/OrdersController.cs index 37e37cc5..a0a99b09 100644 --- a/save-points/03-show-order-status/BlazingPizza.Server/OrdersController.cs +++ b/save-points/03-show-order-status/BlazingPizza.Server/OrdersController.cs @@ -61,12 +61,12 @@ public async Task> PlaceOrder(Order order) // new specials and toppings foreach (var pizza in order.Pizzas) { - pizza.SpecialId = pizza.Special.Id; + pizza.SpecialId = pizza.Special?.Id ?? 0; pizza.Special = null; foreach (var topping in pizza.Toppings) { - topping.ToppingId = topping.Topping.Id; + topping.ToppingId = topping.Topping?.Id ?? 0; topping.Topping = null; } } @@ -75,7 +75,7 @@ public async Task> PlaceOrder(Order order) await _db.SaveChangesAsync(); // In the background, send push notifications if possible - var subscription = await _db.NotificationSubscriptions.Where(e => e.UserId == GetUserId()).SingleOrDefaultAsync(); + var subscription = await _db.NotificationSubscriptions.Where(e => e.UserId == PizzaApiExtensions.GetUserId(HttpContext)).SingleOrDefaultAsync(); if (subscription != null) { _ = TrackAndSendNotificationsAsync(order, subscription); @@ -84,11 +84,6 @@ public async Task> PlaceOrder(Order order) 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 diff --git a/save-points/03-show-order-status/BlazingPizza.Server/PizzaApiExtensions.cs b/save-points/03-show-order-status/BlazingPizza.Server/PizzaApiExtensions.cs index 524ca759..e82b077b 100644 --- a/save-points/03-show-order-status/BlazingPizza.Server/PizzaApiExtensions.cs +++ b/save-points/03-show-order-status/BlazingPizza.Server/PizzaApiExtensions.cs @@ -49,9 +49,11 @@ public static WebApplication MapPizzaApi(this WebApplication app) } - private static string GetUserId(HttpContext context) + public static string GetUserId(HttpContext context) { - return context.User.FindFirstValue(ClaimTypes.NameIdentifier); + string? result = context.User.FindFirstValue(ClaimTypes.NameIdentifier); + if (result is null) throw new UnauthorizedAccessException("User claim was not found."); + return result; } } \ No newline at end of file diff --git a/save-points/03-show-order-status/BlazingPizza.Server/PizzaStoreContext.cs b/save-points/03-show-order-status/BlazingPizza.Server/PizzaStoreContext.cs index 50ac87e4..1505c7af 100644 --- a/save-points/03-show-order-status/BlazingPizza.Server/PizzaStoreContext.cs +++ b/save-points/03-show-order-status/BlazingPizza.Server/PizzaStoreContext.cs @@ -35,4 +35,4 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) // 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/03-show-order-status/BlazingPizza.Server/Startup.cs b/save-points/03-show-order-status/BlazingPizza.Server/Startup.cs new file mode 100644 index 00000000..4a35b695 --- /dev/null +++ b/save-points/03-show-order-status/BlazingPizza.Server/Startup.cs @@ -0,0 +1,69 @@ +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/03-show-order-status/BlazingPizza.Shared/Address.cs b/save-points/03-show-order-status/BlazingPizza.Shared/Address.cs index f2d1daa4..d1a53375 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/Address.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/Address.cs @@ -1,20 +1,18 @@ -using System.ComponentModel.DataAnnotations; - -namespace BlazingPizza; +namespace BlazingPizza; public class Address { public int Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } = string.Empty; - public string Line1 { get; set; } + public string Line1 { get; set; } = string.Empty; - public string Line2 { get; set; } + public string Line2 { get; set; } = string.Empty; - public string City { get; set; } + public string City { get; set; } = string.Empty; - public string Region { get; set; } + public string Region { get; set; } = string.Empty; - public string PostalCode { get; set; } + public string PostalCode { get; set; } = string.Empty; } diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/BlazingPizza.Shared.csproj b/save-points/03-show-order-status/BlazingPizza.Shared/BlazingPizza.Shared.csproj index 075ddd60..785c204e 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/BlazingPizza.Shared.csproj +++ b/save-points/03-show-order-status/BlazingPizza.Shared/BlazingPizza.Shared.csproj @@ -1,13 +1,18 @@  - - $(TargetFrameworkVersion) - BlazingPizza + + $(TargetFrameworkVersion) + BlazingPizza true - + enable + - - - + + + + + + + diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/NotificationSubscription.cs b/save-points/03-show-order-status/BlazingPizza.Shared/NotificationSubscription.cs index 5c99e3f4..16711e31 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/NotificationSubscription.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/NotificationSubscription.cs @@ -2,13 +2,13 @@ public class NotificationSubscription { - public int NotificationSubscriptionId { get; set; } + public required int NotificationSubscriptionId { get; set; } - public string UserId { get; set; } + public required string UserId { get; set; } - public string Url { get; set; } + public required string Url { get; set; } - public string P256dh { get; set; } + public required string P256dh { get; set; } - public string Auth { get; set; } + public required string Auth { get; set; } } diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/Order.cs b/save-points/03-show-order-status/BlazingPizza.Shared/Order.cs index 180ec55b..f1211588 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/Order.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/Order.cs @@ -6,13 +6,15 @@ public class Order { public int OrderId { get; set; } - public string UserId { get; set; } + // Set by the server during POST + public string? UserId { get; set; } public DateTime CreatedTime { get; set; } public Address DeliveryAddress { get; set; } = new Address(); - public LatLong DeliveryLocation { get; set; } + // Set by server during POST + public LatLong? DeliveryLocation { get; set; } public List Pizzas { get; set; } = new List(); diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/OrderWithStatus.cs b/save-points/03-show-order-status/BlazingPizza.Shared/OrderWithStatus.cs index fbfac7af..c0e3495a 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/OrderWithStatus.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/OrderWithStatus.cs @@ -9,16 +9,19 @@ 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; } + // Set from DB + public Order Order { get; set; } = null!; - public string StatusText { get; set; } + // Set from Order + public string StatusText { get; set; } = null!; public bool IsDelivered => StatusText == "Delivered"; - public List MapMarkers { get; set; } + public List MapMarkers { get; set; } = null!; public static OrderWithStatus FromOrder(Order order) { + ArgumentNullException.ThrowIfNull(order.DeliveryLocation); // To simulate a real backend process, we fake status updates based on the amount // of time since the order was placed string statusText; @@ -65,6 +68,7 @@ public static OrderWithStatus FromOrder(Order order) private static LatLong ComputeStartPosition(Order order) { + ArgumentNullException.ThrowIfNull(order.DeliveryLocation); // Random but deterministic based on order ID var rng = new Random(order.OrderId); var distance = 0.01 + rng.NextDouble() * 0.02; diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/Pizza.cs b/save-points/03-show-order-status/BlazingPizza.Shared/Pizza.cs index 2a7a1c29..150de954 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/Pizza.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/Pizza.cs @@ -15,22 +15,24 @@ public class Pizza public int OrderId { get; set; } - public PizzaSpecial Special { get; set; } + public PizzaSpecial? Special { get; set; } public int SpecialId { get; set; } public int Size { get; set; } - public List Toppings { get; set; } + public List Toppings { get; set; } = new(); public decimal GetBasePrice() { + if(Special == null) throw new NullReferenceException($"{nameof(Special)} was null when calculating Base Price."); return ((decimal)Size / (decimal)DefaultSize) * Special.BasePrice; } public decimal GetTotalPrice() { - return GetBasePrice() + Toppings.Sum(t => t.Topping.Price); + if (Toppings.Any(t => t.Topping is null)) throw new NullReferenceException($"{nameof(Toppings)} contained null when calculating the Total Price."); + return GetBasePrice() + Toppings.Sum(t => t.Topping!.Price); } public string GetFormattedTotalPrice() diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/PizzaSpecial.cs b/save-points/03-show-order-status/BlazingPizza.Shared/PizzaSpecial.cs index 1fd9006a..d53ab286 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/PizzaSpecial.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/PizzaSpecial.cs @@ -7,13 +7,13 @@ public class PizzaSpecial { public int Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } = string.Empty; public decimal BasePrice { get; set; } - public string Description { get; set; } + public string Description { get; set; } = string.Empty; - public string ImageUrl { get; set; } + public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); } \ No newline at end of file diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/PizzaTopping.cs b/save-points/03-show-order-status/BlazingPizza.Shared/PizzaTopping.cs index 1c062732..724f1c06 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/PizzaTopping.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/PizzaTopping.cs @@ -2,7 +2,7 @@ public class PizzaTopping { - public Topping Topping { get; set; } + public Topping? Topping { get; set; } public int ToppingId { get; set; } diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/Topping.cs b/save-points/03-show-order-status/BlazingPizza.Shared/Topping.cs index 4eb67ae9..29b9e790 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/Topping.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/Topping.cs @@ -4,7 +4,7 @@ public class Topping { public int Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } = string.Empty; public decimal Price { get; set; } diff --git a/save-points/03-show-order-status/BlazingPizza.Shared/UserInfo.cs b/save-points/03-show-order-status/BlazingPizza.Shared/UserInfo.cs index babb4315..fb0045bf 100644 --- a/save-points/03-show-order-status/BlazingPizza.Shared/UserInfo.cs +++ b/save-points/03-show-order-status/BlazingPizza.Shared/UserInfo.cs @@ -4,6 +4,6 @@ public class UserInfo { public bool IsAuthenticated { get; set; } - public string Name { get; set; } + public string Name { get; set; } = string.Empty; } \ No newline at end of file