Skip to content

Commit 522d3c1

Browse files
committed
Update 08-templated-components
1 parent 6248094 commit 522d3c1

31 files changed

+374
-234
lines changed

docs/08-templated-components.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,22 @@ First, we need to create a delegate that we can pass to the `TemplatedList` that
359359

360360
```html
361361
@code {
362-
Task<List<OrderWithStatus>> LoadOrders()
362+
async Task<List<OrderWithStatus>> LoadOrders()
363363
{
364-
return HttpClient.GetJsonAsync<List<OrderWithStatus>>("orders");
364+
var ordersWithStatus = new List<OrderWithStatus>();
365+
var tokenResult = await TokenProvider.RequestAccessToken();
366+
if (tokenResult.TryGetToken(out var accessToken))
367+
{
368+
var request = new HttpRequestMessage(HttpMethod.Get, "orders");
369+
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);
370+
var response = await HttpClient.SendAsync(request);
371+
ordersWithStatus = await response.Content.ReadFromJsonAsync<List<OrderWithStatus>>();
372+
}
373+
else
374+
{
375+
NavigationManager.NavigateTo(tokenResult.RedirectUrl);
376+
}
377+
return ordersWithStatus;
365378
}
366379
}
367380
```

save-points/08-templated-components/BlazingPizza.Client/App.razor

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@
33
<Found>
44
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)">
55
<NotAuthorized>
6-
<div class="main">
7-
<h2>You're signed out</h2>
8-
<p>To continue, please sign in.</p>
9-
<a class="btn btn-danger" href="user/signin">Sign in</a>
10-
</div>
6+
<RedirectToLogin />
117
</NotAuthorized>
128
<Authorizing>
139
<div class="main">Please wait...</div>
@@ -16,7 +12,7 @@
1612
</Found>
1713
<NotFound>
1814
<LayoutView Layout="typeof(MainLayout)">
19-
<div class="main">Page not found</div>
15+
<div class="main">Sorry, there's nothing at this address.</div>
2016
</LayoutView>
2117
</NotFound>
2218
</Router>

save-points/08-templated-components/BlazingPizza.Client/BlazingPizza.Client.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
<ItemGroup>
1010
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="$(BlazorVersion)" />
1111
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="$(BlazorVersion)" PrivateAssets="all" />
12-
<PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="$(BlazorVersion)" />
13-
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="$(AspNetCoreVersion)" />
12+
<PackageReference Include="System.Net.Http.Json" Version="$(SystemNetHttpJsonVersion)" />
13+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="$(BlazorVersion)" />
1414
</ItemGroup>
1515

1616
<ItemGroup>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
@page "/authentication/{action}"
2+
@inject OrderState OrderState
3+
@inject NavigationManager NavigationManager
4+
5+
<RemoteAuthenticatorViewCore
6+
TAuthenticationState="PizzaAuthenticationState"
7+
AuthenticationState="RemoteAuthenticationState"
8+
OnLogInSucceeded="RestorePizza"
9+
Action="@Action" />
10+
11+
@code{
12+
[Parameter] public string Action { get; set; }
13+
14+
public PizzaAuthenticationState RemoteAuthenticationState { get; set; } = new PizzaAuthenticationState();
15+
16+
protected override void OnInitialized()
17+
{
18+
if (RemoteAuthenticationActions.IsAction(RemoteAuthenticationActions.LogIn, Action))
19+
{
20+
// Preserve the current order so that we don't loose it
21+
RemoteAuthenticationState.Order = OrderState.Order;
22+
}
23+
}
24+
25+
private void RestorePizza(PizzaAuthenticationState pizzaState)
26+
{
27+
if (pizzaState.Order != null)
28+
{
29+
OrderState.ReplaceOrder(pizzaState.Order);
30+
}
31+
}
32+
}
Lines changed: 36 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,53 @@
11
@page "/checkout"
2+
@attribute [Authorize]
23
@inject OrderState OrderState
34
@inject HttpClient HttpClient
45
@inject NavigationManager NavigationManager
5-
@inject IJSRuntime JSRuntime
6+
@inject IAccessTokenProvider TokenProvider
67

78
<div class="main">
8-
<AuthorizeView Context="authContext">
9-
<NotAuthorized>
10-
<h2>Redirecting you...</h2>
11-
</NotAuthorized>
12-
<Authorized>
13-
<EditForm Model="OrderState.Order.DeliveryAddress" OnValidSubmit="PlaceOrder">
14-
<div class="checkout-cols">
15-
<div class="checkout-order-details">
16-
<h4>Review order</h4>
17-
<OrderReview Order="OrderState.Order" />
18-
</div>
19-
20-
<div class="checkout-delivery-address">
21-
<h4>Deliver to...</h4>
22-
<AddressEditor Address="OrderState.Order.DeliveryAddress" />
23-
</div>
24-
</div>
25-
26-
<button type="submit" class="checkout-button btn btn-warning">
27-
Place order
28-
</button>
29-
30-
<DataAnnotationsValidator />
31-
</EditForm>
32-
</Authorized>
33-
</AuthorizeView>
9+
<EditForm Model="OrderState.Order.DeliveryAddress" OnValidSubmit="PlaceOrder">
10+
<div class="checkout-cols">
11+
<div class="checkout-order-details">
12+
<h4>Review order</h4>
13+
<OrderReview Order="OrderState.Order" />
14+
</div>
15+
16+
<div class="checkout-delivery-address">
17+
<h4>Deliver to...</h4>
18+
<AddressEditor Address="OrderState.Order.DeliveryAddress" />
19+
</div>
20+
</div>
21+
22+
<button type="submit" class="checkout-button btn btn-warning" disabled="@isSubmitting">
23+
Place order
24+
</button>
25+
26+
<DataAnnotationsValidator />
27+
</EditForm>
3428
</div>
3529

3630
@code {
37-
[CascadingParameter] public Task<AuthenticationState> AuthenticationStateTask { get; set; }
31+
bool isSubmitting;
3832

39-
protected override async Task OnInitializedAsync()
33+
async Task PlaceOrder()
4034
{
41-
var authState = await AuthenticationStateTask;
42-
if (!authState.User.Identity.IsAuthenticated)
35+
isSubmitting = true;
36+
37+
var tokenResult = await TokenProvider.RequestAccessToken();
38+
if (tokenResult.TryGetToken(out var accessToken))
4339
{
44-
// The server won't accept orders from unauthenticated users, so avoid
45-
// an error by making them log in at this point
46-
await LocalStorage.SetAsync(JSRuntime, "currentorder", OrderState.Order);
47-
NavigationManager.NavigateTo("user/signin?redirectUri=/checkout", true);
40+
var request = new HttpRequestMessage(HttpMethod.Post, "orders");
41+
request.Content = JsonContent.Create(OrderState.Order);
42+
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);
43+
var response = await HttpClient.SendAsync(request);
44+
var newOrderId = await response.Content.ReadFromJsonAsync<int>();
45+
OrderState.ResetOrder();
46+
NavigationManager.NavigateTo($"myorders/{newOrderId}");
4847
}
49-
50-
// Try to recover any temporary saved order
51-
if (!OrderState.Order.Pizzas.Any())
48+
else
5249
{
53-
var savedOrder = await LocalStorage.GetAsync<Order>(JSRuntime, "currentorder");
54-
if (savedOrder != null)
55-
{
56-
OrderState.ReplaceOrder(savedOrder);
57-
await LocalStorage.DeleteAsync(JSRuntime, "currentorder");
58-
}
59-
else
60-
{
61-
// There's nothing check out - go to home
62-
NavigationManager.NavigateTo("");
63-
}
50+
NavigationManager.NavigateTo(tokenResult.RedirectUrl);
6451
}
6552
}
66-
67-
async Task PlaceOrder()
68-
{
69-
var newOrderId = await HttpClient.PostJsonAsync<int>("orders", OrderState.Order);
70-
OrderState.ResetOrder();
71-
NavigationManager.NavigateTo($"myorders/{newOrderId}");
72-
}
7353
}

save-points/08-templated-components/BlazingPizza.Client/Pages/Index.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161

6262
protected override async Task OnInitializedAsync()
6363
{
64-
specials = await HttpClient.GetJsonAsync<List<PizzaSpecial>>("specials");
64+
specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>("specials");
6565
}
6666

6767
async Task RemovePizza(Pizza configuredPizza)

save-points/08-templated-components/BlazingPizza.Client/Pages/MyOrders.razor

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
@page "/myorders"
22
@attribute [Authorize]
33
@inject HttpClient HttpClient
4+
@inject NavigationManager NavigationManager
5+
@inject IAccessTokenProvider TokenProvider
46

57
<div class="main">
68
<TemplatedList Loader="@LoadOrders" ListGroupClass="orders-list">
@@ -32,7 +34,19 @@
3234
@code {
3335
async Task<List<OrderWithStatus>> LoadOrders()
3436
{
35-
await Task.Delay(3000);
36-
return await HttpClient.GetJsonAsync<List<OrderWithStatus>>("orders");
37+
var ordersWithStatus = new List<OrderWithStatus>();
38+
var tokenResult = await TokenProvider.RequestAccessToken();
39+
if (tokenResult.TryGetToken(out var accessToken))
40+
{
41+
var request = new HttpRequestMessage(HttpMethod.Get, "orders");
42+
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);
43+
var response = await HttpClient.SendAsync(request);
44+
ordersWithStatus = await response.Content.ReadFromJsonAsync<List<OrderWithStatus>>();
45+
}
46+
else
47+
{
48+
NavigationManager.NavigateTo(tokenResult.RedirectUrl);
49+
}
50+
return ordersWithStatus;
3751
}
3852
}

save-points/08-templated-components/BlazingPizza.Client/Pages/OrderDetails.razor

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
@attribute [Authorize]
33
@using System.Threading
44
@inject HttpClient HttpClient
5+
@inject NavigationManager NavigationManager
6+
@inject IAccessTokenProvider TokenProvider
57
@implements IDisposable
68

79
<div class="main">
@@ -55,24 +57,35 @@
5557

5658
private async void PollForUpdates()
5759
{
58-
pollingCancellationToken = new CancellationTokenSource();
59-
while (!pollingCancellationToken.IsCancellationRequested)
60+
var tokenResult = await TokenProvider.RequestAccessToken();
61+
if (tokenResult.TryGetToken(out var accessToken))
6062
{
61-
try
63+
pollingCancellationToken = new CancellationTokenSource();
64+
while (!pollingCancellationToken.IsCancellationRequested)
6265
{
63-
invalidOrder = false;
64-
orderWithStatus = await HttpClient.GetJsonAsync<OrderWithStatus>($"orders/{OrderId}");
65-
}
66-
catch (Exception ex)
67-
{
68-
invalidOrder = true;
69-
pollingCancellationToken.Cancel();
70-
Console.Error.WriteLine(ex);
71-
}
66+
try
67+
{
68+
invalidOrder = false;
69+
var request = new HttpRequestMessage(HttpMethod.Get, $"orders/{OrderId}");
70+
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);
71+
var response = await HttpClient.SendAsync(request);
72+
orderWithStatus = await response.Content.ReadFromJsonAsync<OrderWithStatus>();
73+
}
74+
catch (Exception ex)
75+
{
76+
invalidOrder = true;
77+
pollingCancellationToken.Cancel();
78+
Console.Error.WriteLine(ex);
79+
}
7280

73-
StateHasChanged();
81+
StateHasChanged();
7482

75-
await Task.Delay(4000);
83+
await Task.Delay(4000);
84+
}
85+
}
86+
else
87+
{
88+
NavigationManager.NavigateTo(tokenResult.RedirectUrl);
7689
}
7790
}
7891

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
2+
3+
namespace BlazingPizza.Client
4+
{
5+
public class PizzaAuthenticationState : RemoteAuthenticationState
6+
{
7+
public Order Order { get; set; }
8+
}
9+
}

save-points/08-templated-components/BlazingPizza.Client/Program.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Microsoft.AspNetCore.Components.Authorization;
1+
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
22
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
33
using Microsoft.Extensions.DependencyInjection;
44
using System.Threading.Tasks;
@@ -16,9 +16,12 @@ public static async Task Main(string[] args)
1616
builder.Services.AddScoped<OrderState>();
1717

1818
// Add auth services
19-
builder.Services.AddOptions();
20-
builder.Services.AddAuthorizationCore();
21-
builder.Services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
19+
builder.Services.AddRemoteAuthentication<PizzaAuthenticationState, ApiAuthorizationProviderOptions>();
20+
builder.Services.AddApiAuthorization(options =>
21+
{
22+
options.AuthenticationPaths.LogOutSucceededPath = "";
23+
options.ProviderOptions.ConfigurationEndpoint = "_configuration/BlazingPizza.Client"; // temporary workaround
24+
});
2225

2326
await builder.Build().RunAsync();
2427
}

0 commit comments

Comments
 (0)