Menerapkan versi asp-append selain file statis di folder wwwroot

Tanggal pembuatan halaman :

Lingkungan

Visual Studio
  • Studio Visual 2019
ASP.NET Inti
  • 3.1 (Halaman silet, MVC)

File statis yang ditempatkan di luar folder wwwroot tidak mencerminkan versi asp-append

app.UseStaticFiles Dengan menentukan panggilan StaticFileOptions tambahan ke metode File statis juga dapat ditempatkan di folder selain wwwroot. Namun, untuk file statis ditempatkan di luar folder wwwroot, link dan tag skrip asp-append-version Menyetel atribut tidak menambahkan informasi versi ke URL.

Aku akan mencobanya. File disusun dalam konfigurasi berikut:

Startup.Configure metode untuk juga menerbitkan folder Area/Situs1/Konten.

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

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

Kode index.cshtml berikut telah ditambahkan ke . asp-append-version Masing-masing ditambahkan.

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

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

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

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

Saat Anda menjalankannya, gambar ditampilkan dengan benar.

Namun, jika Anda melihat HTML halaman, Anda dapat melihat bahwa string hanya diperluas ke file yang ditempatkan di wwwroot.

Penyebab ketika asp-append-version tidak tercermin

Itu tergantung pada properti yang menentukan apakah versi asp-append env.WebRootFileProvider IFileProvider tercermin. Secara default, wwwroot PhysicalFileProvider yang ditentukan diatur sehingga tidak tercermin di folder lain.

Ada kelas yang IFileProvider dapat memiliki lebih dari CompositeFileProvider satu Anda dapat mengemas lebih dari satu di PhysicalFileProvider sini dan memberikannya kepada env.WebRootFileProvider . Hanya jalur folder fisik yang dapat diteruskan ke yang terakhir, StaticFileOptions.RequestPath Tidak mungkin untuk menentukan lebih dari satu, jadi saya tidak berpikir bahwa itu akan menjadi tindakan yang dimaksudkan.

* env.WebRootFileProvider diterima Startup.Configure dengan IWebHostEnvironment env metode.

Warisi IFileProvider dan buat kelas Anda sendiri

ASP.NET fileProvider karena tidak dapat didukung oleh fitur standar di Core saja.

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

Karena itu panjang, saya tidak akan menjelaskan detailnya, tetapi untuk menjelaskan secara singkat, Pertama, StaticFileOptions saya akan memiliki semua daftar yang saya buat di kelas ini. Aku akan mengatur kelas ini env.WebRootFileProvider ke properti nanti.

Setiap metode dipanggil ketika diakses oleh klien, jadi cari StaticFileOptions file statis mana yang Anda akses berdasarkan URL. Mengembalikan StaticFileOptions jalur relatif ke file hit dan FileProvider statis. Jika staticFileOptions tidak terpukul, pengaturan wwwroot diterapkan dengan mengembalikan FileProvider default.

Mengembalikan informasi file yang benar untuk setiap asp-append-version operasi akan mencerminkan atribut.

By the way, kode ini bisa di mana saja.

Terapkan kelas Anda sendiri (CompositeStaticFileOptionsProvider)

Startup.Configure Mari kita perbaiki sebagai berikut: Seperti yang tertulis, tidak ada yang perlu dijelaskan. StaticFileOptions Aku hanya meringkas mereka dalam array.

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();
  // 省略
}

Jika Anda menjalankannya sekarang, Anda dapat melihat bahwa atribut tercermin dalam file asp-append-version statis yang ditempatkan di folder selain wwwroot.