Gunakan versi asp-apl sebagai tambahan kepada fail statik dalam folder wwwroot

Tarikh penciptaan halaman :

Persekitaran

Visual Studio
  • Studio Visual 2019
ASP.NET Teras
  • 3.1 (Laman Cukur, MVC)

Fail statik yang diletakkan di luar folder wwwroot tidak mencerminkan asp-append-versi

app.UseStaticFiles Dengan menentukan panggilan StaticFileOptions tambahan ke kaedah Fail statik juga boleh diletakkan dalam folder selain daripada wwwroot. Walau bagaimanapun, untuk fail statik yang diletakkan di luar folder wwwroot, pautan dan tag skrip asp-append-version Menetapkan atribut tidak menambah maklumat versi ke URL.

Saya akan mencubanya. Fail disusun dalam konfigurasi berikut:

Startup.Configure kaedah untuk juga menerbitkan folder Kawasan/Site1/Kandungan.

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

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

Kod index.cshtml berikut telah ditambah kepada . asp-append-version Masing-masing ditambah.

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

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

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

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

Apabila anda menjalankannya, imej dipaparkan dengan betul.

Walau bagaimanapun, jika anda melihat HTML halaman, anda dapat melihat bahawa rentetan itu hanya diperluaskan ke fail yang diletakkan di wwwroot.

Punca apabila versi lampiran ASP tidak dicerminkan

Ia bergantung kepada harta yang menentukan sama ada versi asp-lampiran env.WebRootFileProvider IFileProvider ditunjukkan. Secara lalai, wwwroot PhysicalFileProvider yang ditentukan disetkan supaya ia tidak ditunjukkan dalam folder lain.

Terdapat kelas yang IFileProvider boleh mempunyai lebih daripada CompositeFileProvider satu Anda boleh membungkus lebih daripada satu di PhysicalFileProvider sini dan memberi kepada env.WebRootFileProvider . Hanya laluan folder fizikal boleh dihantar ke yang terakhir, StaticFileOptions.RequestPath Tidak mungkin untuk menentukan lebih daripada satu, jadi saya tidak fikir ia akan menjadi tindakan yang dimaksudkan.

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

Mewarisi IFileProvider dan buat kelas anda sendiri

ASP.NET failProvider kerana ia tidak boleh disokong oleh ciri standard dalam Teras sahaja.

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

Kerana sudah lama, saya tidak akan menjelaskan butiran, tetapi untuk menjelaskan secara ringkas, Pertama, StaticFileOptions saya akan mempunyai semua senarai yang saya buat dalam kelas ini. Saya akan menetapkan kelas ini env.WebRootFileProvider kepada hartanah kemudian.

Setiap kaedah dipanggil apabila diakses oleh pelanggan, jadi cari fail StaticFileOptions statik yang anda akses berdasarkan URL. Mengembalikan laluan StaticFileOptions relatif ke fail hit dan FileProvider statik. Jika staticFileOptions tidak dilanggar, tetapan wwwroot digunakan dengan mengembalikan FileProvider lalai.

Mengembalikan maklumat fail yang betul untuk setiap asp-append-version operasi akan mencerminkan atribut.

Dengan cara ini, kod ini boleh di mana-mana sahaja.

Gunakan kelas anda sendiri (CompositeStaticFileOptionsProvider)

Startup.Configure Mari kita perbetulkan seperti berikut: Seperti yang ditulis, tidak ada apa-apa untuk dijelaskan. StaticFileOptions Saya hanya merumuskan mereka dalam pelbagai.

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 bahawa atribut ditunjukkan dalam fail statik asp-append-version yang diletakkan dalam folder selain daripada wwwroot.