Skip to content

Commit d00d4d4

Browse files
authored
Improve file globbing explanations in File Providers doc (#17600)
* Improve file globbing explanations in File Providers doc * Revert change to quotes text file * minor edit * more work * more work
1 parent 263fdd2 commit d00d4d4

6 files changed

Lines changed: 49 additions & 49 deletions

File tree

aspnetcore/fundamentals/file-providers.md

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Learn how ASP.NET Core abstracts file system access through the use
55
monikerRange: '>= aspnetcore-2.1'
66
ms.author: riande
77
ms.custom: mvc
8-
ms.date: 11/07/2019
8+
ms.date: 04/06/2020
99
uid: fundamentals/file-providers
1010
---
1111
# File Providers in ASP.NET Core
@@ -14,9 +14,9 @@ By [Steve Smith](https://ardalis.com/)
1414

1515
::: moniker range=">= aspnetcore-3.0"
1616

17-
ASP.NET Core abstracts file system access through the use of File Providers. File Providers are used throughout the ASP.NET Core framework:
17+
ASP.NET Core abstracts file system access through the use of File Providers. File Providers are used throughout the ASP.NET Core framework. For example:
1818

19-
* `IWebHostEnvironment` exposes the app's [content root](xref:fundamentals/index#content-root) and [web root](xref:fundamentals/index#web-root) as `IFileProvider` types.
19+
* <xref:Microsoft.AspNetCore.Hosting.IWebHostEnvironment> exposes the app's [content root](xref:fundamentals/index#content-root) and [web root](xref:fundamentals/index#web-root) as `IFileProvider` types.
2020
* [Static File Middleware](xref:fundamentals/static-files) uses File Providers to locate static files.
2121
* [Razor](xref:mvc/views/razor) uses File Providers to locate pages and views.
2222
* .NET Core tooling uses File Providers and glob patterns to specify which files should be published.
@@ -39,32 +39,33 @@ The primary interface is <xref:Microsoft.Extensions.FileProviders.IFileProvider>
3939
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.Length> (in bytes)
4040
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.LastModified> date
4141

42-
You can read from the file using the [IFileInfo.CreateReadStream](xref:Microsoft.Extensions.FileProviders.IFileInfo.CreateReadStream*) method.
42+
You can read from the file using the <xref:Microsoft.Extensions.FileProviders.IFileInfo.CreateReadStream*?displayProperty=nameWithType> method.
4343

44-
The sample app demonstrates how to configure a File Provider in `Startup.ConfigureServices` for use throughout the app via [dependency injection](xref:fundamentals/dependency-injection).
44+
The *FileProviderSample* sample app demonstrates how to configure a File Provider in `Startup.ConfigureServices` for use throughout the app via [dependency injection](xref:fundamentals/dependency-injection).
4545

4646
## File Provider implementations
4747

48-
Three implementations of `IFileProvider` are available.
48+
The following table lists implementations of `IFileProvider`.
4949

5050
| Implementation | Description |
5151
| -------------- | ----------- |
52-
| [PhysicalFileProvider](#physicalfileprovider) | The physical provider is used to access the system's physical files. |
53-
| [ManifestEmbeddedFileProvider](#manifestembeddedfileprovider) | The manifest embedded provider is used to access files embedded in assemblies. |
54-
| [CompositeFileProvider](#compositefileprovider) | The composite provider is used to provide combined access to files and directories from one or more other providers. |
52+
| [CompositeFileProvider](#compositefileprovider) | Used to provide combined access to files and directories from one or more other providers. |
53+
| [ManifestEmbeddedFileProvider](#manifestembeddedfileprovider) | Used to access files embedded in assemblies. |
54+
| [PhysicalFileProvider](#physicalfileprovider) | Used to access the system's physical files. |
5555

5656
### PhysicalFileProvider
5757

5858
The <xref:Microsoft.Extensions.FileProviders.PhysicalFileProvider> provides access to the physical file system. `PhysicalFileProvider` uses the <xref:System.IO.File?displayProperty=fullName> type (for the physical provider) and scopes all paths to a directory and its children. This scoping prevents access to the file system outside of the specified directory and its children. The most common scenario for creating and using a `PhysicalFileProvider` is to request an `IFileProvider` in a constructor through [dependency injection](xref:fundamentals/dependency-injection).
5959

60-
When instantiating this provider directly, a directory path is required and serves as the base path for all requests made using the provider.
60+
When instantiating this provider directly, an absolute directory path is required and serves as the base path for all requests made using the provider. Glob patterns aren't supported in the directory path.
6161

62-
The following code shows how to create a `PhysicalFileProvider` and use it to obtain directory contents and file information:
62+
The following code shows how to use `PhysicalFileProvider` to obtain directory contents and file information:
6363

6464
```csharp
6565
var provider = new PhysicalFileProvider(applicationRoot);
6666
var contents = provider.GetDirectoryContents(string.Empty);
67-
var fileInfo = provider.GetFileInfo("wwwroot/js/site.js");
67+
var filePath = Path.Combine("wwwroot", "js", "site.js");
68+
var fileInfo = provider.GetFileInfo(filePath);
6869
```
6970

7071
Types in the preceding example:
@@ -73,9 +74,9 @@ Types in the preceding example:
7374
* `contents` is an `IDirectoryContents`.
7475
* `fileInfo` is an `IFileInfo`.
7576

76-
The File Provider can be used to iterate through the directory specified by `applicationRoot` or call `GetFileInfo` to obtain a file's information. The File Provider has no access outside of the `applicationRoot` directory.
77+
The File Provider can be used to iterate through the directory specified by `applicationRoot` or call `GetFileInfo` to obtain a file's information. Glob patterns can't be passed to the `GetFileInfo` method. The File Provider has no access outside of the `applicationRoot` directory.
7778

78-
The sample app creates the provider in the app's `Startup.ConfigureServices` class using [IHostingEnvironment.ContentRootFileProvider](xref:Microsoft.Extensions.Hosting.IHostingEnvironment.ContentRootFileProvider):
79+
The *FileProviderSample* sample app creates the provider in the `Startup.ConfigureServices` method using <xref:Microsoft.Extensions.Hosting.IHostingEnvironment.ContentRootFileProvider?displayProperty=nameWithType>:
7980

8081
```csharp
8182
var physicalProvider = _env.ContentRootFileProvider;
@@ -85,15 +86,16 @@ var physicalProvider = _env.ContentRootFileProvider;
8586

8687
The <xref:Microsoft.Extensions.FileProviders.ManifestEmbeddedFileProvider> is used to access files embedded within assemblies. The `ManifestEmbeddedFileProvider` uses a manifest compiled into the assembly to reconstruct the original paths of the embedded files.
8788

88-
Add a package reference to the project for the [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) package.
89+
To generate a manifest of the embedded files:
8990

90-
To generate a manifest of the embedded files, set the `<GenerateEmbeddedFilesManifest>` property to `true`. Specify the files to embed with [\<EmbeddedResource>](/dotnet/core/tools/csproj#default-compilation-includes-in-net-core-projects):
91+
1. Add the [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) NuGet package to your project.
92+
1. Set the `<GenerateEmbeddedFilesManifest>` property to `true`. Specify the files to embed with [\<EmbeddedResource>](/dotnet/core/tools/csproj#default-compilation-includes-in-net-core-projects):
9193

92-
[!code-csharp[](file-providers/samples/3.x/FileProviderSample/FileProviderSample.csproj?highlight=5,13)]
94+
[!code-xml[](file-providers/samples/3.x/FileProviderSample/FileProviderSample.csproj?highlight=5,13)]
9395

9496
Use [glob patterns](#glob-patterns) to specify one or more files to embed into the assembly.
9597

96-
The sample app creates an `ManifestEmbeddedFileProvider` and passes the currently executing assembly to its constructor.
98+
The *FileProviderSample* sample app creates an `ManifestEmbeddedFileProvider` and passes the currently executing assembly to its constructor.
9799

98100
*Startup.cs*:
99101

@@ -118,24 +120,29 @@ Additional overloads allow you to:
118120

119121
The <xref:Microsoft.Extensions.FileProviders.CompositeFileProvider> combines `IFileProvider` instances, exposing a single interface for working with files from multiple providers. When creating the `CompositeFileProvider`, pass one or more `IFileProvider` instances to its constructor.
120122

121-
In the sample app, a `PhysicalFileProvider` and a `ManifestEmbeddedFileProvider` provide files to a `CompositeFileProvider` registered in the app's service container:
123+
In the *FileProviderSample* sample app, a `PhysicalFileProvider` and a `ManifestEmbeddedFileProvider` provide files to a `CompositeFileProvider` registered in the app's service container. The following code is found in the project's `Startup.ConfigureServices` method:
122124

123125
[!code-csharp[](file-providers/samples/3.x/FileProviderSample/Startup.cs?name=snippet1)]
124126

125127
## Watch for changes
126128

127-
The [IFileProvider.Watch](xref:Microsoft.Extensions.FileProviders.IFileProvider.Watch*) method provides a scenario to watch one or more files or directories for changes. `Watch` accepts a path string, which can use [glob patterns](#glob-patterns) to specify multiple files. `Watch` returns an <xref:Microsoft.Extensions.Primitives.IChangeToken>. The change token exposes:
129+
The <xref:Microsoft.Extensions.FileProviders.IFileProvider.Watch*?displayProperty=nameWithType> method provides a scenario to watch one or more files or directories for changes. The `Watch` method:
128130

129-
* <xref:Microsoft.Extensions.Primitives.IChangeToken.HasChanged> &ndash; A property that can be inspected to determine if a change has occurred.
130-
* <xref:Microsoft.Extensions.Primitives.IChangeToken.RegisterChangeCallback*> &ndash; Called when changes are detected to the specified path string. Each change token only calls its associated callback in response to a single change. To enable constant monitoring, use a <xref:System.Threading.Tasks.TaskCompletionSource`1> (shown below) or recreate `IChangeToken` instances in response to changes.
131+
* Accepts a file path string, which can use [glob patterns](#glob-patterns) to specify multiple files.
132+
* Returns an <xref:Microsoft.Extensions.Primitives.IChangeToken>.
131133

132-
In the sample app, the *WatchConsole* console app is configured to display a message whenever a text file is modified:
134+
The resulting change token exposes:
135+
136+
* <xref:Microsoft.Extensions.Primitives.IChangeToken.HasChanged>&ndash;A property that can be inspected to determine if a change has occurred.
137+
* <xref:Microsoft.Extensions.Primitives.IChangeToken.RegisterChangeCallback*>&ndash;Called when changes are detected to the specified path string. Each change token only calls its associated callback in response to a single change. To enable constant monitoring, use a <xref:System.Threading.Tasks.TaskCompletionSource`1> (shown below) or recreate `IChangeToken` instances in response to changes.
133138

134-
[!code-csharp[](file-providers/samples/3.x/WatchConsole/Program.cs?name=snippet1&highlight=1-2,16,19-20)]
139+
The *WatchConsole* sample app writes a message whenever a *.txt* file in the *TextFiles* directory is modified:
140+
141+
[!code-csharp[](file-providers/samples/3.x/WatchConsole/Program.cs?name=snippet1)]
135142

136143
Some file systems, such as Docker containers and network shares, may not reliably send change notifications. Set the `DOTNET_USE_POLLING_FILE_WATCHER` environment variable to `1` or `true` to poll the file system for changes every four seconds (not configurable).
137144

138-
## Glob patterns
145+
### Glob patterns
139146

140147
File system paths use wildcard patterns called *glob (or globbing) patterns*. Specify groups of files with these patterns. The two wildcard characters are `*` and `**`:
141148

@@ -145,19 +152,14 @@ Matches anything at the current folder level, any filename, or any file extensio
145152
**`**`**
146153
Matches anything across multiple directory levels. Can be used to recursively match many files within a directory hierarchy.
147154

148-
**Glob pattern examples**
149-
150-
**`directory/file.txt`**
151-
Matches a specific file in a specific directory.
152-
153-
**`directory/*.txt`**
154-
Matches all files with *.txt* extension in a specific directory.
155-
156-
**`directory/*/appsettings.json`**
157-
Matches all `appsettings.json` files in directories exactly one level below the *directory* folder.
155+
The following table provides common examples of glob patterns.
158156

159-
**`directory/**/*.txt`**
160-
Matches all files with *.txt* extension found anywhere under the *directory* folder.
157+
|Pattern |Description |
158+
|---------|---------|
159+
|`directory/file.txt`|Matches a specific file in a specific directory.|
160+
|`directory/*.txt`|Matches all files with *.txt* extension in a specific directory.|
161+
|`directory/*/appsettings.json`|Matches all *appsettings.json* files in directories exactly one level below the *directory* folder.|
162+
|`directory/**/*.txt`|Matches all files with a *.txt* extension found anywhere under the *directory* folder.|
161163

162164
::: moniker-end
163165

aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ public IndexModel(IFileProvider fileProvider)
1414

1515
public IDirectoryContents DirectoryContents { get; private set; }
1616

17-
public void OnGet()
18-
{
17+
public void OnGet() =>
1918
DirectoryContents = _fileProvider.GetDirectoryContents(string.Empty);
20-
}
2119
}
2220
}

aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Startup.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Reflection;
21
using Microsoft.AspNetCore.Builder;
32
using Microsoft.AspNetCore.Hosting;
43
using Microsoft.Extensions.DependencyInjection;
@@ -31,9 +30,9 @@ public void ConfigureServices(IServiceCollection services)
3130
#endregion
3231
}
3332

34-
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
33+
public void Configure(IApplicationBuilder app)
3534
{
36-
if (env.IsDevelopment())
35+
if (_env.IsDevelopment())
3736
{
3837
app.UseDeveloperExceptionPage();
3938
}

aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/Program.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ namespace WatchConsole
99
public class Program
1010
{
1111
#region snippet1
12-
private static PhysicalFileProvider _fileProvider =
13-
new PhysicalFileProvider(Directory.GetCurrentDirectory());
12+
private static readonly string _fileFilter = Path.Combine("TextFiles", "*.txt");
1413

1514
public static void Main(string[] args)
1615
{
17-
Console.WriteLine("Monitoring quotes.txt for changes (Ctrl-c to quit)...");
16+
Console.WriteLine($"Monitoring for changes with filter '{_fileFilter}' (Ctrl + C to quit)...");
1817

1918
while (true)
2019
{
@@ -24,15 +23,16 @@ public static void Main(string[] args)
2423

2524
private static async Task MainAsync()
2625
{
27-
IChangeToken token = _fileProvider.Watch("quotes.txt");
26+
var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
27+
IChangeToken token = fileProvider.Watch(_fileFilter);
2828
var tcs = new TaskCompletionSource<object>();
2929

30-
token.RegisterChangeCallback(state =>
30+
token.RegisterChangeCallback(state =>
3131
((TaskCompletionSource<object>)state).TrySetResult(null), tcs);
3232

3333
await tcs.Task.ConfigureAwait(false);
3434

35-
Console.WriteLine("quotes.txt changed");
35+
Console.WriteLine("file changed");
3636
}
3737
#endregion
3838
}

aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/quotes.txt renamed to aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/TextFiles/quotes.txt

File renamed without changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a test!!!!!!

0 commit comments

Comments
 (0)