add number & boolean formatting, replace httpclientfactory with httpclient with base url, add requset message to brp page
- author
- Marijn Besseling <njirambem@gmail.com> · 2025-10-19 19:55 UTC
- commit
- af13f6fd659fb87419462fc439e594afe6790873
- parent
- f9b74d4e2b
- tree
- browse at this commit
9 files changed +113 -28
Blog.sln.DotSettings.user +1 -0
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
| 2 | 2 | <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHeadOutlet_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fdcd84564511e5d72ea56976dd9d171b16c109cd0bb4e027b3d533fd3fdfe2e_003FHeadOutlet_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> |
| 3 | 3 | <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonElement_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F579deeb0a45a829a4e9f827e296d7f339cefa86c77069fa79a05cd9546833_003FJsonElement_002Ecs_002Fz_003A2_002D1/@EntryIndexedValue">ForceIncluded</s:String> |
| 4 | + <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonValueKind_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb12ab569f0e04711a2c9a45d25736ac21f5328_003Ffe_003F47afc792_003FJsonValueKind_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | |
| 4 | 5 | <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANavLink_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fa7e0df76d83fa82349aeb3c67daa309819443bc460287f2f925a61b719635f2_003FNavLink_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> |
| 5 | 6 | <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATaskAwaiter_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F24276f5a960c41c7b74713aa84cb1cae4672f89e225b6dcd2fe9b297a3a39_003FTaskAwaiter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> |
| No newline at end of file | ||
Blog/Components/Pages/BRP.razor +11 -2
| @@ -1,8 +1,17 @@ | ||
| 1 | 1 | "/BRP/{BSN}" |
| 2 | - System.Text.Json | |
| 3 | 2 | <PageTitle>BRP</PageTitle> |
| 4 | 3 | |
| 5 | 4 | <main> |
| 6 | - <JsonRender Element="Entry?.RootElement"></JsonRender> | |
| 5 | + <div> | |
| 6 | + <details> | |
| 7 | + <summary><h1>Request</h1></summary> | |
| 8 | + <JsonRender Element="RequestBody?.RootElement"></JsonRender> | |
| 9 | + </details> | |
| 10 | + </div> | |
| 11 | + <div> | |
| 12 | + <h1>Response</h1> | |
| 13 | + <JsonRender Element="Entry?.RootElement"> | |
| 14 | + </JsonRender> | |
| 15 | + </div> | |
| 7 | 16 | </main> |
| 8 | 17 | |
Blog/Components/Pages/BRP.razor.cs +3 -2
| @@ -2,7 +2,6 @@ using System.Text.Json; | ||
| 2 | 2 | using System.Text.RegularExpressions; |
| 3 | 3 | using Blog.Services; |
| 4 | 4 | using Microsoft.AspNetCore.Components; |
| 5 | -using Microsoft.AspNetCore.Mvc; | |
| 6 | 5 | |
| 7 | 6 | namespace Blog.Components.Pages; |
| 8 | 7 | |
| @@ -13,12 +12,14 @@ public partial class BRP : ComponentBase | ||
| 13 | 12 | |
| 14 | 13 | |
| 15 | 14 | public required BrpService Service { get; set; } |
| 15 | + | |
| 16 | + private JsonDocument RequestBody { get; set; } | |
| 16 | 17 | |
| 17 | 18 | private JsonDocument Entry { get; set; } |
| 18 | 19 | |
| 19 | 20 | protected override async Task OnInitializedAsync() |
| 20 | 21 | { |
| 21 | - Entry = await Service.GetBrpEntryAsync(BSN).ConfigureAwait(true); | |
| 22 | + (RequestBody, Entry) = await Service.GetBrpEntryAsync(BSN).ConfigureAwait(true); | |
| 22 | 23 | await base.OnInitializedAsync(); |
| 23 | 24 | } |
| 24 | 25 | |
Blog/Components/Pages/BrpTestData.razor +9 -7
| @@ -2,11 +2,13 @@ | ||
| 2 | 2 | <PageTitle>BRP Test Data</PageTitle> |
| 3 | 3 | |
| 4 | 4 | <main> |
| 5 | - (var entry in Entries) | |
| 6 | - { | |
| 7 | - <div> | |
| 8 | - <NavLink href=@($"/BRP/{@entry.bsn}")></NavLink> | |
| 9 | - | |
| 10 | - </div> | |
| 11 | - } | |
| 5 | + <div class="two-column"> | |
| 6 | + (var entry in Entries) | |
| 7 | + { | |
| 8 | + <div> | |
| 9 | + <NavLink href=@($"/BRP/{@entry.bsn}")></NavLink> | |
| 10 | + | |
| 11 | + </div> | |
| 12 | + } | |
| 13 | + </div> | |
| 12 | 14 | </main> |
| No newline at end of file | ||
Blog/Components/_Shared/JsonRender.razor +23 -1
| @@ -4,6 +4,7 @@ | ||
| 4 | 4 | |
| 5 | 5 | [Parameter] |
| 6 | 6 | public JsonElement? Element { get; set; } |
| 7 | + | |
| 7 | 8 | } |
| 8 | 9 | (Element is { } element) |
| 9 | 10 | { |
| @@ -14,7 +15,7 @@ | ||
| 14 | 15 | <ul> |
| 15 | 16 | (var property in element.EnumerateObject()) |
| 16 | 17 | { |
| 17 | - <li> | |
| 18 | + <li class="dash"> | |
| 18 | 19 | <span class="name"></span> |
| 19 | 20 | <JsonRender Element="property.Value"/> |
| 20 | 21 | </li> |
| @@ -45,6 +46,27 @@ | ||
| 45 | 46 | { |
| 46 | 47 | <span></span> |
| 47 | 48 | } |
| 49 | + | |
| 50 | + break; | |
| 51 | + } | |
| 52 | + case JsonValueKind.Null: | |
| 53 | + { | |
| 54 | + <span>Null</span> | |
| 55 | + break; | |
| 56 | + } | |
| 57 | + case JsonValueKind.True: | |
| 58 | + { | |
| 59 | + <span class="json-true">True</span> | |
| 60 | + break; | |
| 61 | + } | |
| 62 | + case JsonValueKind.False: | |
| 63 | + { | |
| 64 | + <span class="json-false">False</span> | |
| 65 | + break; | |
| 66 | + } | |
| 67 | + case JsonValueKind.Number: | |
| 68 | + { | |
| 69 | + <span class="json-number">()</span> | |
| 48 | 70 | break; |
| 49 | 71 | } |
| 50 | 72 | } |
Blog/Models/RaadpleegMetBurgerservicenummer.cs +24 -0
| @@ -0,0 +1,24 @@ | ||
| 1 | +namespace Blog.Models; | |
| 2 | + | |
| 3 | +public record RaadpleegMetBurgerservicenummer | |
| 4 | +{ | |
| 5 | + private const string _type = "RaadpleegMetBurgerservicenummer"; | |
| 6 | + private static readonly string[] _fields = | |
| 7 | + [ | |
| 8 | + "aNummer", "adressering", "burgerservicenummer", "datumEersteInschrijvingGBA", | |
| 9 | + "datumInschrijvingInGemeente", "europeesKiesrecht", "geboorte", "gemeenteVanInschrijving", | |
| 10 | + "geslacht", "gezag", "immigratie", "indicatieCurateleRegister", "kinderen", "leeftijd", "naam", | |
| 11 | + "nationaliteiten", "ouders", "overlijden", "partners", "uitsluitingKiesrecht", "verblijfplaats", | |
| 12 | + "verblijfstitel", "verblijfplaatsBinnenland", "adresseringBinnenland" | |
| 13 | + ]; | |
| 14 | + | |
| 15 | + | |
| 16 | + public string Type => _type; | |
| 17 | + public string[] Fields => _fields; | |
| 18 | + public string[] Burgerservicenummer { get; init; } | |
| 19 | + | |
| 20 | + public RaadpleegMetBurgerservicenummer(string bsn) | |
| 21 | + { | |
| 22 | + Burgerservicenummer = [ bsn ]; | |
| 23 | + } | |
| 24 | +} | |
| No newline at end of file | ||
Blog/Program.cs +12 -3
| @@ -4,11 +4,19 @@ using Blog.Services; | ||
| 4 | 4 | var builder = WebApplication.CreateBuilder(args); |
| 5 | 5 | |
| 6 | 6 | // Add services to the container. |
| 7 | -builder.Services.AddRazorComponents(); | |
| 7 | +builder.Services.AddRazorComponents() | |
| 8 | + .AddInteractiveServerComponents(); | |
| 8 | 9 | |
| 9 | 10 | builder.Services.AddHttpClient(); |
| 10 | 11 | builder.Services.AddHybridCache(); |
| 11 | -builder.Services.AddSingleton<BrpService>(); | |
| 12 | +builder.Services.AddHttpClient<BrpService>( | |
| 13 | + client => | |
| 14 | + { | |
| 15 | + client.BaseAddress = new Uri("https://brp.bes.is/"); | |
| 16 | + }); | |
| 17 | + | |
| 18 | +// builder.Services.AddTransient<BrpService>(); | |
| 19 | +// builder.Services.AddTransient<NsService>(); | |
| 12 | 20 | |
| 13 | 21 | var app = builder.Build(); |
| 14 | 22 | |
| @@ -25,6 +33,7 @@ app.UseHttpsRedirection(); | ||
| 25 | 33 | app.UseAntiforgery(); |
| 26 | 34 | |
| 27 | 35 | app.MapStaticAssets(); |
| 28 | -app.MapRazorComponents<App>(); | |
| 36 | +app.MapRazorComponents<App>() | |
| 37 | + .AddInteractiveServerRenderMode(); | |
| 29 | 38 | |
| 30 | 39 | app.Run(); |
| No newline at end of file | ||
Blog/Services/BrpService.cs +11 -12
| @@ -4,7 +4,7 @@ using Microsoft.Extensions.Caching.Hybrid; | ||
| 4 | 4 | |
| 5 | 5 | namespace Blog.Services; |
| 6 | 6 | |
| 7 | -public class BrpService(HybridCache cache, IHttpClientFactory httpClientFactory) | |
| 7 | +public class BrpService(HybridCache cache, HttpClient client) | |
| 8 | 8 | { |
| 9 | 9 | public async Task<BRPEntry[]> GetBrpEntriesAsync(CancellationToken cancellationToken = default) |
| 10 | 10 | { |
| @@ -21,7 +21,7 @@ public class BrpService(HybridCache cache, IHttpClientFactory httpClientFactory) | ||
| 21 | 21 | .ConfigureAwait(false); |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | - public async Task<JsonDocument> GetBrpEntryAsync(string bsn, CancellationToken cancellationToken = default) | |
| 24 | + public async Task<(JsonDocument request, JsonDocument response)> GetBrpEntryAsync(string bsn, CancellationToken cancellationToken = default) | |
| 25 | 25 | { |
| 26 | 26 | return await cache.GetOrCreateAsync( |
| 27 | 27 | $"brp/{bsn}", |
| @@ -31,21 +31,20 @@ public class BrpService(HybridCache cache, IHttpClientFactory httpClientFactory) | ||
| 31 | 31 | .ConfigureAwait(false); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | - private async Task<JsonDocument> FetchBrpEntryAsync(string bsn, CancellationToken cancellationToken) | |
| 34 | + private async Task<(JsonDocument request, JsonDocument response)> FetchBrpEntryAsync(string bsn, CancellationToken cancellationToken) | |
| 35 | 35 | { |
| 36 | - var client = httpClientFactory.CreateClient("brp"); | |
| 37 | 36 | var response = await client.PostAsJsonAsync( |
| 38 | - "https://brp.bes.is/haalcentraal/api/brp/personen", | |
| 39 | - new | |
| 40 | - { | |
| 41 | - type = "RaadpleegMetBurgerservicenummer", | |
| 42 | - burgerservicenummer = new[] { bsn }, | |
| 43 | - fields = new[] {"aNummer","adressering","burgerservicenummer","datumEersteInschrijvingGBA","datumInschrijvingInGemeente","europeesKiesrecht","geboorte","gemeenteVanInschrijving","geslacht","gezag","immigratie","indicatieCurateleRegister","kinderen","leeftijd","naam","nationaliteiten","ouders","overlijden","partners","uitsluitingKiesrecht","verblijfplaats","verblijfstitel","verblijfplaatsBinnenland","adresseringBinnenland"}, | |
| 44 | - }, | |
| 37 | + "haalcentraal/api/brp/personen", | |
| 38 | + new RaadpleegMetBurgerservicenummer(bsn), | |
| 45 | 39 | cancellationToken) |
| 46 | 40 | .ConfigureAwait(false); |
| 47 | 41 | |
| 48 | 42 | await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); |
| 49 | - return await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken).ConfigureAwait(false); | |
| 43 | + var responseDocument = await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken).ConfigureAwait(false); | |
| 44 | + | |
| 45 | + await using var requestStream = await response.RequestMessage!.Content!.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); | |
| 46 | + var requestDocument = await JsonDocument.ParseAsync(requestStream, cancellationToken: cancellationToken).ConfigureAwait(false); | |
| 47 | + | |
| 48 | + return (requestDocument, responseDocument); | |
| 50 | 49 | } |
| 51 | 50 | } |
| No newline at end of file | ||
Blog/wwwroot/app.css +19 -1
| @@ -39,7 +39,7 @@ h1:focus { | ||
| 39 | 39 | |
| 40 | 40 | * { |
| 41 | 41 | box-sizing: border-box; |
| 42 | - font-size: calc(1rem + 0.5vw); | |
| 42 | + font-size: calc(1rem + 0.4vw); | |
| 43 | 43 | font-family: monospace; |
| 44 | 44 | } |
| 45 | 45 | |
| @@ -48,6 +48,7 @@ h1:focus { | ||
| 48 | 48 | : #fafafa; |
| 49 | 49 | : #da0000; |
| 50 | 50 | : #669aba; |
| 51 | + : #5fbb5d; | |
| 51 | 52 | |
| 52 | 53 | : 1.5; |
| 53 | 54 | : 1rem; |
| @@ -248,6 +249,10 @@ footer > ul { | ||
| 248 | 249 | columns: 2; |
| 249 | 250 | } |
| 250 | 251 | |
| 252 | +.two-column { | |
| 253 | + columns: 2; | |
| 254 | +} | |
| 255 | + | |
| 251 | 256 | legend::before { |
| 252 | 257 | content: "( "; |
| 253 | 258 | } |
| @@ -298,3 +303,16 @@ span.name { | ||
| 298 | 303 | li.dash { |
| 299 | 304 | list-style-type: "- "; |
| 300 | 305 | } |
| 306 | + | |
| 307 | +.json-true { | |
| 308 | + color: var(); | |
| 309 | +} | |
| 310 | + | |
| 311 | +.json-false { | |
| 312 | + color: var(); | |
| 313 | +} | |
| 314 | + | |
| 315 | +.json-number { | |
| 316 | + color: var(); | |
| 317 | +} | |
| 318 | + | |