From 9fc7f9ff2b7578c9ec6bdc01715543939f8c7215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Goli=C5=84ski?= Date: Thu, 20 Sep 2018 11:36:41 +0200 Subject: [PATCH] Problem: Router doesn't work with root URIs Registering URI containing only app name ('/MyApp') throws an exception --- .../Routing/Middleware/UriHelperTests.cs | 7 +++++++ .../Routing/Middleware/UriHelper.cs | 6 +++++- Starcounter.Startup/Routing/Router.cs | 8 ++++++++ Starcounter.Startup/Strings.Designer.cs | 18 ++++++++++++++++++ Starcounter.Startup/Strings.resx | 6 ++++++ Starcounter.Startup/StringsFormatted.cs | 7 +++++++ 6 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Starcounter.Startup.Tests/Routing/Middleware/UriHelperTests.cs b/Starcounter.Startup.Tests/Routing/Middleware/UriHelperTests.cs index e612fff..7e6de82 100644 --- a/Starcounter.Startup.Tests/Routing/Middleware/UriHelperTests.cs +++ b/Starcounter.Startup.Tests/Routing/Middleware/UriHelperTests.cs @@ -1,12 +1,17 @@ using System; using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using NUnit.Framework; +using Starcounter.Startup.Routing; +using Starcounter.Startup.Routing.Activation; using Starcounter.Startup.Routing.Middleware; namespace Starcounter.Startup.Tests.Routing.Middleware { public class UriHelperTests { + [TestCase("/app/partial", "/app")] [TestCase("/app/partial/dogs", "/app/dogs")] [TestCase("/APP/PARTIAL/dogs", "/app/dogs")] [TestCase("/app/partial/dogs/1", "/app/dogs/1")] @@ -18,6 +23,7 @@ public void TestPartialToPage(string inputPartialUri, string expectedOutput) .Should().BeEquivalentTo(expectedOutput); } + [TestCase("/app", "/app/partial")] [TestCase("/app/dogs", "/app/partial/dogs")] [TestCase("/APP/dogs", "/app/partial/dogs")] [TestCase("/app/dogs/1", "/app/partial/dogs/1")] @@ -30,6 +36,7 @@ public void TestPageToPartial(string inputPageUri, string expectedOutput) } [TestCase("/app/dogs", false)] + [TestCase("/app/partial", true)] [TestCase("/app/partial/dogs/1", true)] [TestCase("/APP/PARTIAL/dogs/1", true)] // Self.GET lowers case of blended URIs [TestCase("/app/partialdogs/2", false)] diff --git a/Starcounter.Startup/Routing/Middleware/UriHelper.cs b/Starcounter.Startup/Routing/Middleware/UriHelper.cs index 46d966b..4adf818 100644 --- a/Starcounter.Startup/Routing/Middleware/UriHelper.cs +++ b/Starcounter.Startup/Routing/Middleware/UriHelper.cs @@ -5,7 +5,7 @@ namespace Starcounter.Startup.Routing.Middleware { public class UriHelper { - private static readonly Regex PartialUriRegex = new Regex($"^/[^/]+{PartialPart}/", RegexOptions.IgnoreCase); + private static readonly Regex PartialUriRegex = new Regex($"^/[^/]+{PartialPart}(/|$)", RegexOptions.IgnoreCase); private static readonly Regex TemplateArgumentRegex = new Regex(Regex.Escape("{?}")); private const string PartialPart = "/partial"; @@ -88,6 +88,10 @@ public static string WithArguments(string uriTemplate, params string[] arguments private static string ExtractApplicationName(string partialUri) { var indexOfSlash = partialUri.IndexOf("/", 1, StringComparison.Ordinal); + if (indexOfSlash == -1) + { + return partialUri.Substring(1); + } var applicationName = partialUri.Substring(1, indexOfSlash - 1); return applicationName; } diff --git a/Starcounter.Startup/Routing/Router.cs b/Starcounter.Startup/Routing/Router.cs index 1511bc1..aaf04c1 100644 --- a/Starcounter.Startup/Routing/Router.cs +++ b/Starcounter.Startup/Routing/Router.cs @@ -36,6 +36,14 @@ public void HandleGet(Type pageType, HandlerOptions handlerOptions = null) foreach (var urlAttribute in urlAttributes) { var pageUri = urlAttribute.Value; + if (pageUri[0] != '/') + { + throw new InvalidOperationException(StringsFormatted.Router_ViewModelRegisteredWithMalformedUri(pageType, pageUri)); + } + if (UriHelper.IsPartialUri(pageUri)) + { + throw new InvalidOperationException(StringsFormatted.Router_ViewModelRegisteredWithPartialUri(pageType, pageUri)); + } if (urlAttribute.External) { HandleGet(pageUri, pageType, handlerOptions); diff --git a/Starcounter.Startup/Strings.Designer.cs b/Starcounter.Startup/Strings.Designer.cs index 2183fb8..27459df 100644 --- a/Starcounter.Startup/Strings.Designer.cs +++ b/Starcounter.Startup/Strings.Designer.cs @@ -213,6 +213,24 @@ internal static string Router_TypeHasNoUrlAttribute { } } + /// + /// Looks up a localized string similar to View-model {0} is registered with malformed URI: '{1}'. URI has to start with a slash sign ('/'). + /// + internal static string Router_ViewModelRegisteredWithMalformedUri { + get { + return ResourceManager.GetString("Router_ViewModelRegisteredWithMalformedUri", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to View-model {0} is registered with partial URI: '{1}'. Use '{2}' instead. + /// + internal static string Router_ViewModelRegisteredWithPartialUri { + get { + return ResourceManager.GetString("Router_ViewModelRegisteredWithPartialUri", resourceCulture); + } + } + /// /// Looks up a localized string similar to Can't fill URI template '{0}' with arguments: provided URI template has {1} slots, but {2} argument(s) were provided. Arguments values: {3}. /// diff --git a/Starcounter.Startup/Strings.resx b/Starcounter.Startup/Strings.resx index f72d2fd..13a2fab 100644 --- a/Starcounter.Startup/Strings.resx +++ b/Starcounter.Startup/Strings.resx @@ -174,4 +174,10 @@ URI '{0}' is malformed: URI should start with a '/' + + View-model {0} is registered with partial URI: '{1}'. Use '{2}' instead + + + View-model {0} is registered with malformed URI: '{1}'. URI has to start with a slash sign ('/') + \ No newline at end of file diff --git a/Starcounter.Startup/StringsFormatted.cs b/Starcounter.Startup/StringsFormatted.cs index 6003ef8..12e8ef7 100644 --- a/Starcounter.Startup/StringsFormatted.cs +++ b/Starcounter.Startup/StringsFormatted.cs @@ -3,6 +3,7 @@ using System.Reflection; using Starcounter.Startup.Routing; using Starcounter.Startup.Routing.Activation; +using Starcounter.Startup.Routing.Middleware; namespace Starcounter.Startup { @@ -68,5 +69,11 @@ public static string UriHelper_CantFillUriTemplateSlotCountMismatch(string uriTe String.Format(Strings.UriHelper_CantFillUriTemplateSlotCountMismatch, uriTemplate, slotsCount, arguments.Length, String.Join(",", arguments)); public static string UriHelper_MalformedUri(string pageUri) => String.Format(Strings.UriHelper_MalformedUri, pageUri); + + public static string Router_ViewModelRegisteredWithMalformedUri(Type pageType, string pageUri) => + String.Format(Strings.Router_ViewModelRegisteredWithMalformedUri, pageType, pageUri); + + public static string Router_ViewModelRegisteredWithPartialUri(Type pageType, string pageUri) => + String.Format(Strings.Router_ViewModelRegisteredWithPartialUri, pageType, pageUri, UriHelper.PartialToPage(pageUri)); } } \ No newline at end of file