From 2d27dd6f7639e68dbc59eba99b5ee871c521f7e0 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Mon, 26 Aug 2019 15:16:50 -0500 Subject: [PATCH] File Providers topic update for 3.0 (#14027) --- aspnetcore/fundamentals/file-providers.md | 199 +++++++++++++++--- .../2.x/FileProviderSample/Pages/Index.cshtml | 2 +- .../Pages/Shared/_CookieConsentPartial.cshtml | 41 ---- .../Pages/Shared/_Layout.cshtml | 4 - .../Shared/_ValidationScriptsPartial.cshtml | 18 -- .../samples/2.x/WatchConsole/quotes.txt | 2 +- .../FileProviderSample.csproj | 16 ++ .../3.x/FileProviderSample/Pages/Error.cshtml | 26 +++ .../FileProviderSample/Pages/Error.cshtml.cs | 19 ++ .../3.x/FileProviderSample/Pages/Index.cshtml | 30 +++ .../FileProviderSample/Pages/Index.cshtml.cs | 22 ++ .../Pages/Shared/_Layout.cshtml | 14 ++ .../Pages/_ViewImports.cshtml | 3 + .../Pages/_ViewStart.cshtml | 3 + .../samples/3.x/FileProviderSample/Program.cs | 20 ++ .../samples/3.x/FileProviderSample/README.md | 3 + .../3.x/FileProviderSample/Resource.txt | 1 + .../samples/3.x/FileProviderSample/Startup.cs | 54 +++++ .../appsettings.Development.json | 9 + .../appsettings.Production.json | 9 + .../3.x/FileProviderSample/appsettings.json | 10 + .../samples/3.x/WatchConsole/Program.cs | 39 ++++ .../3.x/WatchConsole/WatchConsole.csproj | 7 + .../samples/3.x/WatchConsole/quotes.txt | 3 + 24 files changed, 458 insertions(+), 96 deletions(-) delete mode 100644 aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_CookieConsentPartial.cshtml delete mode 100644 aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_ValidationScriptsPartial.cshtml create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/FileProviderSample.csproj create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Error.cshtml create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Error.cshtml.cs create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml.cs create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Shared/_Layout.cshtml create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/_ViewImports.cshtml create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/_ViewStart.cshtml create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Program.cs create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/README.md create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Resource.txt create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Startup.cs create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.Development.json create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.Production.json create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.json create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/Program.cs create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/WatchConsole.csproj create mode 100644 aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/quotes.txt diff --git a/aspnetcore/fundamentals/file-providers.md b/aspnetcore/fundamentals/file-providers.md index e8509a4c0a..c9517d4e72 100644 --- a/aspnetcore/fundamentals/file-providers.md +++ b/aspnetcore/fundamentals/file-providers.md @@ -5,16 +5,18 @@ description: Learn how ASP.NET Core abstracts file system access through the use monikerRange: '>= aspnetcore-2.1' ms.author: riande ms.custom: mvc -ms.date: 03/30/2019 +ms.date: 08/26/2019 uid: fundamentals/file-providers --- # File Providers in ASP.NET Core By [Steve Smith](https://ardalis.com/) and [Luke Latham](https://github.com/guardrex) +::: moniker range=">= aspnetcore-3.0" + ASP.NET Core abstracts file system access through the use of File Providers. File Providers are used throughout the ASP.NET Core framework: -* [IHostingEnvironment](/dotnet/api/microsoft.extensions.hosting.ihostingenvironment) exposes the app's content root and web root as `IFileProvider` types. +* `IWebHostEnvironment` exposes the app's content root and web root as `IFileProvider` types. * [Static File Middleware](xref:fundamentals/static-files) uses File Providers to locate static files. * [Razor](xref:mvc/views/razor) uses File Providers to locate pages and views. * .NET Core tooling uses File Providers and glob patterns to specify which files should be published. @@ -23,21 +25,21 @@ ASP.NET Core abstracts file system access through the use of File Providers. Fil ## File Provider interfaces -The primary interface is [IFileProvider](/dotnet/api/microsoft.extensions.fileproviders.ifileprovider). `IFileProvider` exposes methods to: +The primary interface is . `IFileProvider` exposes methods to: -* Obtain file information ([IFileInfo](/dotnet/api/microsoft.extensions.fileproviders.ifileinfo)). -* Obtain directory information ([IDirectoryContents](/dotnet/api/microsoft.extensions.fileproviders.idirectorycontents)). -* Set up change notifications (using an [IChangeToken](/dotnet/api/microsoft.extensions.primitives.ichangetoken)). +* Obtain file information (). +* Obtain directory information (). +* Set up change notifications (using an ). `IFileInfo` provides methods and properties for working with files: -* [Exists](/dotnet/api/microsoft.extensions.fileproviders.ifileinfo.exists) -* [IsDirectory](/dotnet/api/microsoft.extensions.fileproviders.ifileinfo.isdirectory) -* [Name](/dotnet/api/microsoft.extensions.fileproviders.ifileinfo.name) -* [Length](/dotnet/api/microsoft.extensions.fileproviders.ifileinfo.length) (in bytes) -* [LastModified](/dotnet/api/microsoft.extensions.fileproviders.ifileinfo.lastmodified) date +* +* +* +* (in bytes) +* date -You can read from the file using the [IFileInfo.CreateReadStream](/dotnet/api/microsoft.extensions.fileproviders.ifileinfo.createreadstream) method. +You can read from the file using the [IFileInfo.CreateReadStream](xref:Microsoft.Extensions.FileProviders.IFileInfo.CreateReadStream*) method. 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). @@ -53,9 +55,9 @@ Three implementations of `IFileProvider` are available. ### PhysicalFileProvider -The [PhysicalFileProvider](/dotnet/api/microsoft.extensions.fileproviders.physicalfileprovider) provides access to the physical file system. `PhysicalFileProvider` uses the [System.IO.File](/dotnet/api/system.io.file) 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. When instantiating this provider, a directory path is required and serves as the base path for all requests made using the provider. You can instantiate a `PhysicalFileProvider` provider directly, or you can request an `IFileProvider` in a constructor through [dependency injection](xref:fundamentals/dependency-injection). +The provides access to the physical file system. `PhysicalFileProvider` uses the 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). -**Static types** +When instantiating this provider directly, a directory path is required and serves as the base path for all requests made using the provider. The following code shows how to create a `PhysicalFileProvider` and use it to obtain directory contents and file information: @@ -73,31 +75,164 @@ Types in the preceding example: 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. -The sample app creates the provider in the app's `Startup.ConfigureServices` class using [IHostingEnvironment.ContentRootFileProvider](/dotnet/api/microsoft.extensions.hosting.ihostingenvironment.contentrootfileprovider): +The sample app creates the provider in the app's `Startup.ConfigureServices` class using [IHostingEnvironment.ContentRootFileProvider](xref:Microsoft.Extensions.Hosting.IHostingEnvironment.ContentRootFileProvider): ```csharp var physicalProvider = _env.ContentRootFileProvider; ``` -**Obtain File Provider types with dependency injection** +### ManifestEmbeddedFileProvider -Inject the provider into any class constructor and assign it to a local field. Use the field throughout the class's methods to access files. +The 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. -In the sample app, the `IndexModel` class receives an `IFileProvider` instance to obtain directory contents for the app's base path. +Add a package reference to the project for the [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) package. -*Pages/Index.cshtml.cs*: +To generate a manifest of the embedded files, set the `` property to `true`. Specify the files to embed with [\](/dotnet/core/tools/csproj#default-compilation-includes-in-net-core-projects): -[!code-csharp[](file-providers/samples/2.x/FileProviderSample/Pages/Index.cshtml.cs?name=snippet1)] +[!code-csharp[](file-providers/samples/3.x/FileProviderSample/FileProviderSample.csproj?highlight=6,14)] -The `IDirectoryContents` are iterated in the page. +Use [glob patterns](#glob-patterns) to specify one or more files to embed into the assembly. -*Pages/Index.cshtml*: +The sample app creates an `ManifestEmbeddedFileProvider` and passes the currently executing assembly to its constructor. -[!code-cshtml[](file-providers/samples/2.x/FileProviderSample/Pages/Index.cshtml?name=snippet1)] +*Startup.cs*: + +```csharp +var manifestEmbeddedProvider = + new ManifestEmbeddedFileProvider(Assembly.GetEntryAssembly()); +``` + +Additional overloads allow you to: + +* Specify a relative file path. +* Scope files to a last modified date. +* Name the embedded resource containing the embedded file manifest. + +| Overload | Description | +| -------- | ----------- | +| `ManifestEmbeddedFileProvider(Assembly, String)` | Accepts an optional `root` relative path parameter. Specify the `root` to scope calls to to those resources under the provided path. | +| `ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset)` | Accepts an optional `root` relative path parameter and a `lastModified` date () parameter. The `lastModified` date scopes the last modification date for the instances returned by the . | +| `ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset)` | Accepts an optional `root` relative path, `lastModified` date, and `manifestName` parameters. The `manifestName` represents the name of the embedded resource containing the manifest. | + +### CompositeFileProvider + +The 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. + +In the sample app, a `PhysicalFileProvider` and a `ManifestEmbeddedFileProvider` provide files to a `CompositeFileProvider` registered in the app's service container: + +[!code-csharp[](file-providers/samples/3.x/FileProviderSample/Startup.cs?name=snippet1)] + +## Watch for changes + +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 . The change token exposes: + +* – A property that can be inspected to determine if a change has occurred. +* – 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 (shown below) or recreate `IChangeToken` instances in response to changes. + +In the sample app, the *WatchConsole* console app is configured to display a message whenever a text file is modified: + +[!code-csharp[](file-providers/samples/3.x/WatchConsole/Program.cs?name=snippet1&highlight=1-2,16,19-20)] + +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). + +## Glob patterns + +File system paths use wildcard patterns called *glob (or globbing) patterns*. Specify groups of files with these patterns. The two wildcard characters are `*` and `**`: + +**`*`** +Matches anything at the current folder level, any filename, or any file extension. Matches are terminated by `/` and `.` characters in the file path. + +**`**`** +Matches anything across multiple directory levels. Can be used to recursively match many files within a directory hierarchy. + +**Glob pattern examples** + +**`directory/file.txt`** +Matches a specific file in a specific directory. + +**`directory/*.txt`** +Matches all files with *.txt* extension in a specific directory. + +**`directory/*/appsettings.json`** +Matches all `appsettings.json` files in directories exactly one level below the *directory* folder. + +**`directory/**/*.txt`** +Matches all files with *.txt* extension found anywhere under the *directory* folder. + +::: moniker-end + +::: moniker range="< aspnetcore-3.0" + +ASP.NET Core abstracts file system access through the use of File Providers. File Providers are used throughout the ASP.NET Core framework: + +* exposes the app's content root and web root as `IFileProvider` types. +* [Static File Middleware](xref:fundamentals/static-files) uses File Providers to locate static files. +* [Razor](xref:mvc/views/razor) uses File Providers to locate pages and views. +* .NET Core tooling uses File Providers and glob patterns to specify which files should be published. + +[View or download sample code](https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/file-providers/samples) ([how to download](xref:index#how-to-download-a-sample)) + +## File Provider interfaces + +The primary interface is . `IFileProvider` exposes methods to: + +* Obtain file information (). +* Obtain directory information (). +* Set up change notifications (using an ). + +`IFileInfo` provides methods and properties for working with files: + +* +* +* +* (in bytes) +* date + +You can read from the file using the [IFileInfo.CreateReadStream](xref:Microsoft.Extensions.FileProviders.IFileInfo.CreateReadStream*) method. + +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). + +## File Provider implementations + +Three implementations of `IFileProvider` are available. + +| Implementation | Description | +| -------------- | ----------- | +| [PhysicalFileProvider](#physicalfileprovider) | The physical provider is used to access the system's physical files. | +| [ManifestEmbeddedFileProvider](#manifestembeddedfileprovider) | The manifest embedded provider is used to access files embedded in assemblies. | +| [CompositeFileProvider](#compositefileprovider) | The composite provider is used to provide combined access to files and directories from one or more other providers. | + +### PhysicalFileProvider + +The provides access to the physical file system. `PhysicalFileProvider` uses the 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). + +When instantiating this provider directly, a directory path is required and serves as the base path for all requests made using the provider. + +The following code shows how to create a `PhysicalFileProvider` and use it to obtain directory contents and file information: + +```csharp +var provider = new PhysicalFileProvider(applicationRoot); +var contents = provider.GetDirectoryContents(string.Empty); +var fileInfo = provider.GetFileInfo("wwwroot/js/site.js"); +``` + +Types in the preceding example: + +* `provider` is an `IFileProvider`. +* `contents` is an `IDirectoryContents`. +* `fileInfo` is an `IFileInfo`. + +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. + +The sample app creates the provider in the app's `Startup.ConfigureServices` class using [IHostingEnvironment.ContentRootFileProvider](xref:Microsoft.Extensions.Hosting.IHostingEnvironment.ContentRootFileProvider): + +```csharp +var physicalProvider = _env.ContentRootFileProvider; +``` ### ManifestEmbeddedFileProvider -The [ManifestEmbeddedFileProvider](/dotnet/api/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. +The 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. To generate a manifest of the embedded files, set the `` property to `true`. Specify the files to embed with [<EmbeddedResource>](/dotnet/core/tools/csproj#default-compilation-includes-in-net-core-projects): @@ -122,13 +257,13 @@ Additional overloads allow you to: | Overload | Description | | -------- | ----------- | -| [ManifestEmbeddedFileProvider(Assembly, String)](/dotnet/api/microsoft.extensions.fileproviders.manifestembeddedfileprovider.-ctor#Microsoft_Extensions_FileProviders_ManifestEmbeddedFileProvider__ctor_System_Reflection_Assembly_System_String_) | Accepts an optional `root` relative path parameter. Specify the `root` to scope calls to [GetDirectoryContents](/dotnet/api/microsoft.extensions.fileproviders.ifileprovider.getdirectorycontents) to those resources under the provided path. | -| [ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset)](/dotnet/api/microsoft.extensions.fileproviders.manifestembeddedfileprovider.-ctor#Microsoft_Extensions_FileProviders_ManifestEmbeddedFileProvider__ctor_System_Reflection_Assembly_System_String_System_DateTimeOffset_) | Accepts an optional `root` relative path parameter and a `lastModified` date ([DateTimeOffset](/dotnet/api/system.datetimeoffset)) parameter. The `lastModified` date scopes the last modification date for the [IFileInfo](/dotnet/api/microsoft.extensions.fileproviders.ifileinfo) instances returned by the [IFileProvider](/dotnet/api/microsoft.extensions.fileproviders.ifileprovider). | -| [ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset)](/dotnet/api/microsoft.extensions.fileproviders.manifestembeddedfileprovider.-ctor#Microsoft_Extensions_FileProviders_ManifestEmbeddedFileProvider__ctor_System_Reflection_Assembly_System_String_System_String_System_DateTimeOffset_) | Accepts an optional `root` relative path, `lastModified` date, and `manifestName` parameters. The `manifestName` represents the name of the embedded resource containing the manifest. | +| `ManifestEmbeddedFileProvider(Assembly, String)` | Accepts an optional `root` relative path parameter. Specify the `root` to scope calls to to those resources under the provided path. | +| `ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset)` | Accepts an optional `root` relative path parameter and a `lastModified` date () parameter. The `lastModified` date scopes the last modification date for the instances returned by the . | +| `ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset)` | Accepts an optional `root` relative path, `lastModified` date, and `manifestName` parameters. The `manifestName` represents the name of the embedded resource containing the manifest. | ### CompositeFileProvider -The [CompositeFileProvider](/dotnet/api/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. +The 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. In the sample app, a `PhysicalFileProvider` and a `ManifestEmbeddedFileProvider` provide files to a `CompositeFileProvider` registered in the app's service container: @@ -136,10 +271,10 @@ In the sample app, a `PhysicalFileProvider` and a `ManifestEmbeddedFileProvider` ## Watch for changes -The [IFileProvider.Watch](/dotnet/api/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 [IChangeToken](/dotnet/api/microsoft.extensions.primitives.ichangetoken). The change token exposes: +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 . The change token exposes: -* [HasChanged](/dotnet/api/microsoft.extensions.primitives.ichangetoken.haschanged): A property that can be inspected to determine if a change has occurred. -* [RegisterChangeCallback](/dotnet/api/microsoft.extensions.primitives.ichangetoken.registerchangecallback): 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 [TaskCompletionSource](/dotnet/api/system.threading.tasks.taskcompletionsource-1) (shown below) or recreate `IChangeToken` instances in response to changes. +* – A property that can be inspected to determine if a change has occurred. +* – 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 (shown below) or recreate `IChangeToken` instances in response to changes. In the sample app, the *WatchConsole* console app is configured to display a message whenever a text file is modified: @@ -170,3 +305,5 @@ Matches all `appsettings.json` files in directories exactly one level below the **`directory/**/*.txt`** Matches all files with *.txt* extension found anywhere under the *directory* folder. + +::: moniker-end diff --git a/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Index.cshtml b/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Index.cshtml index 46d31aefb2..a99e7607fb 100644 --- a/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Index.cshtml +++ b/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Index.cshtml @@ -18,7 +18,7 @@ { if (item.IsDirectory) { -
  • @item.Name
  • +
  • @item.Name folder
  • } else { diff --git a/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_CookieConsentPartial.cshtml b/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_CookieConsentPartial.cshtml deleted file mode 100644 index 315cfe0ee4..0000000000 --- a/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_CookieConsentPartial.cshtml +++ /dev/null @@ -1,41 +0,0 @@ -@using Microsoft.AspNetCore.Http.Features - -@{ - var consentFeature = Context.Features.Get(); - var showBanner = !consentFeature?.CanTrack ?? false; - var cookieString = consentFeature?.CreateConsentCookie(); -} - -@if (showBanner) -{ - - -} diff --git a/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_Layout.cshtml b/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_Layout.cshtml index 691974d896..fe71a99bb7 100644 --- a/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_Layout.cshtml +++ b/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_Layout.cshtml @@ -9,10 +9,6 @@
    @RenderBody() -
    -
    -

    ©@System.DateTime.Now.Year - File Provider Sample

    -
    diff --git a/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_ValidationScriptsPartial.cshtml b/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_ValidationScriptsPartial.cshtml deleted file mode 100644 index ef848fe8fc..0000000000 --- a/aspnetcore/fundamentals/file-providers/samples/2.x/FileProviderSample/Pages/Shared/_ValidationScriptsPartial.cshtml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - diff --git a/aspnetcore/fundamentals/file-providers/samples/2.x/WatchConsole/quotes.txt b/aspnetcore/fundamentals/file-providers/samples/2.x/WatchConsole/quotes.txt index 4518a3a724..047f17a588 100644 --- a/aspnetcore/fundamentals/file-providers/samples/2.x/WatchConsole/quotes.txt +++ b/aspnetcore/fundamentals/file-providers/samples/2.x/WatchConsole/quotes.txt @@ -1,3 +1,3 @@ "As developers, we fail in two ways: We build the thing wrong, or we build the wrong thing." - Steve Smith -"That's not a thing ... You just made that up." - David Fowler \ No newline at end of file +"That's not a thing ... You just made that up." - David Fowler diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/FileProviderSample.csproj b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/FileProviderSample.csproj new file mode 100644 index 0000000000..e0845b3baf --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/FileProviderSample.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp3.0 + true + + + + + + + + + + + diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Error.cshtml b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Error.cshtml new file mode 100644 index 0000000000..6f92b95655 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Error.cshtml @@ -0,0 +1,26 @@ +@page +@model ErrorModel +@{ + ViewData["Title"] = "Error"; +} + +

    Error.

    +

    An error occurred while processing your request.

    + +@if (Model.ShowRequestId) +{ +

    + Request ID: @Model.RequestId +

    +} + +

    Development Mode

    +

    + Swapping to the Development environment displays detailed information about the error that occurred. +

    +

    + The Development environment shouldn't be enabled for deployed applications. + It can result in displaying sensitive information from exceptions to end users. + For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development + and restarting the app. +

    diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Error.cshtml.cs b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Error.cshtml.cs new file mode 100644 index 0000000000..69540eb602 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Error.cshtml.cs @@ -0,0 +1,19 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace FileProviderSample.Pages +{ + [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] + public class ErrorModel : PageModel + { + public string RequestId { get; set; } + + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; + } + } +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml new file mode 100644 index 0000000000..5bf94204c2 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml @@ -0,0 +1,30 @@ +@page +@model IndexModel +@{ + ViewData["Title"] = "File Provider Sample"; +} + +

    @ViewData["Title"]

    + +
    +
    +
    +

    Folder Contents

    +
    +
    +
      + @foreach (var item in Model.DirectoryContents) + { + if (item.IsDirectory) + { +
    • @item.Name folder
    • + } + else + { +
    • @item.Name - @item.Length bytes
    • + } + } +
    +
    +
    +
    diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml.cs b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml.cs new file mode 100644 index 0000000000..1dc7cb002d --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Index.cshtml.cs @@ -0,0 +1,22 @@ +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.FileProviders; + +namespace FileProviderSample.Pages +{ + public class IndexModel : PageModel + { + private readonly IFileProvider _fileProvider; + + public IndexModel(IFileProvider fileProvider) + { + _fileProvider = fileProvider; + } + + public IDirectoryContents DirectoryContents { get; private set; } + + public void OnGet() + { + DirectoryContents = _fileProvider.GetDirectoryContents(string.Empty); + } + } +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Shared/_Layout.cshtml b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Shared/_Layout.cshtml new file mode 100644 index 0000000000..fe71a99bb7 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/Shared/_Layout.cshtml @@ -0,0 +1,14 @@ + + + + + + @ViewData["Title"] + + + +
    + @RenderBody() +
    + + diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/_ViewImports.cshtml b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/_ViewImports.cshtml new file mode 100644 index 0000000000..5bd9eaca40 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using FileProviderSample +@namespace FileProviderSample.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/_ViewStart.cshtml b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/_ViewStart.cshtml new file mode 100644 index 0000000000..a5f10045db --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Pages/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Program.cs b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Program.cs new file mode 100644 index 0000000000..ca17ddf5b9 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Program.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace FileProviderSample +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/README.md b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/README.md new file mode 100644 index 0000000000..5e27b43b01 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/README.md @@ -0,0 +1,3 @@ +# ASP.NET Core File Provider Sample + +This sample illustrates the use of File Provider. This sample demonstrates the scenario described in the [File Providers in ASP.NET Core](https://docs.microsoft.com/aspnet/core/fundamentals/file-providers) topic. diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Resource.txt b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Resource.txt new file mode 100644 index 0000000000..ae5c876d9c --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Resource.txt @@ -0,0 +1 @@ +An embedded resource. diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Startup.cs b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Startup.cs new file mode 100644 index 0000000000..da32125041 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/Startup.cs @@ -0,0 +1,54 @@ +using System.Reflection; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Hosting; + +namespace FileProviderSample +{ + public class Startup + { + private readonly IWebHostEnvironment _env; + + public Startup(IWebHostEnvironment env) + { + _env = env; + } + + public void ConfigureServices(IServiceCollection services) + { + services.AddRazorPages(); + + #region snippet1 + var physicalProvider = _env.ContentRootFileProvider; + var manifestEmbeddedProvider = + new ManifestEmbeddedFileProvider(Assembly.GetEntryAssembly()); + var compositeProvider = + new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider); + + services.AddSingleton(compositeProvider); + #endregion + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/Error"); + } + + app.UseStaticFiles(); + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); + }); + } + } +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.Development.json b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.Development.json new file mode 100644 index 0000000000..0623a3f445 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.Production.json b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.Production.json new file mode 100644 index 0000000000..8af1e1fedd --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.Production.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Error", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.json b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.json new file mode 100644 index 0000000000..93b64d37ab --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/FileProviderSample/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/Program.cs b/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/Program.cs new file mode 100644 index 0000000000..06d03220a5 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/Program.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Primitives; + +namespace WatchConsole +{ + public class Program + { + #region snippet1 + private static PhysicalFileProvider _fileProvider = + new PhysicalFileProvider(Directory.GetCurrentDirectory()); + + public static void Main(string[] args) + { + Console.WriteLine("Monitoring quotes.txt for changes (Ctrl-c to quit)..."); + + while (true) + { + MainAsync().GetAwaiter().GetResult(); + } + } + + private static async Task MainAsync() + { + IChangeToken token = _fileProvider.Watch("quotes.txt"); + var tcs = new TaskCompletionSource(); + + token.RegisterChangeCallback(state => + ((TaskCompletionSource)state).TrySetResult(null), tcs); + + await tcs.Task.ConfigureAwait(false); + + Console.WriteLine("quotes.txt changed"); + } + #endregion + } +} diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/WatchConsole.csproj b/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/WatchConsole.csproj new file mode 100644 index 0000000000..b59819b2aa --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/WatchConsole.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp3.0 + + + diff --git a/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/quotes.txt b/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/quotes.txt new file mode 100644 index 0000000000..047f17a588 --- /dev/null +++ b/aspnetcore/fundamentals/file-providers/samples/3.x/WatchConsole/quotes.txt @@ -0,0 +1,3 @@ +"As developers, we fail in two ways: We build the thing wrong, or we build the wrong thing." - Steve Smith + +"That's not a thing ... You just made that up." - David Fowler