File Providers topic update for 3.0 (#14027)

pull/14031/head
Luke Latham 2019-08-26 15:16:50 -05:00 committed by GitHub
parent a68e43d4b3
commit 2d27dd6f76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 458 additions and 96 deletions

View File

@ -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 <xref:Microsoft.Extensions.FileProviders.IFileProvider>. `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 (<xref:Microsoft.Extensions.FileProviders.IFileInfo>).
* Obtain directory information (<xref:Microsoft.Extensions.FileProviders.IDirectoryContents>).
* Set up change notifications (using an <xref:Microsoft.Extensions.Primitives.IChangeToken>).
`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
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.Exists>
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.IsDirectory>
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.Name>
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.Length> (in bytes)
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.LastModified> 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 <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).
**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 <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.
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 `<GenerateEmbeddedFilesManifest>` property to `true`. Specify the files to embed with [\<EmbeddedResource>](/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 <xref:Microsoft.Extensions.FileProviders.IFileProvider.GetDirectoryContents*> to those resources under the provided path. |
| `ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset)` | Accepts an optional `root` relative path parameter and a `lastModified` date (<xref:System.DateTimeOffset>) parameter. The `lastModified` date scopes the last modification date for the <xref:Microsoft.Extensions.FileProviders.IFileInfo> instances returned by the <xref:Microsoft.Extensions.FileProviders.IFileProvider>. |
| `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 <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.
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 <xref:Microsoft.Extensions.Primitives.IChangeToken>. The change token exposes:
* <xref:Microsoft.Extensions.Primitives.IChangeToken.HasChanged> &ndash; A property that can be inspected to determine if a change has occurred.
* <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.
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:
* <xref:Microsoft.Extensions.Hosting.IHostingEnvironment> 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 <xref:Microsoft.Extensions.FileProviders.IFileProvider>. `IFileProvider` exposes methods to:
* Obtain file information (<xref:Microsoft.Extensions.FileProviders.IFileInfo>).
* Obtain directory information (<xref:Microsoft.Extensions.FileProviders.IDirectoryContents>).
* Set up change notifications (using an <xref:Microsoft.Extensions.Primitives.IChangeToken>).
`IFileInfo` provides methods and properties for working with files:
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.Exists>
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.IsDirectory>
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.Name>
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.Length> (in bytes)
* <xref:Microsoft.Extensions.FileProviders.IFileInfo.LastModified> 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 <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).
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 <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.
To generate a manifest of the embedded files, set the `<GenerateEmbeddedFilesManifest>` property to `true`. Specify the files to embed with [&lt;EmbeddedResource&gt;](/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 <xref:Microsoft.Extensions.FileProviders.IFileProvider.GetDirectoryContents*> to those resources under the provided path. |
| `ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset)` | Accepts an optional `root` relative path parameter and a `lastModified` date (<xref:System.DateTimeOffset>) parameter. The `lastModified` date scopes the last modification date for the <xref:Microsoft.Extensions.FileProviders.IFileInfo> instances returned by the <xref:Microsoft.Extensions.FileProviders.IFileProvider>. |
| `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 <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.
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 <xref:Microsoft.Extensions.Primitives.IChangeToken>. 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.
* <xref:Microsoft.Extensions.Primitives.IChangeToken.HasChanged> &ndash; A property that can be inspected to determine if a change has occurred.
* <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.
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

View File

@ -18,7 +18,7 @@
{
if (item.IsDirectory)
{
<li><strong>@item.Name</strong></li>
<li><strong>@item.Name</strong> folder</li>
}
else
{

View File

@ -1,41 +0,0 @@
@using Microsoft.AspNetCore.Http.Features
@{
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
var showBanner = !consentFeature?.CanTrack ?? false;
var cookieString = consentFeature?.CreateConsentCookie();
}
@if (showBanner)
{
<nav id="cookieConsent" class="navbar navbar-default navbar-fixed-top" role="alert">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#cookieConsent .navbar-collapse">
<span class="sr-only">Toggle cookie consent banner</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="navbar-brand"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span></span>
</div>
<div class="collapse navbar-collapse">
<p class="navbar-text">
Use this space to summarize your privacy and cookie use policy.
</p>
<div class="navbar-right">
<a asp-page="/Privacy" class="btn btn-info navbar-btn">Learn More</a>
<button type="button" class="btn btn-default navbar-btn" data-cookie-string="@cookieString">Accept</button>
</div>
</div>
</div>
</nav>
<script>
(function () {
document.querySelector("#cookieConsent button[data-cookie-string]").addEventListener("click", function (el) {
document.cookie = el.target.dataset.cookieString;
document.querySelector("#cookieConsent").classList.add("hidden");
}, false);
})();
</script>
}

View File

@ -9,10 +9,6 @@
<body>
<div class="container">
@RenderBody()
<hr>
<footer>
<p>&copy;@System.DateTime.Now.Year - File Provider Sample</p>
</footer>
</div>
</body>
</html>

View File

@ -1,18 +0,0 @@
<environment include="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.9/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-ifv0TYDWxBHzvAk2Z0n8R434FL1Rlv/Av18DXE43N/1rvHyOG4izKst0f2iSLdds">
</script>
</environment>

View File

@ -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
"That's not a thing ... You just made that up." - David Fowler

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0-preview8.19405.4" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resource.txt" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,26 @@
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@ -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;
}
}
}

View File

@ -0,0 +1,30 @@
@page
@model IndexModel
@{
ViewData["Title"] = "File Provider Sample";
}
<h1>@ViewData["Title"]</h1>
<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">Folder Contents</h2>
</div>
<div class="panel-body">
<ul>
@foreach (var item in Model.DirectoryContents)
{
if (item.IsDirectory)
{
<li><strong>@item.Name</strong> folder</li>
}
else
{
<li>@item.Name - @item.Length bytes</li>
}
}
</ul>
</div>
</div>
</div>

View File

@ -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);
}
}
}

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewData["Title"]</title>
<style>body{margin:0;padding-bottom:20px;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff;}h1{font-size:24px;margin:.67em 0;}pre{overflow:auto;}code,pre{font-family:monospace, monospace;font-size:1em;}button,input{margin:0;font:inherit;color:inherit;}button{overflow:visible;}button{text-transform:none;}input{line-height:normal;}{box-sizing:border-box;}:before,*:after{box-sizing:border-box;}input,button{font-family:inherit;font-size:inherit;line-height:inherit;}a{color:#337ab7;text-decoration:none;}h1,h2,h3,h4{font-family:inherit;font-weight:500;line-height:1.1;color:inherit;margin-top:20px;margin-bottom:10px;}h3{font-size:16px;}h4{font-size:18px;}p{margin:0 0 10px;}ol{margin-top:0;margin-bottom:10px;}code,pre{font-family:Menlo, Monaco, Consolas, "Courier New", monospace;}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px;}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;-radius:4px;}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0;}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto;}.container{width:800px;}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;background-image:none;border:1px solid transparent;border-radius:4px;;color:#fff;background-color:green;border-color:gray;float:right}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;box-shadow:0 1px 1px rgba(0, 0, 0, .05);}.panel-body{padding:15px;}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px;}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit;}.panel-default{border-color:#ddd;}.panel-default > .panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd;}.clearfix:before,.clearfix:after,.container:before,.container:after,.panel-body:before,.panel-body:after{display:table;content:" ";}.clearfix:after,.container:after,.panel-body:after{clear:both;}.body-content{padding-left:15px;padding-right:15px;}.panel-body{font-size:16px;}</style>
</head>
<body>
<div class="container">
@RenderBody()
</div>
</body>
</html>

View File

@ -0,0 +1,3 @@
@using FileProviderSample
@namespace FileProviderSample.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

@ -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<Startup>();
});
}
}

View File

@ -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.

View File

@ -0,0 +1 @@
An embedded resource.

View File

@ -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<IFileProvider>(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();
});
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Error",
"System": "Information",
"Microsoft": "Information"
}
}
}

View File

@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

View File

@ -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<object>();
token.RegisterChangeCallback(state =>
((TaskCompletionSource<object>)state).TrySetResult(null), tcs);
await tcs.Task.ConfigureAwait(false);
Console.WriteLine("quotes.txt changed");
}
#endregion
}
}

View File

@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@ -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