Skip to content

Commit f0def26

Browse files
upgrade package version and bug fix for mi to work (#27)
Co-authored-by: Prasad Nikumbh <prnikumb@microsoft.com>
1 parent 33cbae1 commit f0def26

11 files changed

Lines changed: 146 additions & 40 deletions

File tree

src/sdk/Core/Configurations/RetryProtocol.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static RetryProtocol GetDefaultOperationProtocol()
3333
MaxRetryCount = 50,
3434
MinBackoffIntervalInMs = 2000,
3535
MaxBackoffIntervalInMs = 15000,
36-
TimeoutInMs = 3000,
36+
TimeoutInMs = 10000, // 10 seconds - allows time for MI token acquisition
3737
HardTimeoutEnabled = false
3838
};
3939
}

src/sdk/Core/Microsoft.UnifiedRedisPlatform.Core.csproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<LangVersion>latest</LangVersion>
6-
<Version>1.5.0</Version>
6+
<Version>1.6.0</Version>
77
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
88
<Authors>Pratik Bhattacharya</Authors>
99
<Company>Microsoft</Company>
1010
<Product>Unified Redis Platform</Product>
1111
<Description>Lighweight library to connect to a common Redis Cache from multiple applications</Description>
1212
<PackageReleaseNotes>
13-
v1.3.0:
13+
v1.6.0:
14+
- Fixed: Managed Identity token refresh - now uses ConfigureForAzureWithTokenCredentialAsync for automatic token renewal
15+
- Improved: Default operation timeout increased from 3s to 10s to accommodate MI token acquisition
16+
- Improved: Added 60-second keep-alive to prevent stale connections
17+
- All MI authentication methods (ServerOptions, LocalOptions, Direct Connect) now work correctly
1418
- Added Managed Identity (MI) support for Azure Redis Cache authentication
1519
- Upgraded to Microsoft.Azure.StackExchangeRedis 3.2.1
1620
- Added ConnectAsync() method for async connection initialization

src/sdk/Core/Microsoft.UnifiedRedisPlatform.Core.nuspec

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
<package >
33
<metadata>
44
<id>Microsoft.UnifiedRedisPlatform.Core</id>
5-
<version>1.5.0</version>
5+
<version>1.6.0</version>
66
<title>Microsoft.UnifiedRedisPlatform.Core</title>
77
<authors>Pratik Bhattacharya</authors>
88
<owners>Microsoft</owners>
99
<projectUrl>https://dev.azure.com/MicrosoftIT/OneITVSO/_workitems/edit/4288461</projectUrl>
1010
<requireLicenseAcceptance>false</requireLicenseAcceptance>
1111
<description>Lighweight library to connect to a common Redis Cache from multiple applications</description>
1212
<releaseNotes>
13+
v1.6.0:
14+
- Package version update
15+
1316
v1.5.0:
1417
- Added Managed Identity support for Manager API
1518
- Improved configuration handling for ManagedIdentityClientId

src/sdk/Core/RedisConnectionBuilder.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.UnifiedRedisPlatform.Core.Services.Interfaces;
1010
using Azure.Core;
1111
using Azure.Identity;
12+
using Microsoft.Azure.StackExchangeRedis;
1213

1314
namespace Microsoft.UnifiedRedisPlatform.Core
1415
{
@@ -31,11 +32,11 @@ public RedisConnectionBuilder(string serviceEndpoint, string clusterName, string
3132
_appSecret = appSecret;
3233
_managedIdentityClientId = managedIdentityClientId;
3334
_serviceEndpoint = !string.IsNullOrWhiteSpace(serviceEndpoint) ? serviceEndpoint : Constant.OperationApi.DefaultUrl;
34-
35-
// Set MI flag BEFORE creating the service client
35+
36+
// Client decides whether to use MI based on managedIdentityClientId parameter
3637
_useManagedIdentity = !string.IsNullOrWhiteSpace(managedIdentityClientId);
3738
_urpClient = new UnifiedRedisPlatformServiceClient(_serviceEndpoint, _clusterName, _appName, _appSecret, preferredLocation, _useManagedIdentity);
38-
39+
3940
if (_useManagedIdentity)
4041
{
4142
_tokenCredential = CreateTokenCredential(managedIdentityClientId);
@@ -112,7 +113,7 @@ public async Task<UnifiedConfigurationOptions> GetConfiguration(UnifiedConfigura
112113
if (clusterPreferredConfiguration.AreSecondaryConnectionsPresent)
113114
{
114115
currentConfiguration.SecondaryConfigurationsOptions = new List<ConfigurationOptions>(); // Secondary connections are added from settings
115-
foreach(var secondaryConnection in clusterPreferredConfiguration.SecondaryRedisConnectionStrings)
116+
foreach (var secondaryConnection in clusterPreferredConfiguration.SecondaryRedisConnectionStrings)
116117
{
117118
currentConfiguration.SecondaryConfigurationsOptions.Add(await CreateRedisConfigurationOptionAsync(secondaryConnection, applicationPreferredConfiguration, isSecondaryConnection: true));
118119
}
@@ -146,10 +147,16 @@ private async Task<ConfigurationOptions> CreateRedisConfigurationOptionAsync(str
146147

147148
options.AbortOnConnectFail = false;
148149
options.Ssl = true;
150+
options.KeepAlive = 60; // Send keep-alive every 60 seconds to prevent stale connections
149151

150-
// Use Managed Identity token for Redis authentication if configured
152+
// Use Managed Identity for Redis authentication if configured
153+
// ConfigureForAzureWithTokenCredentialAsync handles automatic token refresh
151154
// Otherwise, keep the password from the connection string (legacy behavior)
152-
if (_useManagedIdentity)
155+
if (_useManagedIdentity && _tokenCredential != null)
156+
{
157+
await options.ConfigureForAzureWithTokenCredentialAsync(_tokenCredential).ConfigureAwait(false);
158+
}
159+
else
153160
{
154161
var token = await GetRedisAccessTokenAsync();
155162
options.Password = token;
@@ -195,12 +202,12 @@ private async Task<ConfigurationOptions> CreateRedisConfigurationOptionsFromExis
195202
existingConfiguration.ResolveDns = serverConfiguration.ResolveDns;
196203
}
197204

198-
// Use Managed Identity token for Redis authentication if configured
205+
// Use Managed Identity for Redis authentication if configured
206+
// ConfigureForAzureWithTokenCredentialAsync handles automatic token refresh
199207
// Otherwise, keep the password from the connection string (legacy behavior)
200-
if (_useManagedIdentity)
208+
if (_useManagedIdentity && _tokenCredential != null)
201209
{
202-
var token = await GetRedisAccessTokenAsync();
203-
existingConfiguration.Password = token;
210+
await existingConfiguration.ConfigureForAzureWithTokenCredentialAsync(_tokenCredential).ConfigureAwait(false);
204211
}
205212
else
206213
{
@@ -224,8 +231,9 @@ private async Task<ConfigurationOptions> CreateRedisConfigurationOptionsFromExis
224231

225232
existingConfiguration.ConnectTimeout = applicationConfiguration.ConnectionPreference.ConnectionRetryProtocol.TimeoutInMs;
226233

234+
// Ensure keep-alive is set to prevent stale connections (default 60 seconds)
227235
existingConfiguration.KeepAlive =
228-
existingConfiguration.KeepAlive >= 1 ? existingConfiguration.KeepAlive : serverConfiguration.KeepAlive;
236+
existingConfiguration.KeepAlive >= 1 ? existingConfiguration.KeepAlive : (serverConfiguration.KeepAlive >= 1 ? serverConfiguration.KeepAlive : 60);
229237

230238
existingConfiguration.Proxy =
231239
existingConfiguration.Proxy != Proxy.None ? existingConfiguration.Proxy : serverConfiguration.Proxy;

src/sdk/Core/Services/HttpClientFactory.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Net.Http;
1+
using System;
2+
using System.Net.Http;
23
using Microsoft.UnifiedRedisPlatform.Core.Services.Interfaces;
34

45
namespace Microsoft.UnifiedRedisPlatform.Core.Services
@@ -24,7 +25,10 @@ public HttpClient GetUnifiedPlatformClient()
2425
if (_serviceClient == null)
2526
{
2627
var retryHandler = new RetryHttpHandler(new HttpClientHandler(), _maxRetry, _backoffInterval);
27-
_serviceClient = new HttpClient(retryHandler);
28+
_serviceClient = new HttpClient(retryHandler)
29+
{
30+
Timeout = TimeSpan.FromSeconds(30) // 30 second overall timeout for URP service calls
31+
};
2832
}
2933
}
3034
return _serviceClient;

src/sdk/Extensions/Microsoft.Extensions.Caching.UnifiedRedisPlatform/Microsoft.Extensions.Caching.UnifiedRedisPlatform.csproj

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
5-
<Version>1.0.2</Version>
5+
<Version>1.2.0</Version>
66
<Authors>Pratik Bhattacharya</Authors>
77
<Company>Microsoft</Company>
88
<Product>Unified Redis Platform</Product>
@@ -13,6 +13,15 @@
1313
<PackageId>DistributedCache.Extensions.UnifiedRedisPlatform</PackageId>
1414
<PackageTags>IDistributedCache redis azure caching distributed_cache azure-cache-for-redus azure-cache aspnetcore-cache urp unifedredisplatform unifiedredisframework managed-identity</PackageTags>
1515
<PackageReleaseNotes>
16+
v1.2.0:
17+
- Updated to Microsoft.UnifiedRedisPlatform.Core v1.6.0
18+
- Improved Managed Identity support and stability
19+
20+
v1.1.0:
21+
- Updated to Microsoft.UnifiedRedisPlatform.Core v1.5.0
22+
- Full Managed Identity (MI) support via ManagedIdentityClientId option
23+
- Backward compatible - existing configurations continue to work
24+
1625
v1.0.0-rc-2.0:
1726
- Added ManagedIdentityClientId option for Azure AD authentication
1827
- Added ServiceEndpoint option for custom URP service endpoints
@@ -24,7 +33,7 @@ v1.0.0-rc-2.0:
2433
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
2534
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.3" />
2635
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.3" />
27-
<PackageReference Include="Microsoft.UnifiedRedisPlatform.Core" Version="1.5.0" />
36+
<PackageReference Include="Microsoft.UnifiedRedisPlatform.Core" Version="1.6.0" />
2837
</ItemGroup>
2938

3039
</Project>

src/tests/Microsoft.UnifiedRedisPlatform.TestApps/TestConsole461.SDK/App.config

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,31 @@
77
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
88
<dependentAssembly>
99
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
10-
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
10+
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
11+
</dependentAssembly>
12+
<dependentAssembly>
13+
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
14+
<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
15+
</dependentAssembly>
16+
<dependentAssembly>
17+
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
18+
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
19+
</dependentAssembly>
20+
<dependentAssembly>
21+
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
22+
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
23+
</dependentAssembly>
24+
<dependentAssembly>
25+
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
26+
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
27+
</dependentAssembly>
28+
<dependentAssembly>
29+
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
30+
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
31+
</dependentAssembly>
32+
<dependentAssembly>
33+
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
34+
<bindingRedirect oldVersion="0.0.0.0-8.0.0.3" newVersion="8.0.0.3" />
1135
</dependentAssembly>
1236
</assemblyBinding>
1337
</runtime>

src/tests/Microsoft.UnifiedRedisPlatform.TestApps/TestConsole461.SDK/Microsoft.UnifiedRedisPlatform.TestConsole461.SDK.csproj

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,20 @@
3636
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
3737
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
3838
</Reference>
39-
<Reference Include="Microsoft.UnifiedRedisPlatform.Core, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
40-
<HintPath>..\packages\Microsoft.UnifiedRedisPlatform.Core.1.4.0\lib\netstandard2.0\Microsoft.UnifiedRedisPlatform.Core.dll</HintPath>
39+
<Reference Include="Microsoft.Bcl.Memory, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
40+
<HintPath>..\packages\Microsoft.Bcl.Memory.9.0.0\lib\net462\Microsoft.Bcl.Memory.dll</HintPath>
41+
</Reference>
42+
<Reference Include="Microsoft.Bcl.TimeProvider, Version=8.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
43+
<HintPath>..\packages\Microsoft.Bcl.TimeProvider.8.0.1\lib\net462\Microsoft.Bcl.TimeProvider.dll</HintPath>
44+
</Reference>
45+
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=8.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
46+
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
47+
</Reference>
48+
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=8.0.0.3, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
49+
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.8.0.3\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
50+
</Reference>
51+
<Reference Include="Microsoft.UnifiedRedisPlatform.Core, Version=1.0.4.0, Culture=neutral, processorArchitecture=MSIL">
52+
<HintPath>..\packages\Microsoft.UnifiedRedisPlatform.Core.1.6.0\lib\netstandard2.0\Microsoft.UnifiedRedisPlatform.Core.dll</HintPath>
4153
</Reference>
4254
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
4355
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
@@ -49,25 +61,54 @@
4961
<HintPath>..\packages\StackExchange.Redis.2.8.24\lib\net472\StackExchange.Redis.dll</HintPath>
5062
</Reference>
5163
<Reference Include="System" />
52-
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
53-
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
64+
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
65+
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
5466
</Reference>
5567
<Reference Include="System.Core" />
68+
<Reference Include="System.Diagnostics.DiagnosticSource, Version=8.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
69+
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.8.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
70+
</Reference>
71+
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
72+
<HintPath>..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
73+
<Private>True</Private>
74+
<Private>True</Private>
75+
</Reference>
76+
<Reference Include="System.IO.FileSystem.AccessControl, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
77+
<HintPath>..\packages\System.IO.FileSystem.AccessControl.5.0.0\lib\net461\System.IO.FileSystem.AccessControl.dll</HintPath>
78+
</Reference>
5679
<Reference Include="System.IO.Pipelines, Version=5.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
5780
<HintPath>..\packages\System.IO.Pipelines.5.0.1\lib\net461\System.IO.Pipelines.dll</HintPath>
5881
</Reference>
59-
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
60-
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
82+
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
83+
<HintPath>..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll</HintPath>
6184
</Reference>
6285
<Reference Include="System.Numerics" />
63-
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
64-
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
86+
<Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
87+
<HintPath>..\packages\System.Numerics.Vectors.4.6.1\lib\net462\System.Numerics.Vectors.dll</HintPath>
88+
</Reference>
89+
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
90+
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
91+
</Reference>
92+
<Reference Include="System.Security.AccessControl, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
93+
<HintPath>..\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll</HintPath>
94+
</Reference>
95+
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
96+
<HintPath>..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
97+
</Reference>
98+
<Reference Include="System.Text.Encodings.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
99+
<HintPath>..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
100+
</Reference>
101+
<Reference Include="System.Text.Json, Version=8.0.0.6, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
102+
<HintPath>..\packages\System.Text.Json.8.0.6\lib\net462\System.Text.Json.dll</HintPath>
103+
</Reference>
104+
<Reference Include="System.Threading.Channels, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
105+
<HintPath>..\packages\System.Threading.Channels.5.0.0\lib\net461\System.Threading.Channels.dll</HintPath>
65106
</Reference>
66-
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
67-
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
107+
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
108+
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.6.0\lib\net462\System.Threading.Tasks.Extensions.dll</HintPath>
68109
</Reference>
69-
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
70-
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
110+
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
111+
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
71112
</Reference>
72113
<Reference Include="System.Xml.Linq" />
73114
<Reference Include="System.Data.DataSetExtensions" />

0 commit comments

Comments
 (0)