diff --git a/src/Money.UI.Blazor/Pages/Account/Login.cshtml.cs b/src/Money.UI.Blazor/Pages/Account/Login.cshtml.cs index a79cc450..51590165 100644 --- a/src/Money.UI.Blazor/Pages/Account/Login.cshtml.cs +++ b/src/Money.UI.Blazor/Pages/Account/Login.cshtml.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Blazor.Components; using Microsoft.AspNetCore.Blazor.Services; using Money.Services; +using Neptuo.Collections.Specialized; using System; using System.Collections.Generic; using System.Linq; @@ -18,7 +19,7 @@ public class LoginBase : BlazorComponent internal ApiClient ApiClient { get; set; } [Inject] - internal IUriHelper Uri { get; set; } + internal QueryString QueryString { get; set; } [Parameter] protected string ReturnUrl { get; set; } @@ -32,29 +33,7 @@ public class LoginBase : BlazorComponent protected override void OnParametersSet() { base.OnParametersSet(); - SetReturnUrl(); - } - - private void SetReturnUrl() - { - string url = Uri.GetAbsoluteUri(); - int indexOfQuery = url.IndexOf('?'); - if (indexOfQuery >= 0) - { - string query = url.Substring(indexOfQuery + 1).ToLowerInvariant(); - string[] parameters = query.Split('&'); - foreach (string parameter in parameters) - { - string[] keyValue = parameter.Split('='); - if (keyValue[0] == "returnurl") - { - if (keyValue.Length == 2) - ReturnUrl = keyValue[1]; - - break; - } - } - } + ReturnUrl = QueryString.Find("returnUrl"); } protected Task OnSubmitAsync() @@ -71,8 +50,8 @@ private async Task LoginAsync(string userName, string password, bool isPermanent { if (!await ApiClient.LoginAsync(userName, password, isPermanent)) ErrorMessages.Add("User name and password don't match."); - else if (ReturnUrl != null) - Uri.NavigateTo(ReturnUrl); + else if (!String.IsNullOrEmpty(ReturnUrl)) + Navigator.Open(ReturnUrl); else Navigator.OpenSummary(); } diff --git a/src/Money.UI.Blazor/Services/Navigator.cs b/src/Money.UI.Blazor/Services/Navigator.cs index 0e49738d..795ce72b 100644 --- a/src/Money.UI.Blazor/Services/Navigator.cs +++ b/src/Money.UI.Blazor/Services/Navigator.cs @@ -36,6 +36,9 @@ private void OnLocationChanged(object sender, string e) private void OpenExternal(string url) => Interop.NavigateTo(url); + public void Open(string url) + => uri.NavigateTo(url); + public void OpenSummary() => uri.NavigateTo(UrlSummary()); diff --git a/src/Money.UI.Blazor/Services/QueryString.cs b/src/Money.UI.Blazor/Services/QueryString.cs new file mode 100644 index 00000000..95531431 --- /dev/null +++ b/src/Money.UI.Blazor/Services/QueryString.cs @@ -0,0 +1,76 @@ +using Microsoft.AspNetCore.Blazor.Services; +using Neptuo; +using Neptuo.Collections.Specialized; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Money.Services +{ + /// + /// A current parsed query string provider. + /// + public class QueryString : DisposableBase, IReadOnlyKeyValueCollection + { + private readonly IUriHelper uri; + private KeyValueCollection parameters; + + public QueryString(IUriHelper uri) + { + Ensure.NotNull(uri, "uri"); + this.uri = uri; + + uri.OnLocationChanged += OnLocationChanged; + } + + private void OnLocationChanged(object sender, string e) + => parameters = null; + + private void EnsureParameters() + { + if (parameters == null) + { + parameters = new KeyValueCollection(); + + string url = uri.GetAbsoluteUri(); + int indexOfQuery = url.IndexOf('?'); + if (indexOfQuery >= 0) + { + string query = url.Substring(indexOfQuery + 1).ToLowerInvariant(); + string[] items = query.Split('&'); + foreach (string parameter in items) + { + string[] keyValue = parameter.Split('='); + if (keyValue.Length == 2) + parameters.Add(keyValue[0], keyValue[1]); + else + parameters.Add(keyValue[0], null); + } + } + } + } + + public IEnumerable Keys + { + get + { + EnsureParameters(); + return parameters.Keys; + } + } + + public bool TryGet(string key, out T value) + { + EnsureParameters(); + return parameters.TryGet(key?.ToLowerInvariant(), out value); + } + + protected override void DisposeManagedResources() + { + base.DisposeManagedResources(); + uri.OnLocationChanged -= OnLocationChanged; + } + } +} diff --git a/src/Money.UI.Blazor/Startup.cs b/src/Money.UI.Blazor/Startup.cs index b854f328..009a8d6e 100644 --- a/src/Money.UI.Blazor/Startup.cs +++ b/src/Money.UI.Blazor/Startup.cs @@ -20,6 +20,7 @@ public void ConfigureServices(IServiceCollection services) services .AddTransient() .AddTransient() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/src/Neptuo/Collections/Specialized/_ReadOnlyKeyValueCollectionExtensions.cs b/src/Neptuo/Collections/Specialized/_ReadOnlyKeyValueCollectionExtensions.cs index 69794ad4..c54895ef 100644 --- a/src/Neptuo/Collections/Specialized/_ReadOnlyKeyValueCollectionExtensions.cs +++ b/src/Neptuo/Collections/Specialized/_ReadOnlyKeyValueCollectionExtensions.cs @@ -51,6 +51,25 @@ public static T Get(this IReadOnlyKeyValueCollection collection, string key, return defaultValue; } + /// + /// Reads the value of in . + /// If value is found and can be converted to , returns it. + /// Otherwise the default value of is returned. + /// + /// Collection of key-value pairs. + /// Requested key. + /// Value of in . + public static T Find(this IReadOnlyKeyValueCollection collection, string key) + { + Ensure.NotNull(collection, "collection"); + + T value; + if (collection.TryGet(key, out value)) + return value; + + return default(T); + } + /// /// Returns true if contains . ///