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 @page "/BRP/{BSN}"
2 -@using 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 [Inject]
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 - @foreach (var entry in Entries)
6 - {
7 - <div>
8 - <NavLink href=@($"/BRP/{@entry.bsn}")>@entry.bsn</NavLink>
9 - @entry.naam
10 - </div>
11 - }
5 + <div class="two-column">
6 + @foreach (var entry in Entries)
7 + {
8 + <div>
9 + <NavLink href=@($"/BRP/{@entry.bsn}")>@entry.bsn</NavLink>
10 + @entry.naam
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 @if (Element is { } element)
9 10 {
@@ -14,7 +15,7 @@
14 15 <ul>
15 16 @foreach (var property in element.EnumerateObject())
16 17 {
17 - <li>
18 + <li class="dash">
18 19 <span class="name">@property.Name</span>
19 20 <JsonRender Element="property.Value"/>
20 21 </li>
@@ -45,6 +46,27 @@
45 46 {
46 47 <span>@value</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">@element.GetDouble()</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 --white: #fafafa;
49 49 --error: #da0000;
50 50 --info: #669aba;
51 + --green: #5fbb5d;
51 52
52 53 --ratio: 1.5;
53 54 --s0: 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(--green);
309 +}
310 +
311 +.json-false {
312 + color: var(--error);
313 +}
314 +
315 +.json-number {
316 + color: var(--info);
317 +}
318 +