From c144890bc3485a7dfd32268a4128c058cc291c39 Mon Sep 17 00:00:00 2001
From: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com>
Date: Tue, 7 Apr 2026 14:45:53 -0700
Subject: [PATCH] Enable User Agent feature extension (#4124)
---
.../Data/SqlClient/LocalAppContextSwitches.cs | 24 ---------
.../src/Microsoft/Data/SqlClient/TdsParser.cs | 2 +-
.../Common/LocalAppContextSwitchesHelper.cs | 15 ------
.../SqlClient/LocalAppContextSwitchesTest.cs | 1 -
.../SimulatedServerTests/ConnectionTests.cs | 54 -------------------
5 files changed, 1 insertion(+), 95 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
index 7694092907..16e0abb7ec 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
@@ -36,13 +36,6 @@ internal static class LocalAppContextSwitches
private const string EnableMultiSubnetFailoverByDefaultString =
"Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault";
- ///
- /// The name of the app context switch that controls whether
- /// the user agent feature is enabled.
- ///
- private const string EnableUserAgentString =
- "Switch.Microsoft.Data.SqlClient.EnableUserAgent";
-
#if NET
///
/// The name of the app context switch that controls whether
@@ -177,11 +170,6 @@ private enum SwitchValue : byte
///
private static SwitchValue s_enableMultiSubnetFailoverByDefault = SwitchValue.None;
- ///
- /// The cached value of the EnableUserAgent switch.
- ///
- private static SwitchValue s_enableUserAgent = SwitchValue.None;
-
#if NET
///
/// The cached value of the GlobalizationInvariantMode switch.
@@ -319,18 +307,6 @@ static LocalAppContextSwitches()
defaultValue: false,
ref s_enableMultiSubnetFailoverByDefault);
- ///
- /// When set to true, the user agent feature is enabled and the driver will
- /// send the user agent string to the server.
- ///
- /// The default value of this switch is false.
- ///
- public static bool EnableUserAgent =>
- AcquireAndReturn(
- EnableUserAgentString,
- defaultValue: false,
- ref s_enableUserAgent);
-
#if NET
///
/// .NET Core 2.0 and up supports Globalization Invariant mode, which
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs
index 94281b4998..088d41d94d 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs
@@ -9663,7 +9663,7 @@ private int ApplyFeatureExData(TdsEnums.FeatureExtension requestedFeatures,
checked
{
// NOTE: As part of TDS spec UserAgent feature extension should be the first feature extension in the list.
- if (LocalAppContextSwitches.EnableUserAgent && ((requestedFeatures & TdsEnums.FeatureExtension.UserAgent) != 0))
+ if ((requestedFeatures & TdsEnums.FeatureExtension.UserAgent) != 0)
{
length += WriteUserAgentFeatureRequest(userAgent, write);
}
diff --git a/src/Microsoft.Data.SqlClient/tests/Common/LocalAppContextSwitchesHelper.cs b/src/Microsoft.Data.SqlClient/tests/Common/LocalAppContextSwitchesHelper.cs
index 4a0cdf67de..8102f47d51 100644
--- a/src/Microsoft.Data.SqlClient/tests/Common/LocalAppContextSwitchesHelper.cs
+++ b/src/Microsoft.Data.SqlClient/tests/Common/LocalAppContextSwitchesHelper.cs
@@ -43,7 +43,6 @@ public sealed class LocalAppContextSwitchesHelper : IDisposable
private readonly bool? _disableTnirByDefaultOriginal;
#endif
private readonly bool? _enableMultiSubnetFailoverByDefaultOriginal;
- private readonly bool? _enableUserAgentOriginal;
#if NET
private readonly bool? _globalizationInvariantModeOriginal;
#endif
@@ -93,8 +92,6 @@ public LocalAppContextSwitchesHelper()
#endif
_enableMultiSubnetFailoverByDefaultOriginal =
GetSwitchValue("s_enableMultiSubnetFailoverByDefault");
- _enableUserAgentOriginal =
- GetSwitchValue("s_enableUserAgent");
#if NET
_globalizationInvariantModeOriginal =
GetSwitchValue("s_globalizationInvariantMode");
@@ -149,9 +146,6 @@ public void Dispose()
SetSwitchValue(
"s_enableMultiSubnetFailoverByDefault",
_enableMultiSubnetFailoverByDefaultOriginal);
- SetSwitchValue(
- "s_enableUserAgent",
- _enableUserAgentOriginal);
#if NET
SetSwitchValue(
"s_globalizationInvariantMode",
@@ -228,15 +222,6 @@ public bool? EnableMultiSubnetFailoverByDefault
set => SetSwitchValue("s_enableMultiSubnetFailoverByDefault", value);
}
- ///
- /// Get or set the EnableUserAgent switch value.
- ///
- public bool? EnableUserAgent
- {
- get => GetSwitchValue("s_enableUserAgent");
- set => SetSwitchValue("s_enableUserAgent", value);
- }
-
#if NET
///
/// Get or set the GlobalizationInvariantMode switch value.
diff --git a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/LocalAppContextSwitchesTest.cs b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/LocalAppContextSwitchesTest.cs
index 59445a26b6..a5db02faa0 100644
--- a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/LocalAppContextSwitchesTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/LocalAppContextSwitchesTest.cs
@@ -28,7 +28,6 @@ public void TestDefaultAppContextSwitchValues()
Assert.False(LocalAppContextSwitches.UseConnectionPoolV2);
Assert.False(LocalAppContextSwitches.TruncateScaledDecimal);
Assert.False(LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner);
- Assert.False(LocalAppContextSwitches.EnableUserAgent);
Assert.False(LocalAppContextSwitches.EnableMultiSubnetFailoverByDefault);
#if NET
Assert.False(LocalAppContextSwitches.GlobalizationInvariantMode);
diff --git a/src/Microsoft.Data.SqlClient/tests/UnitTests/SimulatedServerTests/ConnectionTests.cs b/src/Microsoft.Data.SqlClient/tests/UnitTests/SimulatedServerTests/ConnectionTests.cs
index a729e6afe2..06553b11f5 100644
--- a/src/Microsoft.Data.SqlClient/tests/UnitTests/SimulatedServerTests/ConnectionTests.cs
+++ b/src/Microsoft.Data.SqlClient/tests/UnitTests/SimulatedServerTests/ConnectionTests.cs
@@ -840,10 +840,6 @@ public void TestConnWithVectorFeatExtVersionNegotiation(bool expectedConnectionR
[InlineData(false)]
public void TestConnWithUserAgentFeatureExtension(bool sendAck)
{
- // Enable sending the UserAgent if desired.
- using LocalAppContextSwitchesHelper switchesHelper = new();
- switchesHelper.EnableUserAgent = true;
-
// Start the test server.
using TdsServer server = new();
server.Start();
@@ -904,55 +900,5 @@ public void TestConnWithUserAgentFeatureExtension(bool sendAck)
// TODO: Confirm the server sent an Ack by reading log message from SqlInternalConnectionTds
}
-
- ///
- /// Test to verify no UserAgent relevant information is sent when EnableUserAgentField switch is disabled.
- ///
- [Fact]
- public void TestConnWithoutUserAgentFeatureExtension()
- {
- // Disable the client-side UserAgent field entirely
- using LocalAppContextSwitchesHelper switchesHelper = new();
- switchesHelper.EnableUserAgent = false;
-
- using var server = new TdsServer();
- server.Start();
-
- // Do not advertise or force the UserAgent feature on the server
- server.ServerSupportedUserAgentFeatureExtVersion = 0x00; // no support
- server.EnableUserAgentFeatureExt = false; // no forced ACK
-
- bool loginValidated = false;
- bool userAgentFeatureSeen = false;
-
- // Inspect the LOGIN7 packet captured by the test server
- server.OnLogin7Validated = loginToken =>
- {
- var featureExtTokens = loginToken.FeatureExt
- .OfType()
- .ToArray();
-
- // Ensure there is no UserAgentSupport token at all
- var uaToken = featureExtTokens.FirstOrDefault(t => t.FeatureID == TDSFeatureID.UserAgentSupport);
- userAgentFeatureSeen = uaToken is not null;
-
- loginValidated = true;
- };
-
- // Connect to the test TDS server with a basic connection string
- var connStr = new SqlConnectionStringBuilder
- {
- DataSource = $"localhost,{server.EndPoint.Port}",
- Encrypt = SqlConnectionEncryptOption.Optional,
- }.ConnectionString;
-
- using var connection = new SqlConnection(connStr);
- connection.Open();
-
- // Verify that the connection succeeded and no UserAgent data was sent
- Assert.Equal(ConnectionState.Open, connection.State);
- Assert.True(loginValidated, "Expected LOGIN7 to be validated by the test server");
- Assert.False(userAgentFeatureSeen, "Did not expect a UserAgentSupport feature token in LOGIN7");
- }
}
}