diff --git a/dotnet/src/webdriver/Command.cs b/dotnet/src/webdriver/Command.cs
index b7acb42ef2dbf..28034ce57dfa4 100644
--- a/dotnet/src/webdriver/Command.cs
+++ b/dotnet/src/webdriver/Command.cs
@@ -20,6 +20,7 @@
 using OpenQA.Selenium.Internal;
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Text.Json;
 using System.Text.Json.Serialization;
 using System.Text.Json.Serialization.Metadata;
@@ -31,15 +32,29 @@ namespace OpenQA.Selenium;
 /// </summary>
 public class Command
 {
-    private readonly static JsonSerializerOptions s_jsonSerializerOptions = new()
+    [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = $"All trimming-unsafe access points to {nameof(s_jsonSerializerOptions)} are annotated as such")]
+    [UnconditionalSuppressMessage("AOT", "IL3050", Justification = $"All AOT-unsafe access points to {nameof(s_jsonSerializerOptions)} are annotated as such")]
+    private static class JsonOptionsHolder
     {
-        TypeInfoResolverChain =
+        public readonly static JsonSerializerOptions s_jsonSerializerOptions = new()
         {
-            CommandJsonSerializerContext.Default,
-            new DefaultJsonTypeInfoResolver()
-        },
-        Converters = { new ResponseValueJsonConverter() }
-    };
+            TypeInfoResolver = GetTypeInfoResolver(),
+            Converters = { new ResponseValueJsonConverter() }
+        };
+
+        private static IJsonTypeInfoResolver GetTypeInfoResolver()
+        {
+#if NET8_0_OR_GREATER
+            if (!System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported)
+            {
+                return CommandJsonSerializerContext.Default;
+            }
+#endif
+            return JsonTypeInfoResolver.Combine(CommandJsonSerializerContext.Default, new DefaultJsonTypeInfoResolver());
+        }
+    }
+
+    private readonly Dictionary<string, object?> _parameters;
 
     /// <summary>
     /// Initializes a new instance of the <see cref="Command"/> class using a command name and a JSON-encoded string for the parameters.
@@ -47,8 +62,10 @@ public class Command
     /// <param name="name">Name of the command</param>
     /// <param name="jsonParameters">Parameters for the command as a JSON-encoded string.</param>
     public Command(string name, string jsonParameters)
-        : this(null, name, ConvertParametersFromJson(jsonParameters))
     {
+        this.SessionId = null;
+        this._parameters = ConvertParametersFromJson(jsonParameters) ?? new Dictionary<string, object?>();
+        this.Name = name ?? throw new ArgumentNullException(nameof(name));
     }
 
     /// <summary>
@@ -61,7 +78,7 @@ public Command(string name, string jsonParameters)
     public Command(SessionId? sessionId, string name, Dictionary<string, object?>? parameters)
     {
         this.SessionId = sessionId;
-        this.Parameters = parameters ?? new Dictionary<string, object?>();
+        this._parameters = parameters ?? new Dictionary<string, object?>();
         this.Name = name ?? throw new ArgumentNullException(nameof(name));
     }
 
@@ -81,18 +98,32 @@ public Command(SessionId? sessionId, string name, Dictionary<string, object?>? p
     /// Gets the parameters of the command
     /// </summary>
     [JsonPropertyName("parameters")]
-    public Dictionary<string, object?> Parameters { get; }
+    public Dictionary<string, object?> Parameters
+    {
+        [RequiresUnreferencedCode("Adding untyped parameter values for JSON serialization has best-effort AOT support. Ensure only Selenium types and well-known .NET types are added.")]
+        [RequiresDynamicCode("Adding untyped parameter values for JSON serialization has best-effort AOT support. Ensure only Selenium types and well-known .NET types are added.")]
+        get => _parameters;
+    }
 
     /// <summary>
     /// Gets the parameters of the command as a JSON-encoded string.
     /// </summary>
     public string ParametersAsJsonString
     {
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = $"All trimming-unsafe access points to {nameof(_parameters)} are annotated as such")]
+        [UnconditionalSuppressMessage("AOT", "IL3050", Justification = $"All AOT-unsafe access points to {nameof(_parameters)} are annotated as such")]
         get
         {
-            if (this.Parameters != null && this.Parameters.Count > 0)
+            if (HasParameters())
             {
-                return JsonSerializer.Serialize(this.Parameters, s_jsonSerializerOptions);
+                try
+                {
+                    return JsonSerializer.Serialize(this._parameters, JsonOptionsHolder.s_jsonSerializerOptions);
+                }
+                catch (NotSupportedException ex)
+                {
+                    throw new WebDriverException("Attempted to serialize an unsupported type. Ensure you are using Selenium types, or well-known .NET types such as Dictionary<string, object> and object[]", ex);
+                }
             }
             else
             {
@@ -101,6 +132,25 @@ public string ParametersAsJsonString
         }
     }
 
+    internal bool HasParameters()
+    {
+        return this._parameters != null && this._parameters.Count > 0;
+    }
+
+    internal bool TryGetValueAndRemoveIfNotNull(string key, [NotNullWhen(true)] out object? value)
+    {
+        if (this._parameters.TryGetValue(key, out value))
+        {
+            if (value is not null)
+            {
+                this._parameters.Remove(key);
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /// <summary>
     /// Returns a string of the Command object
     /// </summary>
@@ -168,5 +218,6 @@ public override string ToString()
 [JsonSerializable(typeof(Dictionary<string, short>))]
 [JsonSerializable(typeof(Dictionary<string, ushort>))]
 [JsonSerializable(typeof(Dictionary<string, string>))]
+[JsonSerializable(typeof(object[]))]
 [JsonSourceGenerationOptions(Converters = [typeof(ResponseValueJsonConverter)])]
 internal partial class CommandJsonSerializerContext : JsonSerializerContext;
diff --git a/dotnet/src/webdriver/HttpCommandInfo.cs b/dotnet/src/webdriver/HttpCommandInfo.cs
index 38e7b382d697f..60d227250aec2 100644
--- a/dotnet/src/webdriver/HttpCommandInfo.cs
+++ b/dotnet/src/webdriver/HttpCommandInfo.cs
@@ -119,17 +119,13 @@ private static string GetCommandPropertyValue(string propertyName, Command comma
                 propertyValue = commandToExecute.SessionId.ToString();
             }
         }
-        else if (commandToExecute.Parameters != null && commandToExecute.Parameters.Count > 0)
+        else if (commandToExecute.HasParameters())
         {
             // Extract the URL parameter, and remove it from the parameters dictionary
             // so it doesn't get transmitted as a JSON parameter.
-            if (commandToExecute.Parameters.TryGetValue(propertyName, out var propertyValueObject))
+            if (commandToExecute.TryGetValueAndRemoveIfNotNull(propertyName, out var propertyValueObject))
             {
-                if (propertyValueObject != null)
-                {
-                    propertyValue = propertyValueObject.ToString()!;
-                    commandToExecute.Parameters.Remove(propertyName);
-                }
+                propertyValue = propertyValueObject.ToString()!;
             }
         }
 
diff --git a/dotnet/src/webdriver/WebDriver.cs b/dotnet/src/webdriver/WebDriver.cs
index 77f82461053d7..b88403643d2d0 100644
--- a/dotnet/src/webdriver/WebDriver.cs
+++ b/dotnet/src/webdriver/WebDriver.cs
@@ -40,7 +40,7 @@ public class WebDriver : IWebDriver, ISearchContext, IJavaScriptExecutor, IFinds
     /// </summary>
     protected static readonly TimeSpan DefaultCommandTimeout = TimeSpan.FromSeconds(60);
     private IFileDetector fileDetector = new DefaultFileDetector();
-    private NetworkManager network;
+    private NetworkManager? network;
     private WebElementFactory elementFactory;
 
     private readonly List<string> registeredCommands = new List<string>();