diff --git a/.docfx/api/types/Cuemon.AspNetCore.Razor.TagHelpers.TagHelperBaseUrlMode.md b/.docfx/api/types/Cuemon.AspNetCore.Razor.TagHelpers.TagHelperBaseUrlMode.md new file mode 100644 index 000000000..856affa91 --- /dev/null +++ b/.docfx/api/types/Cuemon.AspNetCore.Razor.TagHelpers.TagHelperBaseUrlMode.md @@ -0,0 +1,41 @@ +--- +uid: Cuemon.AspNetCore.Razor.TagHelpers.TagHelperBaseUrlMode +example: +- *content +--- + +The `TagHelperBaseUrlMode` enumeration controls how the base URL of a static resource is resolved by the app- and CDN-scoped tag helpers. `Configured` (the default) resolves the base URL exclusively from the configured `BaseUrl` and `Scheme`, whereas `Automatic` uses the configured `BaseUrl` when present and otherwise derives the base URL from the current HTTP request — useful when the same deployment is served from multiple origins. The following example demonstrates both modes through `CdnTagHelperOptions` and `GetFormattedBaseUrl`. + +```csharp +using System; +using Cuemon.AspNetCore.Razor.TagHelpers; +using Microsoft.AspNetCore.Http; + +namespace DocfxExamples; + +public class TagHelperBaseUrlModeExample +{ + public void Demonstrate() + { + var configured = new CdnTagHelperOptions + { + BaseUrlMode = TagHelperBaseUrlMode.Configured, + Scheme = ProtocolUriScheme.Https, + BaseUrl = "static.example.com" + }; + Console.WriteLine(configured.GetFormattedBaseUrl()); // Output: https://static.example.com/ + + var automatic = new CdnTagHelperOptions + { + BaseUrlMode = TagHelperBaseUrlMode.Automatic, + BaseUrl = null // No fixed origin, so fall back to the current HTTP request. + }; + var request = new DefaultHttpContext().Request; + request.Scheme = "https"; + request.Host = new HostString("app.example.com"); + request.PathBase = "/myapp"; + Console.WriteLine(automatic.GetFormattedBaseUrl(request)); // Output: https://app.example.com/myapp/ + } +} + +``` diff --git a/.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt index 4a4a3643f..5b34bab19 100644 --- a/.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt index 3e4f2e646..785ed3db4 100644 --- a/.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt index 2dbd9e08e..5b88a3824 100644 --- a/.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt index 4a4a3643f..0411eed4b 100644 --- a/.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt @@ -1,3 +1,15 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + +# New Features +- ADDED `TagHelperBaseUrlMode` enum to control how base URLs are resolved in tag helper options +- ADDED automatic base URL resolution to `CacheBustingTagHelper` via the new `ResolveUrl` method +- ADDED `ViewContext` property to `CacheBustingTagHelper` to enable access to the current HTTP request context +- EXTENDED `ImageTagHelper`, `LinkTagHelper`, and `ScriptTagHelper` to support automatic URL resolution from the current HTTP request when `TagHelperBaseUrlMode.Automatic` is configured + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt index 176d9d7b1..ddf0d2443 100644 --- a/.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Core.App/PackageReleaseNotes.txt b/.nuget/Cuemon.Core.App/PackageReleaseNotes.txt index afe9d5bc5..3ffb84e3e 100644 --- a/.nuget/Cuemon.Core.App/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Core.App/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Core/PackageReleaseNotes.txt b/.nuget/Cuemon.Core/PackageReleaseNotes.txt index cc9b04f7e..5e30221dc 100644 --- a/.nuget/Cuemon.Core/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Core/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt b/.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt b/.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt index 9bf3caa93..247ba5026 100644 --- a/.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Data/PackageReleaseNotes.txt b/.nuget/Cuemon.Data/PackageReleaseNotes.txt index c75594dcb..446fb3f71 100644 --- a/.nuget/Cuemon.Data/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Data/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt b/.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt index 4a4a3643f..5b34bab19 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt index 150f28cbd..8e7cafd05 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt index a542383f1..bb94ff809 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt index 4a4a3643f..5b34bab19 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt index 1ef27e966..e82ace680 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt index 324225973..2cef943a3 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt index 8505d1391..60b98e801 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt index bceeb8879..ff8d32267 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt index b0ae981f5..5248eed69 100644 --- a/.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt index be34c48fc..4bd8eabe4 100644 --- a/.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt index b7ee357d4..630702d25 100644 --- a/.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt index 61f74d3dd..a0a76b3ce 100644 --- a/.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.FileProviders.Physical/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.FileProviders.Physical/PackageReleaseNotes.txt index 867efaa6c..c0f5eb252 100644 --- a/.nuget/Cuemon.Extensions.FileProviders.Physical/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.FileProviders.Physical/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt index 2f7315333..4ff36bd82 100644 --- a/.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt index fe752f270..a56b51626 100644 --- a/.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9, .NET Standard 2.1 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt index e1fc44ffe..ebc24d2d4 100644 --- a/.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt index 884ecb612..61cb1032b 100644 --- a/.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt index 0573e6e80..0c301807c 100644 --- a/.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.IO/PackageReleaseNotes.txt b/.nuget/Cuemon.IO/PackageReleaseNotes.txt index 5a0ca50d5..32b0a91b8 100644 --- a/.nuget/Cuemon.IO/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.IO/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Kernel/PackageReleaseNotes.txt b/.nuget/Cuemon.Kernel/PackageReleaseNotes.txt index 60d733646..462353804 100644 --- a/.nuget/Cuemon.Kernel/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Kernel/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Net/PackageReleaseNotes.txt b/.nuget/Cuemon.Net/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Net/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Net/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Resilience/PackageReleaseNotes.txt b/.nuget/Cuemon.Resilience/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Resilience/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Resilience/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt b/.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt index 64c75fbf2..199041f78 100644 --- a/.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt b/.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt index 155076481..651301fb2 100644 --- a/.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Threading/PackageReleaseNotes.txt b/.nuget/Cuemon.Threading/PackageReleaseNotes.txt index b1121191a..381d8f14f 100644 --- a/.nuget/Cuemon.Threading/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Threading/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Xml/PackageReleaseNotes.txt b/.nuget/Cuemon.Xml/PackageReleaseNotes.txt index 521d8a0ac..a56780086 100644 --- a/.nuget/Cuemon.Xml/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Xml/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.7.0 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.6.0 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 096c2f401..466dff025 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), For more details, please refer to `PackageReleaseNotes.txt` on a per assembly basis in the `.nuget` folder. +## [10.7.0] - 2026-08-12 + +This is a minor release focused on enhancing Razor tag helper flexibility with automatic base URL resolution and modernizing package dependency management. The release introduces opt-in automatic base URL derivation from the current HTTP request while maintaining backward compatibility with the default configured mode. Tag helper functionality remains stable while new capabilities provide greater flexibility for dynamic deployment scenarios. + +### Added + +- `TagHelperBaseUrlMode` enumeration with `Configured` and `Automatic` modes to control base URL resolution strategy, +- Automatic base URL resolution capability in tag helpers allowing dynamic derivation from the current HTTP request scheme, host, and path base when `BaseUrlMode` is set to `Automatic`, +- `ViewContext` property injection in `CacheBustingTagHelper` base class to enable HTTP request context access for automatic URL resolution, +- `ResolveUrl` protected method in tag helper base class for consistent URL path normalization and base URL composition, +- Comprehensive test coverage for automatic base URL resolution across `AppImageTagHelper`, `AppLinkTagHelper`, and `AppScriptTagHelper` with test factory helper. + +### Changed + +- Central package transitive pinning enabled in `Directory.Packages.props` for improved transitive dependency resolution, requiring explicit declaration of transitive dependencies in affected projects, +- Package dependencies updated to latest compatible versions across all supported target frameworks: Microsoft.Data.Sqlite (10.0.10 → 10.0.11, 9.0.18 → 9.0.19), Microsoft.Extensions packages (10.0.10 → 10.0.11, 9.0.18 → 9.0.19), System.Text.Json (10.0.10 → 10.0.11), +- Newtonsoft.Json added as a conditional dependency for Cuemon.Core.Tests to explicitly manage transitive package resolution with transitive pinning enabled. + ## [10.6.0] - 2026-08-07 This is a minor release that combines new portable file provider and async retry capabilities with bug fixes for retry, timeout, cancellation, and exception-handling edge cases. Existing public APIs remain available, while the corrected failure and retry behavior may differ for affected edge cases. The release also includes comprehensive dependency updates across all supported target frameworks. @@ -1856,6 +1874,7 @@ This release was primarily focused on adapting a more modern way of performing C - XmlWriterUtility class from Cuemon.Xml namespace - XmlWriterUtilityExtensions class from the Cuemon.Xml namespace +[10.7.0]: https://github.com/codebeltnet/cuemon/compare/v10.6.0...v10.7.0 [10.6.0]: https://github.com/codebeltnet/cuemon/compare/v10.5.5...v10.6.0 [10.5.5]: https://github.com/codebeltnet/cuemon/compare/v10.5.4...v10.5.5 [10.5.4]: https://github.com/codebeltnet/cuemon/compare/v10.5.3...v10.5.4 diff --git a/Directory.Packages.props b/Directory.Packages.props index 490f661a4..92f77317e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,6 +1,7 @@ true + true @@ -14,6 +15,7 @@ + @@ -22,33 +24,33 @@ - + - - - - - + + + + + - + - - - - - - + + + + + + - - - - - - + + + + + + diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/AppTagHelperOptions.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/AppTagHelperOptions.cs index 022c49871..4131c1f4b 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/AppTagHelperOptions.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/AppTagHelperOptions.cs @@ -19,6 +19,10 @@ public class AppTagHelperOptions : TagHelperOptions /// /// /// + /// + /// + /// + /// /// /// null /// diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/CacheBustingTagHelper.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/CacheBustingTagHelper.cs index 946d5527d..d7d42a66b 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/CacheBustingTagHelper.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/CacheBustingTagHelper.cs @@ -1,6 +1,10 @@ -using Cuemon.AspNetCore.Configuration; +using System; +using System.Globalization; +using Cuemon.AspNetCore.Configuration; using Cuemon.Configuration; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Options; namespace Cuemon.AspNetCore.Razor.TagHelpers; @@ -34,9 +38,36 @@ protected CacheBustingTagHelper(IOptions setup, ICacheBusting cacheBus /// true if an object implementing the interface is specified; otherwise, false. protected bool UseCacheBusting => CacheBusting != null; + /// + /// Gets or sets the current view context. + /// + /// The current view context. + [HtmlAttributeNotBound] + [ViewContext] + public ViewContext ViewContext { get; set; } + /// /// Gets the configured options of this instance. /// /// The configured options of this instance. public TOptions Options { get; } + + /// + /// Resolves the fully qualified URL of the specified static resource. + /// + /// The relative path of the static resource. + /// The fully qualified URL of the specified static resource. + protected string ResolveUrl(string path) + { + var baseUrl = Options.GetFormattedBaseUrl(ViewContext?.HttpContext?.Request); + var resolvedPath = NormalizePath(path, !string.IsNullOrWhiteSpace(baseUrl)); + return string.Concat(baseUrl, UseCacheBusting ? string.Create(CultureInfo.InvariantCulture, $"{resolvedPath}?v={CacheBusting.Version}") : resolvedPath); + } + + private static string NormalizePath(string path, bool normalize) + { + if (!normalize || string.IsNullOrWhiteSpace(path)) { return path; } + if (path.StartsWith("~/", StringComparison.Ordinal)) { path = path.Substring(2); } + return path.TrimStart('/'); + } } diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/CdnTagHelperOptions.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/CdnTagHelperOptions.cs index ca8aaa8da..e737b5901 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/CdnTagHelperOptions.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/CdnTagHelperOptions.cs @@ -19,6 +19,10 @@ public class CdnTagHelperOptions : TagHelperOptions /// /// /// + /// + /// + /// + /// /// /// null /// diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/ImageTagHelper.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/ImageTagHelper.cs index 54847a270..8732c9800 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/ImageTagHelper.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/ImageTagHelper.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.Threading.Tasks; +using System.Threading.Tasks; using Cuemon.AspNetCore.Configuration; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Options; @@ -62,7 +61,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp output.TagName = "img"; if (!string.IsNullOrWhiteSpace(Id)) { output.Attributes.Add("id", Id); } if (!string.IsNullOrWhiteSpace(Class)) { output.Attributes.Add("class", Class); } - output.Attributes.Add("src", string.Concat(Options.GetFormattedBaseUrl(), UseCacheBusting ? string.Create(CultureInfo.InvariantCulture, $"{Src}?v={CacheBusting.Version}") : Src)); + output.Attributes.Add("src", ResolveUrl(Src)); if (!string.IsNullOrWhiteSpace(Alt)) { output.Attributes.Add("alt", Alt); } if (!string.IsNullOrWhiteSpace(Title)) { output.Attributes.Add("title", Title); } return Task.CompletedTask; diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/LinkTagHelper.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/LinkTagHelper.cs index 6afff7109..9c85b21c4 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/LinkTagHelper.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/LinkTagHelper.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.Threading.Tasks; +using System.Threading.Tasks; using Cuemon.AspNetCore.Configuration; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Razor.TagHelpers; @@ -52,7 +51,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp output.TagMode = TagMode.StartTagOnly; output.TagName = "link"; output.Attributes.Add("rel", Rel); - output.Attributes.Add("href", string.Concat(Options.GetFormattedBaseUrl(), UseCacheBusting ? string.Create(CultureInfo.InvariantCulture, $"{Href}?v={CacheBusting.Version}") : Href)); + output.Attributes.Add("href", ResolveUrl(Href)); if (!string.IsNullOrWhiteSpace(Type)) { output.Attributes.Add("type", new HtmlString(Type)); } return Task.CompletedTask; } diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/ScriptTagHelper.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/ScriptTagHelper.cs index 3308bbd82..8ed03af91 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/ScriptTagHelper.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/ScriptTagHelper.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.Threading.Tasks; +using System.Threading.Tasks; using Cuemon.AspNetCore.Configuration; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Options; @@ -43,7 +42,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp output.TagMode = TagMode.StartTagAndEndTag; output.TagName = "script"; output.Attributes.Add("type", "text/javascript"); - output.Attributes.Add("src", string.Concat(Options.GetFormattedBaseUrl(), UseCacheBusting ? string.Create(CultureInfo.InvariantCulture, $"{Src}?v={CacheBusting.Version}") : Src)); + output.Attributes.Add("src", ResolveUrl(Src)); if (Defer) { output.Attributes.Add("defer", "defer"); } return Task.CompletedTask; } diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperBaseUrlMode.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperBaseUrlMode.cs new file mode 100644 index 000000000..55c777ca0 --- /dev/null +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperBaseUrlMode.cs @@ -0,0 +1,15 @@ +namespace Cuemon.AspNetCore.Razor.TagHelpers; +/// +/// Specifies how the base URL of a static resource is resolved. +/// +public enum TagHelperBaseUrlMode +{ + /// + /// Specifies that the base URL is resolved exclusively from the configured values of and . + /// + Configured, + /// + /// Specifies that the base URL is resolved from the configured value of when available; otherwise from the current HTTP request. + /// + Automatic +} diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperOptions.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperOptions.cs index 37fbe684f..e7e1364db 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperOptions.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperOptions.cs @@ -1,6 +1,7 @@ using System.Globalization; using Cuemon.Configuration; using Cuemon.Text; +using Microsoft.AspNetCore.Http; namespace Cuemon.AspNetCore.Razor.TagHelpers; /// @@ -9,10 +10,10 @@ namespace Cuemon.AspNetCore.Razor.TagHelpers; public abstract class TagHelperOptions : IParameterObject { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// - /// The following table shows the initial property values for an instance of . + /// The following table shows the initial property values for an instance of . /// /// /// Property @@ -23,6 +24,10 @@ public abstract class TagHelperOptions : IParameterObject /// /// /// + /// + /// + /// + /// /// /// null /// @@ -30,6 +35,7 @@ public abstract class TagHelperOptions : IParameterObject /// protected TagHelperOptions() { + BaseUrlMode = TagHelperBaseUrlMode.Configured; Scheme = ProtocolUriScheme.Relative; } @@ -39,6 +45,12 @@ protected TagHelperOptions() /// The of these options. public ProtocolUriScheme Scheme { get; set; } + /// + /// Gets or sets the base URL resolution mode of these options. + /// + /// The base URL resolution mode of these options. + public TagHelperBaseUrlMode BaseUrlMode { get; set; } + /// /// Gets or sets the base URL of these options. /// @@ -51,20 +63,34 @@ protected TagHelperOptions() /// The base URL of this instance, formatted according to the defined . public string GetFormattedBaseUrl() { - var baseUrlIsNullOrEmpty = string.IsNullOrWhiteSpace(BaseUrl); + if (string.IsNullOrWhiteSpace(BaseUrl)) { return ""; } var baseUrlWithForwardingSlash = new Stem(BaseUrl).AttachSuffix("/"); switch (Scheme) { case ProtocolUriScheme.None: - return baseUrlIsNullOrEmpty ? "" : string.Create(CultureInfo.InvariantCulture, $"{baseUrlWithForwardingSlash}"); + return string.Create(CultureInfo.InvariantCulture, $"{baseUrlWithForwardingSlash}"); case ProtocolUriScheme.Http: - return baseUrlIsNullOrEmpty ? "" : string.Create(CultureInfo.InvariantCulture, $"{nameof(UriScheme.Http).ToLowerInvariant()}://{baseUrlWithForwardingSlash}"); + return string.Create(CultureInfo.InvariantCulture, $"{nameof(UriScheme.Http).ToLowerInvariant()}://{baseUrlWithForwardingSlash}"); case ProtocolUriScheme.Https: - return baseUrlIsNullOrEmpty ? "" : string.Create(CultureInfo.InvariantCulture, $"{nameof(UriScheme.Https).ToLowerInvariant()}://{baseUrlWithForwardingSlash}"); + return string.Create(CultureInfo.InvariantCulture, $"{nameof(UriScheme.Https).ToLowerInvariant()}://{baseUrlWithForwardingSlash}"); case ProtocolUriScheme.Relative: - return baseUrlIsNullOrEmpty ? "" : string.Create(CultureInfo.InvariantCulture, $"//{baseUrlWithForwardingSlash}"); + return string.Create(CultureInfo.InvariantCulture, $"//{baseUrlWithForwardingSlash}"); default: return ""; } } + + /// + /// Gets the base URL of this instance, resolved from the configured values of this instance or the specified . + /// + /// The current HTTP request that may provide the effective scheme, host and application base path when is and is not configured. + /// The base URL of this instance, resolved from the configured values of this instance or the specified . + public string GetFormattedBaseUrl(HttpRequest request) + { + if (BaseUrlMode == TagHelperBaseUrlMode.Automatic && string.IsNullOrWhiteSpace(BaseUrl) && request != null) + { + return string.Create(CultureInfo.InvariantCulture, $"{request.Scheme}://{request.Host.ToUriComponent()}{request.PathBase.ToUriComponent()}/"); + } + return GetFormattedBaseUrl(); + } } diff --git a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppImageTagHelperTest.cs b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppImageTagHelperTest.cs index 966bb0695..083aa6062 100644 --- a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppImageTagHelperTest.cs +++ b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppImageTagHelperTest.cs @@ -1,11 +1,6 @@ -using System.Threading.Tasks; -using Cuemon.AspNetCore.Razor.TagHelpers.Assets; -using Cuemon.Extensions.AspNetCore.Configuration; +using System; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; -using Codebelt.Extensions.Xunit.Hosting.AspNetCore; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Cuemon.AspNetCore.Razor.TagHelpers; @@ -18,65 +13,34 @@ public AppImageTagHelperTest(ITestOutputHelper output) : base(output) [Fact] public async Task Page_RenderImageTagForAppRole() { - using (var filter = WebHostTestFactory.Create(services => - { - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) - { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppImageTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + var body = await TagHelperTestFactory.GetBodyAsync("/AppImageTagHelper"); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } [Fact] public async Task Page_RenderImageTagForAppRole_WithCacheBusting() { - using (var filter = WebHostTestFactory.Create(services => - { - services.AddCacheBusting(); - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) + var body = await TagHelperTestFactory.GetBodyAsync("/AppImageTagHelper", useCacheBusting: true); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderImageTagForAppRole_UsingCurrentRequestOrigin() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppImageTagHelper?path=/images/logo.svg", o => { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppImageTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = null; + }, baseAddress: new Uri("https://localhost:7241")); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } } diff --git a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppLinkTagHelperTest.cs b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppLinkTagHelperTest.cs index 4bd1b9e70..950833045 100644 --- a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppLinkTagHelperTest.cs +++ b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppLinkTagHelperTest.cs @@ -1,11 +1,6 @@ -using System.Threading.Tasks; -using Cuemon.AspNetCore.Razor.TagHelpers.Assets; -using Cuemon.Extensions.AspNetCore.Configuration; +using System; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; -using Codebelt.Extensions.Xunit.Hosting.AspNetCore; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Cuemon.AspNetCore.Razor.TagHelpers; @@ -18,65 +13,89 @@ public AppLinkTagHelperTest(ITestOutputHelper output) : base(output) [Fact] public async Task Page_RenderLinkTagForAppRole() { - using (var filter = WebHostTestFactory.Create(services => - { - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) - { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppLinkTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper"); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } [Fact] public async Task Page_RenderLinkTagForAppRole_WithCacheBusting() { - using (var filter = WebHostTestFactory.Create(services => + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper", useCacheBusting: true); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderLinkTagForAppRole_WithoutConfiguredBaseUrl() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper?variant=stylesheet&path=/css/site.css", o => o.BaseUrl = null); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderLinkTagForAppRole_UsingCurrentRequestOrigin() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper?variant=stylesheet&path=css/site.css", o => { - services.AddCacheBusting(); - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = null; + o.Scheme = ProtocolUriScheme.Http; + }, baseAddress: new Uri("https://localhost:7241")); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderLinkTagForAppRole_UsingExplicitBaseUrlWhenAutomaticModeIsEnabled() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper?variant=stylesheet&path=/css/site.css", o => { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppLinkTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = "assets.example.com"; + o.Scheme = ProtocolUriScheme.Https; + }, baseAddress: new Uri("http://localhost:7241")); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderLinkTagForAppRole_PreservesFontPreloadAttributes() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper?variant=preload"); + + TestOutput.WriteLine(body); + + Assert.Contains(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Contains(@" - { - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) - { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppScriptTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + var body = await TagHelperTestFactory.GetBodyAsync("/AppScriptTagHelper"); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } [Fact] public async Task Page_RenderScriptTagForAppRole_WithCacheBusting() { - using (var filter = WebHostTestFactory.Create(services => + var body = await TagHelperTestFactory.GetBodyAsync("/AppScriptTagHelper", useCacheBusting: true); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderScriptTagForAppRole_UsingCurrentRequestOrigin() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppScriptTagHelper", o => { - services.AddCacheBusting(); - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = null; + }, baseAddress: new Uri("https://localhost:7241")); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderScriptTagForAppRole_UsingCurrentRequestOriginAndPathBase_WithCacheBusting() + { + var body = await TagHelperTestFactory.GetBodyAsync("/myapp/AppScriptTagHelper?path=~/js/site.js", o => + { + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = null; + }, useCacheBusting: true, baseAddress: new Uri("https://example.com"), pathBase: "/myapp"); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderScriptTagForAppRole_UsingLocalHttpExternalOriginWhenConfigured() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppScriptTagHelper?path=~/js/site.js", o => { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppScriptTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = "localhost:8080"; + o.Scheme = ProtocolUriScheme.Http; + }, baseAddress: new Uri("https://localhost:7241")); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } } diff --git a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppImageTagHelper.cshtml b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppImageTagHelper.cshtml index a5699d186..6a7113943 100644 --- a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppImageTagHelper.cshtml +++ b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppImageTagHelper.cshtml @@ -1,2 +1,6 @@ @page - \ No newline at end of file +@{ + var src = Request.Query["path"].ToString(); + if (string.IsNullOrWhiteSpace(src)) { src = "cuemon-logo.svg"; } +} + \ No newline at end of file diff --git a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppLinkTagHelper.cshtml b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppLinkTagHelper.cshtml index 6bd541af6..74308e07a 100644 --- a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppLinkTagHelper.cshtml +++ b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppLinkTagHelper.cshtml @@ -1,2 +1,40 @@ @page -