From 3c1c8e490b9b04185435a434f6cf3b5a2ab82687 Mon Sep 17 00:00:00 2001 From: Antonio Costa Date: Wed, 27 Aug 2025 12:06:36 +0100 Subject: [PATCH] Implement Refit Client --- .../AuthorizedHandler.cs | 22 +++++++++++ .../Components/Pages/Home.razor.cs | 15 +++++++- .../Pages/ShoppingListPage.razor.cs | 2 +- POC.CodelessAPIClient.WebApp/Configs.cs | 7 ++++ .../HttpClients/AuthFakeClient.cs | 6 --- .../HttpClients/FakeClient.cs | 38 ------------------- .../HttpClients/IAuthorizedClient.cs | 2 + .../HttpClients/IClient.cs | 10 ++++- .../POC.CodelessAPIClient.WebApp.csproj | 5 +++ POC.CodelessAPIClient.WebApp/Program.cs | 11 +++++- POC.CodelessAPIClient.WebApp/appsettings.json | 6 ++- 11 files changed, 74 insertions(+), 50 deletions(-) create mode 100644 POC.CodelessAPIClient.WebApp/AuthorizedHandler.cs create mode 100644 POC.CodelessAPIClient.WebApp/Configs.cs delete mode 100644 POC.CodelessAPIClient.WebApp/HttpClients/AuthFakeClient.cs delete mode 100644 POC.CodelessAPIClient.WebApp/HttpClients/FakeClient.cs diff --git a/POC.CodelessAPIClient.WebApp/AuthorizedHandler.cs b/POC.CodelessAPIClient.WebApp/AuthorizedHandler.cs new file mode 100644 index 0000000..8908ee8 --- /dev/null +++ b/POC.CodelessAPIClient.WebApp/AuthorizedHandler.cs @@ -0,0 +1,22 @@ +namespace POC.CodelessAPIClient.WebApp; + +public class AuthorizedHandler : DelegatingHandler +{ + private readonly string _apiBearerToken; + + public AuthorizedHandler(string apiBearerToken) + { + //_apiBearerToken = "asdasdasd"; + _apiBearerToken = apiBearerToken; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + if (!string.IsNullOrWhiteSpace(_apiBearerToken)) + { + request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiBearerToken); + } + + return await base.SendAsync(request, cancellationToken); + } +} \ No newline at end of file diff --git a/POC.CodelessAPIClient.WebApp/Components/Pages/Home.razor.cs b/POC.CodelessAPIClient.WebApp/Components/Pages/Home.razor.cs index 92a5c64..67c18b8 100644 --- a/POC.CodelessAPIClient.WebApp/Components/Pages/Home.razor.cs +++ b/POC.CodelessAPIClient.WebApp/Components/Pages/Home.razor.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Components; using POC.CodelessAPIClient.WebApp.HttpClients; +using Refit; namespace POC.CodelessAPIClient.WebApp.Components.Pages; @@ -13,8 +14,20 @@ protected override async Task OnAfterRenderAsync(bool firstRender) await base.OnAfterRenderAsync(firstRender); if (firstRender) { - _authString = await AuthClient.GetAuthorization(); + await GetAuthorized(); StateHasChanged(); } } + + private async Task GetAuthorized() + { + try + { + _authString = await AuthClient.GetAuthorization(); + } + catch (ApiException ex) + { + _authString = ex.ReasonPhrase; + } + } } \ No newline at end of file diff --git a/POC.CodelessAPIClient.WebApp/Components/Pages/ShoppingListPage.razor.cs b/POC.CodelessAPIClient.WebApp/Components/Pages/ShoppingListPage.razor.cs index 1e936bf..6e0e776 100644 --- a/POC.CodelessAPIClient.WebApp/Components/Pages/ShoppingListPage.razor.cs +++ b/POC.CodelessAPIClient.WebApp/Components/Pages/ShoppingListPage.razor.cs @@ -73,7 +73,7 @@ private async Task DeleteItem(ShoppingListItem item) { _isLoading = true; StateHasChanged(); - await Client.RemoveItem(item); + await Client.RemoveItem(item.Id!.Value); await RefreshList(); diff --git a/POC.CodelessAPIClient.WebApp/Configs.cs b/POC.CodelessAPIClient.WebApp/Configs.cs new file mode 100644 index 0000000..ce4420d --- /dev/null +++ b/POC.CodelessAPIClient.WebApp/Configs.cs @@ -0,0 +1,7 @@ +namespace POC.CodelessAPIClient.WebApp; + +public class Configs +{ + public string ApiUrl { get; set; } + public string ApiBearerToken { get; set; } +} \ No newline at end of file diff --git a/POC.CodelessAPIClient.WebApp/HttpClients/AuthFakeClient.cs b/POC.CodelessAPIClient.WebApp/HttpClients/AuthFakeClient.cs deleted file mode 100644 index 4333784..0000000 --- a/POC.CodelessAPIClient.WebApp/HttpClients/AuthFakeClient.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace POC.CodelessAPIClient.WebApp.HttpClients; - -public class AuthFakeClient : IAuthorizedClient -{ - public Task GetAuthorization() => Task.FromResult("Authorized"); -} \ No newline at end of file diff --git a/POC.CodelessAPIClient.WebApp/HttpClients/FakeClient.cs b/POC.CodelessAPIClient.WebApp/HttpClients/FakeClient.cs deleted file mode 100644 index 2f5e1a1..0000000 --- a/POC.CodelessAPIClient.WebApp/HttpClients/FakeClient.cs +++ /dev/null @@ -1,38 +0,0 @@ -using POC.CodelessAPIClient.Models; - -namespace POC.CodelessAPIClient.WebApp.HttpClients; - -public class FakeClient : IClient -{ - private ShoppingList _shoppingList; - public FakeClient() - { - _shoppingList = new Models.ShoppingList() - { - Name = "Shopping List for Tesco", - Date = DateTime.UtcNow - }; - } - - public Task Get() => Task.FromResult(_shoppingList); - - public Task AddItem(ShoppingListItem item) - { - item.Id ??= Guid.NewGuid(); - _shoppingList.Add(item); - return Task.FromResult(_shoppingList); - } - - public Task UpdateItem(ShoppingListItem item) - { - var existingItem = _shoppingList.Single(x => x.Id == item.Id); - _shoppingList[_shoppingList.IndexOf(existingItem)] = item; - return Task.FromResult(_shoppingList); - } - - public Task RemoveItem(ShoppingListItem item) - { - _shoppingList.RemoveAll(x => x.Id == item.Id); - return Task.FromResult(_shoppingList); - } -} \ No newline at end of file diff --git a/POC.CodelessAPIClient.WebApp/HttpClients/IAuthorizedClient.cs b/POC.CodelessAPIClient.WebApp/HttpClients/IAuthorizedClient.cs index 7ab3e4e..b65d502 100644 --- a/POC.CodelessAPIClient.WebApp/HttpClients/IAuthorizedClient.cs +++ b/POC.CodelessAPIClient.WebApp/HttpClients/IAuthorizedClient.cs @@ -1,8 +1,10 @@ using POC.CodelessAPIClient.Models; +using Refit; namespace POC.CodelessAPIClient.WebApp.HttpClients; public interface IAuthorizedClient { + [Get("/SecureStatus")] Task GetAuthorization(); } \ No newline at end of file diff --git a/POC.CodelessAPIClient.WebApp/HttpClients/IClient.cs b/POC.CodelessAPIClient.WebApp/HttpClients/IClient.cs index 0bc7836..ab1310c 100644 --- a/POC.CodelessAPIClient.WebApp/HttpClients/IClient.cs +++ b/POC.CodelessAPIClient.WebApp/HttpClients/IClient.cs @@ -1,11 +1,19 @@ using POC.CodelessAPIClient.Models; +using Refit; namespace POC.CodelessAPIClient.WebApp.HttpClients; public interface IClient { + [Get("/ShoppingList")] Task Get(); + + [Post("/ShoppingList")] Task AddItem(ShoppingListItem item); + + [Put("/ShoppingList")] Task UpdateItem(ShoppingListItem item); - Task RemoveItem(ShoppingListItem item); + + [Delete("/ShoppingList/{id}")] + Task RemoveItem([AliasAs("id")]Guid id); } \ No newline at end of file diff --git a/POC.CodelessAPIClient.WebApp/POC.CodelessAPIClient.WebApp.csproj b/POC.CodelessAPIClient.WebApp/POC.CodelessAPIClient.WebApp.csproj index 1ea91a9..8e39bb4 100644 --- a/POC.CodelessAPIClient.WebApp/POC.CodelessAPIClient.WebApp.csproj +++ b/POC.CodelessAPIClient.WebApp/POC.CodelessAPIClient.WebApp.csproj @@ -10,4 +10,9 @@ + + + + + diff --git a/POC.CodelessAPIClient.WebApp/Program.cs b/POC.CodelessAPIClient.WebApp/Program.cs index dd2bd98..2392a81 100644 --- a/POC.CodelessAPIClient.WebApp/Program.cs +++ b/POC.CodelessAPIClient.WebApp/Program.cs @@ -1,5 +1,6 @@ using POC.CodelessAPIClient.WebApp.Components; using POC.CodelessAPIClient.WebApp.HttpClients; +using Refit; namespace POC.CodelessAPIClient.WebApp; @@ -13,8 +14,14 @@ public static void Main(string[] args) builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + var configs = builder.Configuration.GetSection("Configurations").Get(); + + builder.Services.AddRefitClient() + .ConfigureHttpClient(c => c.BaseAddress = new Uri(configs!.ApiUrl)); + + builder.Services.AddRefitClient() + .ConfigureHttpClient(c => c.BaseAddress = new Uri(configs!.ApiUrl)) + .AddHttpMessageHandler(() => new AuthorizedHandler(configs.ApiBearerToken)); var app = builder.Build(); diff --git a/POC.CodelessAPIClient.WebApp/appsettings.json b/POC.CodelessAPIClient.WebApp/appsettings.json index 10f68b8..dba5697 100644 --- a/POC.CodelessAPIClient.WebApp/appsettings.json +++ b/POC.CodelessAPIClient.WebApp/appsettings.json @@ -5,5 +5,9 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "Configurations": { + "ApiUrl": "http://localhost:5052", + "ApiBearerToken": "your-secret-token" + } }