Commit 8a853d06 authored by Daniel Roth's avatar Daniel Roth
Browse files

Update to use typed client with authorizing message handler

parent 6e347d50
......@@ -4,7 +4,7 @@
{
@Loading
}
else if (items.Count == 0)
else if (!items.Any())
{
@Empty
}
......@@ -21,9 +21,9 @@ else
}
@code {
List<TItem> items;
IEnumerable<TItem> items;
[Parameter] public Func<Task<List<TItem>>> Loader { get; set; }
[Parameter] public Func<Task<IEnumerable<TItem>>> Loader { get; set; }
[Parameter] public RenderFragment Loading { get; set; }
[Parameter] public RenderFragment Empty { get; set; }
[Parameter] public RenderFragment<TItem> Item { get; set; }
......
......@@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="$(BlazorVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="$(BlazorVersion)" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Http" Version="$(AspNetCoreVersion)" />
<PackageReference Include="System.Net.Http.Json" Version="$(SystemNetHttpJsonVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="$(BlazorVersion)" />
</ItemGroup>
......
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
namespace BlazingPizza.Client
{
public class OrdersClient
{
private readonly HttpClient httpClient;
public OrdersClient(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task<IEnumerable<OrderWithStatus>> GetOrders() =>
await httpClient.GetFromJsonAsync<IEnumerable<OrderWithStatus>>("orders");
public async Task<OrderWithStatus> GetOrder(int orderId) =>
await httpClient.GetFromJsonAsync<OrderWithStatus>($"orders/{orderId}");
public async Task<int> PlaceOrder(Order order)
{
var response = await httpClient.PostAsJsonAsync("orders", order);
response.EnsureSuccessStatusCode();
var orderId = await response.Content.ReadFromJsonAsync<int>();
return orderId;
}
public async Task SubscribeToNotifications(NotificationSubscription subscription)
{
var response = await httpClient.PostAsJsonAsync("notifications/subscribe", subscription);
response.EnsureSuccessStatusCode();
}
}
}
@page "/checkout"
@attribute [Authorize]
@inject OrderState OrderState
@inject HttpClient HttpClient
@inject NavigationManager NavigationManager
@inject IAccessTokenProvider TokenProvider
@inject OrdersClient OrdersClient
@inject IJSRuntime JSRuntime
<div class="main">
......@@ -39,21 +38,17 @@
async Task RequestNotificationSubscriptionAsync()
{
var tokenResult = await TokenProvider.RequestAccessToken();
if (tokenResult.TryGetToken(out var accessToken))
var subscription = await JSRuntime.InvokeAsync<NotificationSubscription>("blazorPushNotifications.requestSubscription");
if (subscription != null)
{
var subscription = await JSRuntime.InvokeAsync<NotificationSubscription>("blazorPushNotifications.requestSubscription");
if (subscription != null)
try
{
var request = new HttpRequestMessage(HttpMethod.Put, "notifications/subscribe");
request.Content = JsonContent.Create(subscription);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);
await HttpClient.SendAsync(request);
await OrdersClient.SubscribeToNotifications(subscription);
}
catch (AccessTokenNotAvailableException ex)
{
ex.Redirect();
}
}
else
{
NavigationManager.NavigateTo(tokenResult.RedirectUrl);
}
}
......@@ -61,20 +56,15 @@
{
isSubmitting = true;
var tokenResult = await TokenProvider.RequestAccessToken();
if (tokenResult.TryGetToken(out var accessToken))
try
{
var request = new HttpRequestMessage(HttpMethod.Post, "orders");
request.Content = JsonContent.Create(OrderState.Order);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);
var response = await HttpClient.SendAsync(request);
var newOrderId = await response.Content.ReadFromJsonAsync<int>();
var newOrderId = await OrdersClient.PlaceOrder(OrderState.Order);
OrderState.ResetOrder();
NavigationManager.NavigateTo($"myorders/{newOrderId}");
}
else
catch (AccessTokenNotAvailableException ex)
{
NavigationManager.NavigateTo(tokenResult.RedirectUrl);
ex.Redirect();
}
}
}
@page "/myorders"
@attribute [Authorize]
@inject HttpClient HttpClient
@inject NavigationManager NavigationManager
@inject IAccessTokenProvider TokenProvider
@inject OrdersClient OrdersClient
<div class="main">
<TemplatedList Loader="@LoadOrders" ListGroupClass="orders-list">
......@@ -32,20 +30,16 @@
</div>
@code {
async Task<List<OrderWithStatus>> LoadOrders()
async Task<IEnumerable<OrderWithStatus>> LoadOrders()
{
var ordersWithStatus = new List<OrderWithStatus>();
var tokenResult = await TokenProvider.RequestAccessToken();
if (tokenResult.TryGetToken(out var accessToken))
var ordersWithStatus = Enumerable.Empty<OrderWithStatus>();
try
{
var request = new HttpRequestMessage(HttpMethod.Get, "orders");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);
var response = await HttpClient.SendAsync(request);
ordersWithStatus = await response.Content.ReadFromJsonAsync<List<OrderWithStatus>>();
ordersWithStatus = await OrdersClient.GetOrders();
}
else
catch (AccessTokenNotAvailableException ex)
{
NavigationManager.NavigateTo(tokenResult.RedirectUrl);
ex.Redirect();
}
return ordersWithStatus;
}
......
@page "/myorders/{orderId:int}"
@attribute [Authorize]
@using System.Threading
@inject HttpClient HttpClient
@inject NavigationManager NavigationManager
@inject IAccessTokenProvider TokenProvider
@inject OrdersClient OrdersClient
@implements IDisposable
<div class="main">
......@@ -57,35 +55,28 @@
private async void PollForUpdates()
{
var tokenResult = await TokenProvider.RequestAccessToken();
if (tokenResult.TryGetToken(out var accessToken))
invalidOrder = false;
pollingCancellationToken = new CancellationTokenSource();
while (!pollingCancellationToken.IsCancellationRequested)
{
pollingCancellationToken = new CancellationTokenSource();
while (!pollingCancellationToken.IsCancellationRequested)
try
{
try
{
invalidOrder = false;
var request = new HttpRequestMessage(HttpMethod.Get, $"orders/{OrderId}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);
var response = await HttpClient.SendAsync(request);
orderWithStatus = await response.Content.ReadFromJsonAsync<OrderWithStatus>();
}
catch (Exception ex)
{
invalidOrder = true;
pollingCancellationToken.Cancel();
Console.Error.WriteLine(ex);
}
orderWithStatus = await OrdersClient.GetOrder(OrderId);
StateHasChanged();
await Task.Delay(4000);
}
}
else
{
NavigationManager.NavigateTo(tokenResult.RedirectUrl);
catch (AccessTokenNotAvailableException ex)
{
pollingCancellationToken.Cancel();
ex.Redirect();
}
catch (Exception ex)
{
invalidOrder = true;
pollingCancellationToken.Cancel();
Console.Error.WriteLine(ex);
StateHasChanged();
}
}
}
......
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
......@@ -14,6 +15,8 @@ namespace BlazingPizza.Client
builder.RootComponents.Add<App>("app");
builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddHttpClient<OrdersClient>(client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddScoped<OrderState>();
// Add auth services
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment