From 6c46e06fd565b6ca123a4ee3ccf709891d79973c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20N=C3=A4geli?= Date: Thu, 2 Jan 2025 12:34:22 +0100 Subject: [PATCH] Improve the public Layout builder API - Throw a more meaningful exception if the same segment is added twice to a layout - Do no longer prevent slashes in segment names but threat them as multiple segments --- Modules/Layouting/Provider/LayoutBuilder.cs | 10 +++++++--- .../Acceptance/Modules/Layouting/LayoutTests.cs | 14 +++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Modules/Layouting/Provider/LayoutBuilder.cs b/Modules/Layouting/Provider/LayoutBuilder.cs index 465d30ca..67171ae1 100644 --- a/Modules/Layouting/Provider/LayoutBuilder.cs +++ b/Modules/Layouting/Provider/LayoutBuilder.cs @@ -42,7 +42,7 @@ public LayoutBuilder Index(IHandlerBuilder handler) /// /// The name of the path segment to be handled /// The handler which will handle the segment - public LayoutBuilder Add(string name, IHandler handler) => Add(new HandlerWrapper(handler)); + public LayoutBuilder Add(string name, IHandler handler) => Add(name, new HandlerWrapper(handler)); /// /// Adds a handler that will be invoked for all URLs below @@ -54,10 +54,14 @@ public LayoutBuilder Add(string name, IHandlerBuilder handler) { if (name.Contains('/')) { - throw new ArgumentException("Path seperators are not allowed in the name of the segment.", nameof(name)); + return this.Add(name.Split('/', StringSplitOptions.RemoveEmptyEntries), handler); + } + + if (!RoutedHandlers.TryAdd(name, handler)) + { + throw new InvalidOperationException($"A segment with the name '{name}' has already been added to the layout"); } - RoutedHandlers.Add(name, handler); return this; } diff --git a/Testing/Acceptance/Modules/Layouting/LayoutTests.cs b/Testing/Acceptance/Modules/Layouting/LayoutTests.cs index bdb6009a..5d3309ff 100644 --- a/Testing/Acceptance/Modules/Layouting/LayoutTests.cs +++ b/Testing/Acceptance/Modules/Layouting/LayoutTests.cs @@ -80,10 +80,18 @@ public async Task TestRedirect(TestEngine engine) } [TestMethod] - [ExpectedException(typeof(ArgumentException))] - public void TestIllegalPathCharacters() + [MultiEngineTest] + public async Task TestMultiSegmentInName(TestEngine engine) { - Layout.Create().Add("some/path", Content.From(Resource.FromString("Hello World"))); + var layout = Layout.Create().Add("/api/v1/", Content.From(Resource.FromString("Hello World"))); + + await using var runner = await TestHost.RunAsync(layout, engine: engine); + + using var response = await runner.GetResponseAsync("/api/v1/"); + + await response.AssertStatusAsync(HttpStatusCode.OK); + + Assert.AreEqual("Hello World", await response.GetContentAsync()); } [TestMethod]