From b7b7c472af557622dbfb59b1958a276a1cefdd51 Mon Sep 17 00:00:00 2001 From: "Valeriano A.R." Date: Tue, 29 Jul 2025 02:05:28 +0200 Subject: [PATCH] Enhance dictionary safety with `SafeGet`, `SafeSet`, and `SafeRemove` methods. Adjust `IWebContext` and related tests to support nullable value types in dictionary operations. Refactor `GetRequestParameter` for clarity and consistency. --- .../Code/AspnetCoreWebContext.cs | 6 +-- .../Code/ExtensionMethodsTests.cs | 8 ++-- .../Controls/ButtonTests.cs | 3 +- .../Controls/CTextBoxTests.cs | 11 +++--- .../Controls/HiddenFieldTests.cs | 3 +- .../Controls/HtmlFormTests.cs | 3 +- .../Controls/TextBoxTests.cs | 3 +- .../Fakes/FakeWebContext.cs | 4 +- VAR.WebFormsCore.Tests/Pages/FrmEchoTests.cs | 5 ++- .../Pages/PageCommonTests.cs | 2 +- VAR.WebFormsCore/Code/ExtensionMethods.cs | 38 +++++++++++++------ VAR.WebFormsCore/Code/IWebContext.cs | 3 +- 12 files changed, 55 insertions(+), 34 deletions(-) diff --git a/VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs b/VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs index ee2556c..4eb7727 100644 --- a/VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs +++ b/VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs @@ -34,16 +34,16 @@ public class AspnetCoreWebContext : IWebContext } - private Dictionary? _requestCookies; + private Dictionary? _requestCookies; - public Dictionary RequestCookies + public Dictionary RequestCookies { get { if (_requestCookies == null) { _requestCookies = _context.Request.Cookies - .ToDictionary(p => p.Key, p => p.Value); + .ToDictionary(p => p.Key, p => (string?)p.Value); } return _requestCookies; diff --git a/VAR.WebFormsCore.Tests/Code/ExtensionMethodsTests.cs b/VAR.WebFormsCore.Tests/Code/ExtensionMethodsTests.cs index c232c3b..547a500 100644 --- a/VAR.WebFormsCore.Tests/Code/ExtensionMethodsTests.cs +++ b/VAR.WebFormsCore.Tests/Code/ExtensionMethodsTests.cs @@ -38,7 +38,7 @@ public class ExtensionMethodsTests FakeWebContext fakeWebContext = new(); string key = "Key"; string value = "Value"; - fakeWebContext.RequestQuery.Add(key, value); + fakeWebContext.RequestQuery.SafeSet(key, value); string result = fakeWebContext.GetRequestParameter(key); @@ -52,7 +52,7 @@ public class ExtensionMethodsTests FakeWebContext fakeWebContext = new(requestMethod: "POST"); string key = "Key"; string value = "Value"; - fakeWebContext.RequestForm.Add(key, value); + fakeWebContext.RequestForm.SafeSet(key, value); string result = fakeWebContext.GetRequestParameter(key); @@ -67,7 +67,7 @@ public class ExtensionMethodsTests string keyInvalid = "KeyInvalid"; string key = "Key"; string value = "Value"; - fakeWebContext.RequestQuery.Add(keyInvalid, value); + fakeWebContext.RequestQuery.SafeSet(keyInvalid, value); string result = fakeWebContext.GetRequestParameter(key); @@ -82,7 +82,7 @@ public class ExtensionMethodsTests string keyInvalid = "KeyInvalid"; string key = "Key"; string value = "Value"; - fakeWebContext.RequestForm.Add(keyInvalid, value); + fakeWebContext.RequestForm.SafeSet(keyInvalid, value); string result = fakeWebContext.GetRequestParameter(key); diff --git a/VAR.WebFormsCore.Tests/Controls/ButtonTests.cs b/VAR.WebFormsCore.Tests/Controls/ButtonTests.cs index 8d7546c..3869d99 100644 --- a/VAR.WebFormsCore.Tests/Controls/ButtonTests.cs +++ b/VAR.WebFormsCore.Tests/Controls/ButtonTests.cs @@ -1,3 +1,4 @@ +using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Tests.Fakes; @@ -56,7 +57,7 @@ public class ButtonTests button.Click += (o, _) => { result = (o as Button)?.CommandArgument; }; page.Controls.Add(button); - fakeWebContext.RequestForm.Add(button.ClientID, "Clicked"); + fakeWebContext.RequestForm.SafeSet(button.ClientID, "Clicked"); page.ProcessRequest(fakeWebContext); Assert.Equal(commandArgument, result); diff --git a/VAR.WebFormsCore.Tests/Controls/CTextBoxTests.cs b/VAR.WebFormsCore.Tests/Controls/CTextBoxTests.cs index 9b2043a..ed92a92 100644 --- a/VAR.WebFormsCore.Tests/Controls/CTextBoxTests.cs +++ b/VAR.WebFormsCore.Tests/Controls/CTextBoxTests.cs @@ -1,3 +1,4 @@ +using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Tests.Fakes; @@ -94,7 +95,7 @@ public class CTextBoxTests page0.ProcessRequest(fakeWebContext0); FakeWebContext fakeWebContext1 = new(requestMethod: "POST"); - fakeWebContext1.RequestForm.Add(cTextBox0.TxtContent.ClientID, changedValue); + fakeWebContext1.RequestForm.SafeSet(cTextBox0.TxtContent.ClientID, changedValue); Page page1 = new(); CTextBox cTextBox1 = new() { Text = text }; page1.Controls.Add(cTextBox1); @@ -188,7 +189,7 @@ public class CTextBoxTests }; page.Controls.Add(button); - fakeWebContext.RequestForm.Add(button.ClientID, "Clicked"); + fakeWebContext.RequestForm.SafeSet(button.ClientID, "Clicked"); page.ProcessRequest(fakeWebContext); int? resultHeight = cTextBox.GetClientsideHeight(); @@ -222,7 +223,7 @@ public class CTextBoxTests button.Click += (_, _) => { cTextBox.SetClientsideHeight(null); }; page.Controls.Add(button); - fakeWebContext.RequestForm.Add(button.ClientID, "Clicked"); + fakeWebContext.RequestForm.SafeSet(button.ClientID, "Clicked"); page.ProcessRequest(fakeWebContext); int? resultHeight = cTextBox.GetClientsideHeight(); @@ -259,7 +260,7 @@ public class CTextBoxTests }; page.Controls.Add(button); - fakeWebContext.RequestForm.Add(button.ClientID, "Clicked"); + fakeWebContext.RequestForm.SafeSet(button.ClientID, "Clicked"); page.ProcessRequest(fakeWebContext); int? resultHeight = cTextBox.GetClientsideHeight(); @@ -286,7 +287,7 @@ public class CTextBoxTests }; page.Controls.Add(button); - fakeWebContext.RequestForm.Add(button.ClientID, "Clicked"); + fakeWebContext.RequestForm.SafeSet(button.ClientID, "Clicked"); page.ProcessRequest(fakeWebContext); int? resultHeight = cTextBox.GetClientsideHeight(); diff --git a/VAR.WebFormsCore.Tests/Controls/HiddenFieldTests.cs b/VAR.WebFormsCore.Tests/Controls/HiddenFieldTests.cs index 4be85f2..4990260 100644 --- a/VAR.WebFormsCore.Tests/Controls/HiddenFieldTests.cs +++ b/VAR.WebFormsCore.Tests/Controls/HiddenFieldTests.cs @@ -1,3 +1,4 @@ +using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Tests.Fakes; @@ -51,7 +52,7 @@ public class HiddenFieldTests HiddenField hiddenField = new() { Value = value }; page.Controls.Add(hiddenField); - fakeWebContext.RequestForm.Add(hiddenField.ClientID, changedValue); + fakeWebContext.RequestForm.SafeSet(hiddenField.ClientID, changedValue); page.ProcessRequest(fakeWebContext); Assert.Equal(changedValue, hiddenField.Value); diff --git a/VAR.WebFormsCore.Tests/Controls/HtmlFormTests.cs b/VAR.WebFormsCore.Tests/Controls/HtmlFormTests.cs index e2b527a..e73fa54 100644 --- a/VAR.WebFormsCore.Tests/Controls/HtmlFormTests.cs +++ b/VAR.WebFormsCore.Tests/Controls/HtmlFormTests.cs @@ -1,3 +1,4 @@ +using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Tests.Fakes; @@ -27,7 +28,7 @@ public class HtmlFormTests public void MustRenderCorrectly__WithQueryParameters() { FakeWebContext fakeWebContext = new(); - fakeWebContext.RequestQuery.Add("test", "value"); + fakeWebContext.RequestQuery.SafeSet("test", "value"); Page page = new(); HtmlForm htmlForm = new(); page.Controls.Add(htmlForm); diff --git a/VAR.WebFormsCore.Tests/Controls/TextBoxTests.cs b/VAR.WebFormsCore.Tests/Controls/TextBoxTests.cs index 36585a1..291198b 100644 --- a/VAR.WebFormsCore.Tests/Controls/TextBoxTests.cs +++ b/VAR.WebFormsCore.Tests/Controls/TextBoxTests.cs @@ -1,3 +1,4 @@ +using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Tests.Fakes; @@ -138,7 +139,7 @@ public class TextBoxTests TextBox textBox = new() { Text = text }; page.Controls.Add(textBox); - fakeWebContext.RequestForm.Add(textBox.ClientID, changedValue); + fakeWebContext.RequestForm.SafeSet(textBox.ClientID, changedValue); page.ProcessRequest(fakeWebContext); Assert.Equal(changedValue, textBox.Text); diff --git a/VAR.WebFormsCore.Tests/Fakes/FakeWebContext.cs b/VAR.WebFormsCore.Tests/Fakes/FakeWebContext.cs index 3621582..74ecb95 100644 --- a/VAR.WebFormsCore.Tests/Fakes/FakeWebContext.cs +++ b/VAR.WebFormsCore.Tests/Fakes/FakeWebContext.cs @@ -22,7 +22,7 @@ public class FakeWebContext : IWebContext public Dictionary RequestHeader { get; } = new(); - public Dictionary RequestCookies { get; } = new(); + public Dictionary RequestCookies { get; } = new(); public Dictionary RequestQuery { get; } = new(); @@ -32,7 +32,7 @@ public class FakeWebContext : IWebContext public long? RequestContentLength { get; } - public byte[]? RequestReadBin() + public byte[] RequestReadBin() { throw new NotImplementedException(); } diff --git a/VAR.WebFormsCore.Tests/Pages/FrmEchoTests.cs b/VAR.WebFormsCore.Tests/Pages/FrmEchoTests.cs index 70197c9..f2ff8ac 100644 --- a/VAR.WebFormsCore.Tests/Pages/FrmEchoTests.cs +++ b/VAR.WebFormsCore.Tests/Pages/FrmEchoTests.cs @@ -1,3 +1,4 @@ +using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Tests.Fakes; using Xunit; @@ -31,7 +32,7 @@ public class FrmEchoTests public void ProcessRequest__OneQueryParameterGet__FormData() { FakeWebContext fakeWebContext = new(); - fakeWebContext.RequestQuery.Add("Test", "Value"); + fakeWebContext.RequestQuery.SafeSet("Test", "Value"); FrmEcho frmEcho = new(); frmEcho.ProcessRequest(fakeWebContext); @@ -53,7 +54,7 @@ public class FrmEchoTests public void ProcessRequest__OneFormParameterPost__FormData() { FakeWebContext fakeWebContext = new(requestMethod: "POST"); - fakeWebContext.RequestForm.Add("Test", "Value"); + fakeWebContext.RequestForm.SafeSet("Test", "Value"); FrmEcho frmEcho = new(); frmEcho.ProcessRequest(fakeWebContext); diff --git a/VAR.WebFormsCore.Tests/Pages/PageCommonTests.cs b/VAR.WebFormsCore.Tests/Pages/PageCommonTests.cs index eeb0592..1db4176 100644 --- a/VAR.WebFormsCore.Tests/Pages/PageCommonTests.cs +++ b/VAR.WebFormsCore.Tests/Pages/PageCommonTests.cs @@ -55,7 +55,7 @@ public class PageCommonTests (GlobalConfig.Get() as FakeGlobalConfig)?.FakeSetLoginHandler(loginHandler); (GlobalConfig.Get() as FakeGlobalConfig)?.FakeSetAuthenticated(true); FakeWebContext fakeWebContext = new(requestMethod: "POST"); - fakeWebContext.RequestForm.Add("ctl00_ctl02_btnLogout", "Logout"); + fakeWebContext.RequestForm.SafeSet("ctl00_ctl02_btnLogout", "Logout"); TestEmptyForm testEmptyForm = new(mustBeAuthenticated: true); testEmptyForm.ProcessRequest(fakeWebContext); diff --git a/VAR.WebFormsCore/Code/ExtensionMethods.cs b/VAR.WebFormsCore/Code/ExtensionMethods.cs index d40b8a9..d09a2cb 100644 --- a/VAR.WebFormsCore/Code/ExtensionMethods.cs +++ b/VAR.WebFormsCore/Code/ExtensionMethods.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Text; using VAR.Json; @@ -11,23 +12,17 @@ public static class ExtensionMethods { if (context.RequestMethod == "POST") { - foreach (string key in context.RequestForm.Keys) + if (context.RequestForm.ContainsKey(parameter)) { - if (string.IsNullOrEmpty(key) == false && key == parameter) - { - return context.RequestForm[key] ?? string.Empty; - } + return context.RequestForm.SafeGet(parameter, null) ?? string.Empty; } } - - foreach (string key in context.RequestQuery.Keys) + + if (context.RequestQuery.ContainsKey(parameter)) { - if (string.IsNullOrEmpty(key) == false && key == parameter) - { - return context.RequestQuery[key] ?? string.Empty; - } + return context.RequestQuery.SafeGet(parameter, null) ?? string.Empty; } - + return string.Empty; } @@ -42,4 +37,23 @@ public static class ExtensionMethods } #endregion IWebContext + + #region Dictionary + + public static TValue? SafeGet(this IDictionary dictionary, TKey key, TValue defaultValue) + { + return dictionary.TryGetValue(key, out TValue? value) ? value : defaultValue; + } + + public static void SafeSet(this IDictionary dictionary, TKey key, TValue value) + { + dictionary[key] = value; + } + + public static void SafeRemove(this IDictionary dictionary, TKey key) + { + dictionary.Remove(key); + } + + #endregion Dictionary } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/IWebContext.cs b/VAR.WebFormsCore/Code/IWebContext.cs index ccf33bf..c5a7148 100644 --- a/VAR.WebFormsCore/Code/IWebContext.cs +++ b/VAR.WebFormsCore/Code/IWebContext.cs @@ -7,8 +7,9 @@ public interface IWebContext { string RequestPath { get; } string RequestMethod { get; } + Dictionary RequestHeader { get; } - Dictionary RequestCookies { get; } + Dictionary RequestCookies { get; } Dictionary RequestQuery { get; } Dictionary RequestForm { get; }