Ngoài các tệp tĩnh trong thư mục wwwroot, asp-append-version cũng được áp dụng

Ngày tạo trang :

môi trường

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 3.1 (Trang Razor, MVC)

Các tệp tĩnh được đặt bên ngoài thư mục wwwroot không phản ánh asp-append-version

app.UseStaticFiles Bằng cách chỉ định một cuộc gọi StaticFileOptions đến các phương pháp khác Các tệp tĩnh cũng có thể được đặt trong một thư mục khác với wwwroot. Tuy nhiên, đối với các tệp tĩnh, liên kết và thẻ tập lệnh được đặt bên ngoài thư mục wwwroot asp-append-version Đặt thuộc tính không đính kèm thông tin phiên bản vào URL.

Tôi sẽ cố gắng kiểm tra. Tệp có cấu hình sau:

Startup.Configure Phương pháp này cũng được thiết lập để tiếp cận thư mục Areas/Site1/Content.

// wwwroot フォルダで静的ファイル参照を有効にする
app.UseStaticFiles();

// Site1 用の物理コンテンツフォルダと参照 URL を紐づける
app.UseStaticFiles(new StaticFileOptions()
{
  FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Areas/Site1/Content")),
  RequestPath = "/Site1",
});

Dưới đây index.cshtml là mã bạn đã thêm vào. Mỗi asp-append-version người trong số họ được đính kèm.

<!-- ここから追加 -->

<!-- wwwroot のファイル -->
<img src="~/image/sample.png" asp-append-version="true" />

<!-- wwwroot 以外のファイル -->
<img src="~/site1/image/sample1.png" asp-append-version="true" />

<!-- ここからまで -->

Khi bạn làm điều này, hình ảnh được hiển thị một cách chí

Tuy nhiên, nếu bạn nhìn vào HTML của trang, bạn sẽ thấy rằng chuỗi chỉ được triển khai cho các tệp được đặt trong wwwroot.

Lý do asp-append-version không được phản ánh

Được thiết lập bởi các thuộc tính để xác định xem asp-append-version có env.WebRootFileProvider hiệu IFileProvider lực hay không. Theo mặc định, wwwroot được đặt PhysicalFileProvider thành và do đó không được phản ánh trong các thư mục khác.

Có một lớp có IFileProvider thể tạm CompositeFileProvider thời có nhiều hơn một, Bạn có PhysicalFileProvider thể nhét một vài người env.WebRootFileProvider ở đây và vượt qua nó Chỉ có thể vượt qua nhiều đường dẫn thư mục vật lý, StaticFileOptions.RequestPath Bởi vì nhiều hơn một không thể được chỉ định, tôi không nghĩ rằng họ là hành vi mong đợi.

env.WebRootFileProvider* Là Startup.Configure phương pháp IWebHostEnvironment env để nhận được.

Kế thừa IFileProvider và tạo lớp của riêng bạn

ASP.NET tính năng tiêu chuẩn trong Core, vì vậy hãy tạo FileProvider của riêng bạn.

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Primitives;

namespace Microsoft.Extensions.FileProviders
{
  /// <summary>
  /// wwwroot フォルダ以外のファイルで "asp-append-version”を有効にするための複数の <see cref="StaticFileOptions"/> を管理するファイルプロバイダです。
  /// </summary>
  class CompositeStaticFileOptionsProvider : IFileProvider
  {
    private readonly IFileProvider _webRootFileProvider;
    private readonly IEnumerable<StaticFileOptions> _staticFileOptions;

    /// <summary>
    /// コンストラクタです。
    /// </summary>
    /// <param name="webRootFileProvider">
    /// デフォルトの wwwroot が設定されている WebRootFileProvider を指定します。通常は env.WebRootFileProvider を指定してください。
    /// これは追加した <see cref="StaticFileOptions"/> がヒットしなかった場合に使用するためです。
    /// </param>
    /// <param name="staticFileOptions">
    /// 追加した静的ファイルオプションの一覧です。
    /// FileProvider と RequestPath が設定されている必要があります。
    /// </param>
    public CompositeStaticFileOptionsProvider(IFileProvider webRootFileProvider, IEnumerable<StaticFileOptions> staticFileOptions)
    {
      _webRootFileProvider = webRootFileProvider ?? throw new ArgumentNullException(nameof(webRootFileProvider));
      _staticFileOptions = staticFileOptions;
    }

    /// <summary>
    /// 指定されたパスにあるディレクトリを列挙します(存在する場合)。
    /// </summary>
    /// <param name="subpath">ディレクトリを識別する相対パス。</param>
    /// <returns>ディレクトリの内容を返します。</returns>
    public IDirectoryContents GetDirectoryContents(string subpath)
    {
      var result = GetFileProvider(subpath);
      return result.FileProvider.GetDirectoryContents(result.StaticFileRelativePath);
    }

    /// <summary>
    /// 指定されたパスでファイルを見つけます。
    /// </summary>
    /// <param name="subpath">ファイルを識別する相対パス。</param>
    /// <returns>ファイル情報。 発信者はExistsプロパティを確認する必要があります。</returns>
    public IFileInfo GetFileInfo(string subpath)
    {
      var result = GetFileProvider(subpath);
      return result.FileProvider.GetFileInfo(result.StaticFileRelativePath);
    }

    /// <summary>
    /// 指定されたフィルターの Microsoft.Extensions.Primitives.IChangeToken を作成します。
    /// </summary>
    /// <param name="filter">監視するファイルまたはフォルダーを決定するために使用されるフィルター文字列。 例:**/*.cs、*.*、subFolder/**/*.cshtml。</param>
    /// <returns>ファイル一致フィルターが追加、変更、または削除されたときに通知される Microsoft.Extensions.Primitives.IChangeToken。</returns>
    public IChangeToken Watch(string filter)
    {
      var result = GetFileProvider(filter);
      return result.FileProvider.Watch(result.StaticFileRelativePath);
    }

    /// <summary>
    /// 指定された相対 URL に含まれる <see cref="StaticFileOptions"/> を探し、その FileProvider と静的ファイルへの相対パスを返します。
    /// 見つからなかった場合は wwwroot を持つ FileProvider を返します。
    /// </summary>
    /// <param name="path">アクセスされたホスト名以降の相対 URL。</param>
    /// <returns>検索された <see cref="StaticFileOptions"/> の FileProvider と RequestPath から静的ファイルへの相対パス。</returns>
    private (IFileProvider FileProvider, string StaticFileRelativePath) GetFileProvider(string path)
    {
      if (_staticFileOptions != null)
      {
        foreach (var option in _staticFileOptions)
        {
          // 登録している RequestPath とアクセスされた URL の大文字小文字が異なる場合があるので OrdinalIgnoreCase を指定
          if (path.StartsWith(option.RequestPath, StringComparison.OrdinalIgnoreCase))
          {
            return (option.FileProvider, path[option.RequestPath.Value.Length..]);
          }
        }
      }
      return (_webRootFileProvider, path);
    }
  }
}

Bởi vì nó là dài, tỉnh của tôi bỏ qua các chi tiết giải thích, nhưng đơn giản là nói, Đầu tiên, StaticFileOptions giữ tất cả các danh sách bạn tạo ra trong lớp này. Đặt lớp này env.WebRootFileProvider vào thuộc tính sau.

Khi khách hàng truy cập nó, mỗi phương pháp được gọi là, vì vậy chúng tôi StaticFileOptions truy cập các tập tin tĩnh dựa trên tìm kiếm URL. Trả về StaticFileOptions đường FileProvider dẫn tương đối đến lần truy cập và tệp tĩnh. Nếu StaticFileOptions bỏ lỡ, cài đặt wwwroot được áp dụng bằng cách trả về FileProvider mặc định.

Nếu mỗi hành động trả về thông tin tệp chính xác, asp-append-version thuộc tính sẽ có hiệu lực.

Bằng cách này, nó không quan trọng nếu tôi tạo ra mã này.

Áp dụng lớp học của riêng bạn (CompositeStaticFileOptions Proovider)

Startup.Configure Bây giờ bạn có thể sửa chữa nó như sau: Bởi vì nó được viết, không có gì đặc biệt để giải thích. StaticFileOptions Tôi sử dụng một mảng để tóm tắt nó.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  // 省略
  app.UseHttpsRedirection();
  
  // ここから修正
  
  var staticOptions = new StaticFileOptions[]
  {
    // Site1 用の物理コンテンツフォルダと参照 URL を紐づける
    new StaticFileOptions()
    {
      FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Areas/Site1/Content")),
      RequestPath = "/Site1",
    },
    // 複数ある場合はこんな感じで追加
    //new StaticFileOptions()
    //{
    //  FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Areas/Site2/Content")),
    //  RequestPath = "/Site2",
    //},
  };
  
  // wwwroot フォルダで静的ファイル参照を有効にする
  app.UseStaticFiles();
  
  // 追加したい StaticFileOptions
  foreach (var option in staticOptions)
  {
    app.UseStaticFiles(option);
  }
  
  // StaticFileOptions を独自クラスでまとめて WebRootFileProvider にセットする
  var compositeProvider = new CompositeStaticFileOptionsProvider(env.WebRootFileProvider, staticOptions);
  env.WebRootFileProvider = compositeProvider;
  
  // ここまで修正
  
  app.UseRouting();
  // 省略
}

Khi bạn làm điều này, bạn sẽ thấy rằng các thuộc tính cũng được phản ánh trong các tập tin tĩnh được đặt asp-append-version trong một thư mục khác hơn là wwwroot.