From 1a1e9ac6becd3296261a2cba6979c5efa0d5a6bb Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Fri, 11 Apr 2025 09:24:18 +0200 Subject: [PATCH 01/11] Swagger Updated to latest Swashbuckle.AspNetCore update from 8.1.0 > 8.1.1 --- Oqtane.Server/Oqtane.Server.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 1ae9c302..a57cac0e 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -48,7 +48,7 @@ - + From 26a686c41257266e8369f9a466bdd91e1760d0fe Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 11 Apr 2025 15:54:02 -0400 Subject: [PATCH 02/11] .NET MAUI client was changed from 0.0.0.0 to 0.0.0.1 in .NET 9 --- Oqtane.Server/Startup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 8c99ef7f..51b60555 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -136,7 +136,7 @@ namespace Oqtane policy => { // allow .NET MAUI client cross origin calls - policy.WithOrigins("https://0.0.0.0", "http://0.0.0.0", "app://0.0.0.0") + policy.WithOrigins("https://0.0.0.1", "http://0.0.0.1", "app://0.0.0.1") .AllowAnyHeader().AllowAnyMethod().AllowCredentials(); }); }); From 95cb5dd66c465d499cb218fd56d8d2089e085647 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 15 Apr 2025 09:20:18 -0400 Subject: [PATCH 03/11] UX improvements for System Update --- .../Modules/Admin/Upgrade/Index.razor | 22 ++++++++++++------- .../Modules/Admin/Upgrade/Index.resx | 7 ++---- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Upgrade/Index.razor b/Oqtane.Client/Modules/Admin/Upgrade/Index.razor index 31fee382..aeda1366 100644 --- a/Oqtane.Client/Modules/Admin/Upgrade/Index.razor +++ b/Oqtane.Client/Modules/Admin/Upgrade/Index.razor @@ -15,7 +15,7 @@ {
- +
@@ -52,15 +57,15 @@
+
-

- } @code { private bool _initialized = false; + private bool _downloaded = false; private Package _package; private bool _upgradeavailable = false; private string _backup = "True"; @@ -125,6 +130,7 @@ ShowProgressIndicator(); await PackageService.DownloadPackageAsync(packageid, version); await PackageService.DownloadPackageAsync(Constants.UpdaterPackageId, version); + _downloaded = true; HideProgressIndicator(); AddModuleMessage(Localizer["Success.Framework.Download"], MessageType.Success); } diff --git a/Oqtane.Client/Resources/Modules/Admin/Upgrade/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Upgrade/Index.resx index e609f42a..a38e830c 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Upgrade/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Upgrade/Index.resx @@ -124,7 +124,7 @@ Error Downloading Framework Package - Upload a framework package and select Install to complete the installation + Upload A Framework Package (Oqtane.Framework.#.#.#.nupkg) And Then Select Upgrade Framework: @@ -144,9 +144,6 @@ Framework Is Already Up To Date - - Upload A Framework Package (Oqtane.Framework.version.nupkg) And Then Select Upgrade - You Cannot Perform A System Update In A Development Environment @@ -157,6 +154,6 @@ Backup Files? - Specify if you want to backup files during the upgrade process. Disabling this option will result in a better experience in some environments. + Specify if you want to backup files during the upgrade process. Disabling this option will reduce the time required for the upgrade. \ No newline at end of file From 4d572d8173881206890400f37a9d825d3a6dd198 Mon Sep 17 00:00:00 2001 From: David Montesinos Date: Mon, 21 Apr 2025 10:48:48 +0200 Subject: [PATCH 04/11] Allow earlier return in files server --- Oqtane.Server/Pages/Files.cshtml.cs | 58 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/Oqtane.Server/Pages/Files.cshtml.cs b/Oqtane.Server/Pages/Files.cshtml.cs index b241388e..97fc2c57 100644 --- a/Oqtane.Server/Pages/Files.cshtml.cs +++ b/Oqtane.Server/Pages/Files.cshtml.cs @@ -112,7 +112,7 @@ namespace Oqtane.Pages url += Request.QueryString.Value.Substring(1); } - + return RedirectPermanent(url); } @@ -137,6 +137,34 @@ namespace Oqtane.Pages string downloadName = file.Name; string filepath = _files.GetFilePath(file); + if (Request.QueryString.HasValue) + { + etag = Utilities.GenerateSimpleHash(Request.QueryString.Value); + } + else + { + etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16); + } + + var header = ""; + if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch)) + { + header = ifNoneMatch.ToString(); + } + + if (header.Equals(etag)) + { + HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified; + return Content(String.Empty); + } + + if (!System.IO.File.Exists(filepath)) + { + _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FilePath}", filepath); + HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; + return BrokenFile(); + } + // evaluate any querystring parameters bool isRequestingImageManipulation = false; @@ -165,34 +193,6 @@ namespace Oqtane.Pages isRequestingImageManipulation = true; } - if (isRequestingImageManipulation) - { - etag = Utilities.GenerateSimpleHash(Request.QueryString.Value); - } - else - { - etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16); - } - - var header = ""; - if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch)) - { - header = ifNoneMatch.ToString(); - } - - if (header.Equals(etag)) - { - HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified; - return Content(String.Empty); - } - - if (!System.IO.File.Exists(filepath)) - { - _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FilePath}", filepath); - HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; - return BrokenFile(); - } - if (isRequestingImageManipulation) { var _ImageFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue; From 1b00fa74bcbabdf4e854a660fd92788496b08143 Mon Sep 17 00:00:00 2001 From: David Montesinos Date: Mon, 21 Apr 2025 11:14:24 +0200 Subject: [PATCH 05/11] Compute file server etag with MD5 and always include ModifiedOn --- Oqtane.Server/Pages/Files.cshtml.cs | 10 +++++----- Oqtane.Shared/Shared/Utilities.cs | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Oqtane.Server/Pages/Files.cshtml.cs b/Oqtane.Server/Pages/Files.cshtml.cs index 97fc2c57..7be27e89 100644 --- a/Oqtane.Server/Pages/Files.cshtml.cs +++ b/Oqtane.Server/Pages/Files.cshtml.cs @@ -137,15 +137,15 @@ namespace Oqtane.Pages string downloadName = file.Name; string filepath = _files.GetFilePath(file); + var etagInput = $"{file.ModifiedOn.Ticks}:{file.Size}"; + if (Request.QueryString.HasValue) { - etag = Utilities.GenerateSimpleHash(Request.QueryString.Value); - } - else - { - etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16); + etagInput += $":{Request.QueryString.Value}"; } + etag = Utilities.GenerateHashMD5(etagInput); + var header = ""; if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch)) { diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs index 826fac70..d38fe490 100644 --- a/Oqtane.Shared/Shared/Utilities.cs +++ b/Oqtane.Shared/Shared/Utilities.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net; +using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using File = Oqtane.Models.File; @@ -619,6 +620,13 @@ namespace Oqtane.Shared } } + public static string GenerateHashMD5(string input) + { + var bytes = Encoding.UTF8.GetBytes(input); + var hashBytes = MD5.HashData(bytes); + return Convert.ToHexString(hashBytes); + } + [Obsolete("ContentUrl(Alias alias, int fileId) is deprecated. Use FileUrl(Alias alias, int fileId) instead.", false)] public static string ContentUrl(Alias alias, int fileId) { From e7acd14faa9a3021ca3099f6979835503e098a0f Mon Sep 17 00:00:00 2001 From: David Montesinos Date: Mon, 21 Apr 2025 15:51:25 +0200 Subject: [PATCH 06/11] Replace MD5 hash with a longer simple hash --- Oqtane.Server/Pages/Files.cshtml.cs | 2 +- Oqtane.Shared/Shared/Utilities.cs | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Oqtane.Server/Pages/Files.cshtml.cs b/Oqtane.Server/Pages/Files.cshtml.cs index 7be27e89..551be05f 100644 --- a/Oqtane.Server/Pages/Files.cshtml.cs +++ b/Oqtane.Server/Pages/Files.cshtml.cs @@ -144,7 +144,7 @@ namespace Oqtane.Pages etagInput += $":{Request.QueryString.Value}"; } - etag = Utilities.GenerateHashMD5(etagInput); + etag = Utilities.GenerateSimpleHash16(etagInput); var header = ""; if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch)) diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs index d38fe490..30e25bb2 100644 --- a/Oqtane.Shared/Shared/Utilities.cs +++ b/Oqtane.Shared/Shared/Utilities.cs @@ -620,11 +620,17 @@ namespace Oqtane.Shared } } - public static string GenerateHashMD5(string input) + public static string GenerateSimpleHash16(string text) { - var bytes = Encoding.UTF8.GetBytes(input); - var hashBytes = MD5.HashData(bytes); - return Convert.ToHexString(hashBytes); + unchecked // prevent overflow exception + { + long hash = 23; + foreach (char c in text) + { + hash = hash * 31 + c; + } + return hash.ToString("X16"); + } } [Obsolete("ContentUrl(Alias alias, int fileId) is deprecated. Use FileUrl(Alias alias, int fileId) instead.", false)] From 430f83e8e9d034b7edee27da3749342bec31b462 Mon Sep 17 00:00:00 2001 From: David Montesinos Date: Mon, 21 Apr 2025 16:46:55 +0200 Subject: [PATCH 07/11] Only compute hash when file has query string --- Oqtane.Server/Pages/Files.cshtml.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Oqtane.Server/Pages/Files.cshtml.cs b/Oqtane.Server/Pages/Files.cshtml.cs index 551be05f..4105262e 100644 --- a/Oqtane.Server/Pages/Files.cshtml.cs +++ b/Oqtane.Server/Pages/Files.cshtml.cs @@ -137,14 +137,14 @@ namespace Oqtane.Pages string downloadName = file.Name; string filepath = _files.GetFilePath(file); - var etagInput = $"{file.ModifiedOn.Ticks}:{file.Size}"; - if (Request.QueryString.HasValue) { - etagInput += $":{Request.QueryString.Value}"; + etag = Utilities.GenerateSimpleHash16($"{file.ModifiedOn.Ticks}:{file.Size}:{Request.QueryString.Value}"); + } + else + { + etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16); } - - etag = Utilities.GenerateSimpleHash16(etagInput); var header = ""; if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch)) From d888d83a986185e1109fb27c74f20086b6308ea6 Mon Sep 17 00:00:00 2001 From: David Montesinos Date: Mon, 21 Apr 2025 18:44:16 +0200 Subject: [PATCH 08/11] Simplify files etag calculation --- Oqtane.Server/Pages/Files.cshtml.cs | 11 +---------- Oqtane.Shared/Shared/Utilities.cs | 13 ------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/Oqtane.Server/Pages/Files.cshtml.cs b/Oqtane.Server/Pages/Files.cshtml.cs index 4105262e..f01cd0b7 100644 --- a/Oqtane.Server/Pages/Files.cshtml.cs +++ b/Oqtane.Server/Pages/Files.cshtml.cs @@ -133,19 +133,10 @@ namespace Oqtane.Pages } } - string etag; + string etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16); string downloadName = file.Name; string filepath = _files.GetFilePath(file); - if (Request.QueryString.HasValue) - { - etag = Utilities.GenerateSimpleHash16($"{file.ModifiedOn.Ticks}:{file.Size}:{Request.QueryString.Value}"); - } - else - { - etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16); - } - var header = ""; if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch)) { diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs index 30e25bb2..ee4586b0 100644 --- a/Oqtane.Shared/Shared/Utilities.cs +++ b/Oqtane.Shared/Shared/Utilities.cs @@ -620,19 +620,6 @@ namespace Oqtane.Shared } } - public static string GenerateSimpleHash16(string text) - { - unchecked // prevent overflow exception - { - long hash = 23; - foreach (char c in text) - { - hash = hash * 31 + c; - } - return hash.ToString("X16"); - } - } - [Obsolete("ContentUrl(Alias alias, int fileId) is deprecated. Use FileUrl(Alias alias, int fileId) instead.", false)] public static string ContentUrl(Alias alias, int fileId) { From da7b0460921354ca5835615eef9a1c87d943cb46 Mon Sep 17 00:00:00 2001 From: David Montesinos Date: Mon, 21 Apr 2025 18:47:34 +0200 Subject: [PATCH 09/11] Remove extra using --- Oqtane.Shared/Shared/Utilities.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs index ee4586b0..826fac70 100644 --- a/Oqtane.Shared/Shared/Utilities.cs +++ b/Oqtane.Shared/Shared/Utilities.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net; -using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using File = Oqtane.Models.File; From e0044658f9767889b52389c148d198fbd30b662b Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 21 Apr 2025 14:13:49 -0400 Subject: [PATCH 10/11] improve validation in Url Mapping --- .../Modules/Admin/UrlMappings/Add.razor | 44 ++++++++++--------- .../Modules/Admin/UrlMappings/Edit.razor | 5 ++- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/UrlMappings/Add.razor b/Oqtane.Client/Modules/Admin/UrlMappings/Add.razor index e57ad13e..a0a7ac9f 100644 --- a/Oqtane.Client/Modules/Admin/UrlMappings/Add.razor +++ b/Oqtane.Client/Modules/Admin/UrlMappings/Add.razor @@ -26,35 +26,37 @@ @code { - private ElementReference form; - private bool validated = false; + private ElementReference form; + private bool validated = false; - private string _url = string.Empty; - private string _mappedurl = string.Empty; + private string _url = string.Empty; + private string _mappedurl = string.Empty; - public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; + public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; - private async Task SaveUrlMapping() - { - validated = true; - var interop = new Interop(JSRuntime); - if (await interop.FormValid(form)) - { - if (_url != _mappedurl) - { - var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/"; - url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : ""); + private async Task SaveUrlMapping() + { + validated = true; + var interop = new Interop(JSRuntime); + if (await interop.FormValid(form)) + { + if (_url != _mappedurl) + { + var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/"; + url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : ""); - _url = (_url.StartsWith("/")) ? _url.Substring(1) : _url; - _url = (!_url.StartsWith("http")) ? url + _url : _url; + _url = (_url.StartsWith("/")) ? _url.Substring(1) : _url; + _url = (!_url.StartsWith("http")) ? url + _url : _url; - if (_url.StartsWith(url)) + _mappedurl = _mappedurl.Replace(url, ""); + _mappedurl = (_mappedurl.StartsWith("/")) ? _mappedurl.Substring(1) : _mappedurl; + + if (_url.StartsWith(url)) { var urlmapping = new UrlMapping(); urlmapping.SiteId = PageState.Site.SiteId; - var route = new Route(_url, PageState.Alias.Path); - urlmapping.Url = route.PagePath; - urlmapping.MappedUrl = _mappedurl.Replace(url, ""); + urlmapping.Url = new Route(_url, PageState.Alias.Path).PagePath; + urlmapping.MappedUrl = _mappedurl; urlmapping.Requests = 0; urlmapping.CreatedOn = DateTime.UtcNow; urlmapping.RequestedOn = DateTime.UtcNow; diff --git a/Oqtane.Client/Modules/Admin/UrlMappings/Edit.razor b/Oqtane.Client/Modules/Admin/UrlMappings/Edit.razor index 10c9a57f..073f851d 100644 --- a/Oqtane.Client/Modules/Admin/UrlMappings/Edit.razor +++ b/Oqtane.Client/Modules/Admin/UrlMappings/Edit.razor @@ -67,8 +67,11 @@ var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/"; url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : ""); + _mappedurl = _mappedurl.Replace(url, ""); + _mappedurl = (_mappedurl.StartsWith("/")) ? _mappedurl.Substring(1) : _mappedurl; + var urlmapping = await UrlMappingService.GetUrlMappingAsync(_urlmappingid); - urlmapping.MappedUrl = _mappedurl.Replace(url, ""); + urlmapping.MappedUrl = _mappedurl; urlmapping = await UrlMappingService.UpdateUrlMappingAsync(urlmapping); await logger.LogInformation("UrlMapping Saved {UrlMapping}", urlmapping); NavigationManager.NavigateTo(NavigateUrl()); From 4f16cd2d012c12a8ce802921c96db0f11e3fc0bd Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 21 Apr 2025 15:14:39 -0400 Subject: [PATCH 11/11] url mapping improvements --- .../Modules/Admin/UrlMappings/Add.razor | 77 +++++++++++-------- .../Modules/Admin/UrlMappings/Edit.razor | 2 +- .../Modules/Admin/UrlMappings/Add.resx | 9 ++- .../Modules/Admin/UrlMappings/Edit.resx | 2 +- Oqtane.Client/UI/SiteRouter.razor | 2 +- Oqtane.Server/Components/App.razor | 2 +- 6 files changed, 57 insertions(+), 37 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/UrlMappings/Add.razor b/Oqtane.Client/Modules/Admin/UrlMappings/Add.razor index a0a7ac9f..8f43985d 100644 --- a/Oqtane.Client/Modules/Admin/UrlMappings/Add.razor +++ b/Oqtane.Client/Modules/Admin/UrlMappings/Add.razor @@ -8,9 +8,12 @@
- +
- +
+ + +
@@ -49,43 +52,57 @@ _url = (!_url.StartsWith("http")) ? url + _url : _url; _mappedurl = _mappedurl.Replace(url, ""); - _mappedurl = (_mappedurl.StartsWith("/")) ? _mappedurl.Substring(1) : _mappedurl; + _mappedurl = (_mappedurl.StartsWith("/") && _mappedurl != "/") ? _mappedurl.Substring(1) : _mappedurl; if (_url.StartsWith(url)) - { - var urlmapping = new UrlMapping(); - urlmapping.SiteId = PageState.Site.SiteId; + { + var urlmapping = new UrlMapping(); + urlmapping.SiteId = PageState.Site.SiteId; urlmapping.Url = new Route(_url, PageState.Alias.Path).PagePath; - urlmapping.MappedUrl = _mappedurl; - urlmapping.Requests = 0; - urlmapping.CreatedOn = DateTime.UtcNow; - urlmapping.RequestedOn = DateTime.UtcNow; + urlmapping.MappedUrl = _mappedurl; + urlmapping.Requests = 0; + urlmapping.CreatedOn = DateTime.UtcNow; + urlmapping.RequestedOn = DateTime.UtcNow; - try - { - urlmapping = await UrlMappingService.AddUrlMappingAsync(urlmapping); - await logger.LogInformation("UrlMapping Saved {UrlMapping}", urlmapping); - NavigationManager.NavigateTo(NavigateUrl()); - } - catch (Exception ex) - { - await logger.LogError(ex, "Error Saving UrlMapping {UrlMapping} {Error}", urlmapping, ex.Message); - AddModuleMessage(Localizer["Error.SaveUrlMapping"], MessageType.Error); - } - } - else - { - AddModuleMessage(Localizer["Message.SaveUrlMapping"], MessageType.Warning); - } - } - else - { + try + { + urlmapping = await UrlMappingService.AddUrlMappingAsync(urlmapping); + await logger.LogInformation("UrlMapping Saved {UrlMapping}", urlmapping); + NavigationManager.NavigateTo(NavigateUrl()); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Saving UrlMapping {UrlMapping} {Error}", urlmapping, ex.Message); + AddModuleMessage(Localizer["Error.SaveUrlMapping"], MessageType.Error); + } + } + else + { + AddModuleMessage(Localizer["Message.SaveUrlMapping"], MessageType.Warning); + } + } + else + { AddModuleMessage(Localizer["Message.DuplicateUrlMapping"], MessageType.Warning); - } + } } else { AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); } } + + private void GenerateUrl() + { + var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/"; + url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : ""); + + var chars = "abcdefghijklmnopqrstuvwxyz"; + Random rnd = new Random(); + for (int i = 0; i < 5; i++) + { + url += chars.Substring(rnd.Next(0, chars.Length - 1), 1); + } + _url = url; + } } diff --git a/Oqtane.Client/Modules/Admin/UrlMappings/Edit.razor b/Oqtane.Client/Modules/Admin/UrlMappings/Edit.razor index 073f851d..78a062f9 100644 --- a/Oqtane.Client/Modules/Admin/UrlMappings/Edit.razor +++ b/Oqtane.Client/Modules/Admin/UrlMappings/Edit.razor @@ -68,7 +68,7 @@ url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : ""); _mappedurl = _mappedurl.Replace(url, ""); - _mappedurl = (_mappedurl.StartsWith("/")) ? _mappedurl.Substring(1) : _mappedurl; + _mappedurl = (_mappedurl.StartsWith("/") && _mappedurl != "/") ? _mappedurl.Substring(1) : _mappedurl; var urlmapping = await UrlMappingService.GetUrlMappingAsync(_urlmappingid); urlmapping.MappedUrl = _mappedurl; diff --git a/Oqtane.Client/Resources/Modules/Admin/UrlMappings/Add.resx b/Oqtane.Client/Resources/Modules/Admin/UrlMappings/Add.resx index e1185498..a8de1c59 100644 --- a/Oqtane.Client/Resources/Modules/Admin/UrlMappings/Add.resx +++ b/Oqtane.Client/Resources/Modules/Admin/UrlMappings/Add.resx @@ -1,4 +1,4 @@ - +