From 2c1543aa82a5635888c10898bee389c25a4f172f Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Thu, 18 Aug 2022 16:04:30 -0400 Subject: [PATCH] optimize Url Parameters and implement in Event Log --- Oqtane.Client/Modules/Admin/Logs/Detail.razor | 5 +- Oqtane.Client/Modules/Admin/Logs/Index.razor | 19 +++-- .../Modules/Controls/ActionLink.razor | 6 +- Oqtane.Client/Modules/ModuleBase.cs | 74 ++++++++++--------- Oqtane.Shared/Models/Route.cs | 4 +- 5 files changed, 60 insertions(+), 48 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Logs/Detail.razor b/Oqtane.Client/Modules/Admin/Logs/Detail.razor index 7df9838f..71f26397 100644 --- a/Oqtane.Client/Modules/Admin/Logs/Detail.razor +++ b/Oqtane.Client/Modules/Admin/Logs/Detail.razor @@ -130,13 +130,14 @@ private string _properties = string.Empty; private string _server = string.Empty; - public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; + public override string RouteTemplate => "/{id}"; + public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; protected override async Task OnInitializedAsync() { try { - _logId = Int32.Parse(PageState.QueryString["id"]); + _logId = Int32.Parse(UrlParameters["id"]); var log = await LogService.GetLogAsync(_logId); if (log != null) { diff --git a/Oqtane.Client/Modules/Admin/Logs/Index.razor b/Oqtane.Client/Modules/Admin/Logs/Index.razor index e8ed4717..49a8e0a9 100644 --- a/Oqtane.Client/Modules/Admin/Logs/Index.razor +++ b/Oqtane.Client/Modules/Admin/Logs/Index.razor @@ -63,7 +63,7 @@ else @Localizer["Function"] - + @context.LogDate @context.Level @context.Feature @@ -99,29 +99,32 @@ else private List _logs; private string _retention = ""; + public override string RouteTemplate => "/{level}/{function}/{rows}/{page}"; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; protected override async Task OnInitializedAsync() { try { + // external link to log item will display Details component if (PageState.QueryString.ContainsKey("id") && int.TryParse(PageState.QueryString["id"], out int id)) { NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, ModuleState.ModuleId, "Detail", $"id={id}")); } - if (PageState.QueryString.ContainsKey("level")) + + if (UrlParameters.ContainsKey("level")) { - _level = PageState.QueryString["level"]; + _level = UrlParameters["level"]; } - if (PageState.QueryString.ContainsKey("function")) + if (UrlParameters.ContainsKey("function")) { - _function = PageState.QueryString["function"]; + _function = UrlParameters["function"]; } - if (PageState.QueryString.ContainsKey("rows")) + if (UrlParameters.ContainsKey("rows")) { - _rows = PageState.QueryString["rows"]; + _rows = UrlParameters["rows"]; } - if (PageState.QueryString.ContainsKey("page") && int.TryParse(PageState.QueryString["page"], out int page)) + if (UrlParameters.ContainsKey("page") && int.TryParse(UrlParameters["page"], out int page)) { _page = page; } diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index a74c0d8a..6f3a29bf 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -121,12 +121,12 @@ _permissions = (string.IsNullOrEmpty(Permissions)) ? ModuleState.Permissions : Permissions; _text = Localize(nameof(Text), _text); + _url = (ModuleId == -1) ? EditUrl(Action, _parameters) : EditUrl(ModuleId, Action, _parameters); if (!string.IsNullOrEmpty(ReturnUrl)) { - _parameters += ((!string.IsNullOrEmpty(_parameters)) ? "&" : "") + $"returnurl={WebUtility.UrlEncode(ReturnUrl)}"; + _url += ((_url.Contains("?")) ? "&" : "?") + $"returnurl={WebUtility.UrlEncode(ReturnUrl)}"; } - _url = (ModuleId == -1) ? EditUrl(Action, _parameters) : EditUrl(ModuleId, Action, _parameters); - _authorized = IsAuthorized(); + _authorized = IsAuthorized(); } private bool IsAuthorized() diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs index ab1cb528..3005dbe9 100644 --- a/Oqtane.Client/Modules/ModuleBase.cs +++ b/Oqtane.Client/Modules/ModuleBase.cs @@ -15,6 +15,7 @@ namespace Oqtane.Modules public abstract class ModuleBase : ComponentBase, IModuleControl { private Logger _logger; + private Dictionary _urlparameters; protected Logger logger => _logger ?? (_logger = new Logger(this)); @@ -47,6 +48,20 @@ namespace Oqtane.Modules public virtual List Resources { get; set; } + // url parameters + public virtual string RouteTemplate { get; set; } + + public Dictionary UrlParameters { + get + { + if (_urlparameters == null) + { + _urlparameters = GetUrlParameters(RouteTemplate); + } + return _urlparameters; + } + } + // base lifecycle method for handling JSInterop script registration protected override async Task OnAfterRenderAsync(bool firstRender) @@ -153,31 +168,26 @@ namespace Oqtane.Modules return Utilities.ImageUrl(PageState.Alias, fileid, width, height, mode, position, background, rotate, recreate); } - public string AddUrlParameters(params string[] parameters) + public string AddUrlParameters(params object[] parameters) { - return AddUrlParameters(PageState.Page.Path, parameters); - } - - public string AddUrlParameters(string path, params string[] parameters) - { - var url = path + "/" + Constants.UrlParametersDelimiter; + var url = ""; for (var i = 0; i < parameters.Length; i++) { - url += "/" + parameters[i]; + url += "/" + parameters[i].ToString(); } return url; } - // parameters template is in the form of a standard route template ie. "{id}/{name}" - public virtual Dictionary GetUrlParameters(string parametersTemplate = "") + // template is in the form of a standard route template ie. "/{id}/{name}" and produces dictionary of key/value pairs + // if url parameters belong to a specific module you should embed a unique key into the route (ie. /!/blog/1) and validate the url parameter key in the module + public virtual Dictionary GetUrlParameters(string template = "") { var urlParameters = new Dictionary(); - string[] templateSegments; var parameters = PageState.UrlParameters.Split('/', StringSplitOptions.RemoveEmptyEntries); - var parameterId = 0; - if (string.IsNullOrEmpty(parametersTemplate)) + if (string.IsNullOrEmpty(template)) { + // no template will populate dictionary with generic "parameter#" keys for (int i = 0; i < parameters.Length; i++) { urlParameters.TryAdd("parameter" + i, parameters[i]); @@ -185,32 +195,30 @@ namespace Oqtane.Modules } else { - templateSegments = parametersTemplate.Split('/', StringSplitOptions.RemoveEmptyEntries); + var segments = template.Split('/', StringSplitOptions.RemoveEmptyEntries); + string key; - if (parameters.Length == templateSegments.Length) + for (int i = 0; i < parameters.Length; i++) { - for (int i = 0; i < parameters.Length; i++) + if (i < segments.Length) { - if (parameters.Length > i) + key = segments[i]; + if (key.StartsWith("{") && key.EndsWith("}")) { - if (templateSegments[i] == parameters[i]) - { - urlParameters.TryAdd("parameter" + parameterId, parameters[i]); - parameterId++; - } - else if (templateSegments[i].StartsWith("{") && templateSegments[i].EndsWith("}")) - { - var key = templateSegments[i].Replace("{", ""); - key = key.Replace("}", ""); - urlParameters.TryAdd(key, parameters[i]); - } - else - { - i = parameters.Length; - urlParameters.Clear(); - } + // dynamic segment + key = key.Substring(1, key.Length - 2); + } + else + { + // static segments use generic "parameter#" keys + key = "parameter" + i.ToString(); } } + else // unspecified segments use generic "parameter#" keys + { + key = "parameter" + i.ToString(); + } + urlParameters.TryAdd(key, parameters[i]); } } diff --git a/Oqtane.Shared/Models/Route.cs b/Oqtane.Shared/Models/Route.cs index bff8f17f..9b4cc683 100644 --- a/Oqtane.Shared/Models/Route.cs +++ b/Oqtane.Shared/Models/Route.cs @@ -38,13 +38,13 @@ namespace Oqtane.Models if (pos != -1) { UrlParameters = PagePath.Substring(pos + 3); - PagePath = PagePath.Substring(1, pos); + PagePath = PagePath.Substring(0, pos); } pos = PagePath.IndexOf("/" + Constants.ModuleDelimiter + "/"); if (pos != -1) { ModuleId = PagePath.Substring(pos + 3); - PagePath = PagePath.Substring(1, pos); + PagePath = PagePath.Substring(0, pos); } if (ModuleId.Length != 0) {