From 2fcc9cb44523f33f7b791fec5cef6362addc041b Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Tue, 19 May 2026 11:12:49 -0300 Subject: [PATCH] Preserve request URL casing in ApplicationPath on .NET Framework In .NET Framework, HttpRequest.ApplicationPath returns the path as configured in IIS regardless of the casing the client used in the URL, while .NET Core's PathBase preserves the request casing. Callers like GAM use this value as a cookie Path; since cookie paths are case-sensitive per RFC 6265, a mismatch caused the browser to drop the cookie when the URL casing differed from IIS. GetApplicationPath now returns the matching prefix taken from Request.Url.AbsolutePath, aligning behavior across frameworks. New appSettings flag PreserveApplicationPathCasing (default true) allows reverting to the historical behavior if needed. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../GxClasses/Helpers/HttpHelper.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs index aee97e8b7..055e9cf5f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs @@ -1310,9 +1310,41 @@ public static string GetApplicationPath(this HttpRequest request) else return string.Empty; #else - return request.ApplicationPath; + string appPath = request.ApplicationPath; + if (!PreserveApplicationPathCasing || string.IsNullOrEmpty(appPath) || appPath == "/") + return appPath; + // Align .NET Framework behavior with .NET Core: return the path using + // the casing of the actual request URL (cookie paths are case-sensitive + // per RFC 6265, so the path written by callers must match what the + // browser sees in the address bar). + string urlPath = request.Url.AbsolutePath; + if (!string.IsNullOrEmpty(urlPath) + && urlPath.Length >= appPath.Length + && urlPath.StartsWith(appPath, StringComparison.OrdinalIgnoreCase)) + { + return urlPath.Substring(0, appPath.Length); + } + return appPath; #endif } +#if !NETCORE + static bool? _preserveApplicationPathCasing; + static bool PreserveApplicationPathCasing + { + get + { + if (!_preserveApplicationPathCasing.HasValue) + { + if (Config.GetValueOf("PreserveApplicationPathCasing", out string value) + && bool.TryParse(value, out bool parsed)) + _preserveApplicationPathCasing = parsed; + else + _preserveApplicationPathCasing = true; + } + return _preserveApplicationPathCasing.Value; + } + } +#endif public static Uri GetUrlReferrer(this HttpRequest request) { #if NETCORE