Skip to content

Commit 83d4dcd

Browse files
ConfigurationBuilder.AddJsonFile can't fire OnChange event using relative paths (#111101)
Fixes #71386 --------- Co-authored-by: Jeff Handley <[email protected]>
1 parent 541b7ab commit 83d4dcd

File tree

4 files changed

+44
-4
lines changed

4 files changed

+44
-4
lines changed

src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,5 +1017,31 @@ private sealed class MyOptions
10171017

10181018
public string XmlKey1 { get; set; }
10191019
}
1020+
1021+
private async Task WatchOverConfigJsonFileAndUpdateIt(string filePath)
1022+
{
1023+
var builder = new ConfigurationBuilder().AddJsonFile(filePath, true, true).Build();
1024+
bool reloaded = false;
1025+
ChangeToken.OnChange(builder.GetReloadToken, () =>
1026+
{
1027+
reloaded = true;
1028+
});
1029+
File.WriteAllText(filePath, "{\"Prop2\":\"Value2\"}");
1030+
await WaitForChange(
1031+
() => reloaded,
1032+
"on file change event handler did not get executed");
1033+
}
1034+
1035+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows))]
1036+
public async Task OnChangeGetFiredForRelativeWindowsPath()
1037+
{
1038+
await WatchOverConfigJsonFileAndUpdateIt(".\\testFileToReload.json");
1039+
}
1040+
1041+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsLinux))]
1042+
public async Task OnChangeGetFiredForRelativeLinuxPath()
1043+
{
1044+
await WatchOverConfigJsonFileAndUpdateIt("./testFileToReload.json");
1045+
}
10201046
}
10211047
}

src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkCurrent)</TargetFrameworks>
55
<EnableDefaultItems>true</EnableDefaultItems>
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<Compile Include="$(LibrariesProjectRoot)Microsoft.Extensions.Configuration\tests\Common\ConfigurationProviderExtensions.cs"
10-
Link="Common\ConfigurationProviderExtensions.cs" />
9+
<Compile Include="$(LibrariesProjectRoot)Microsoft.Extensions.Configuration\tests\Common\ConfigurationProviderExtensions.cs" Link="Common\ConfigurationProviderExtensions.cs" />
10+
</ItemGroup>
11+
12+
<ItemGroup>
13+
<Content Include="testFileToReload.json">
14+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
15+
</Content>
1116
</ItemGroup>
1217

1318
<ItemGroup>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"Prop1": "Value1"
3+
}

src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,18 @@ private IChangeToken GetOrAddChangeToken(string pattern)
165165
}
166166
else
167167
{
168-
changeToken = GetOrAddFilePathChangeToken(pattern);
168+
// get rid of \. in Windows and ./ in UNIX's at the start of path file
169+
var filePath = RemoveRelativePathSegment(pattern);
170+
changeToken = GetOrAddFilePathChangeToken(filePath);
169171
}
170172

171173
return changeToken;
172174
}
173175

176+
private static string RemoveRelativePathSegment(string pattern) =>
177+
// The pattern has already been normalized to unix directory separators
178+
pattern.StartsWith("./", StringComparison.Ordinal) ? pattern.Substring(2) : pattern;
179+
174180
internal IChangeToken GetOrAddFilePathChangeToken(string filePath)
175181
{
176182
if (!_filePathTokenLookup.TryGetValue(filePath, out ChangeTokenInfo tokenInfo))

0 commit comments

Comments
 (0)