Aplicați versiunea asp-append în plus față de fișierele statice din folderul wwwroot

Data creării paginii :

Mediu

Studio vizual
  • Studio vizual 2019
ASP.NET Core
  • 3.1 (Pagina razor, MVC)

Fișierele statice plasate în afara folderului wwwroot nu reflectă asp-append-version

app.UseStaticFiles Specificând un apel suplimentar StaticFileOptions la metoda Fișierele statice pot fi, de asemenea, plasate în alte foldere decât wwwroot. Cu toate acestea, pentru fișierele statice plasate în afara folderului wwwroot, link-ul și etichetele de script asp-append-version Setarea atributului nu adaugă informații despre versiune la URL.

O să încerc. Fișierele sunt aranjate în următoarele configurații:

Startup.Configure pentru a publica, de asemenea, folderul Zone/Site1/Conținut.

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

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

Următorul index.cshtml cod a fost adăugat la . Fiecare asp-append-version este adăugat.

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

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

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

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

Când o executați, imaginea este afișată corect.

Cu toate acestea, dacă vă uitați la HTML-ul paginii, puteți vedea că șirul este extins numai la fișierele plasate în wwwroot.

Cauze atunci când asp-append-version nu se reflectă

Depinde de proprietatea care determină dacă versiunea asp-append env.WebRootFileProvider este IFileProvider reflectată. În mod implicit, wwwroot PhysicalFileProvider specificat este setat astfel încât să nu se reflecte în alte foldere.

Există o clasă IFileProvider care poate avea mai mult CompositeFileProvider de o Puteți ambalaj mai mult de unul aici PhysicalFileProvider și dă-l la env.WebRootFileProvider . Numai o cale de folder fizic poate fi transmisă la ultima, StaticFileOptions.RequestPath Nu este posibil să se precizeze mai multe, deci nu cred că va fi acțiunea preconizată.

* env.WebRootFileProvider se Startup.Configure primea prin IWebHostEnvironment env metoda.

Moștenește IFileProvider și creează-ți propriile clase

ASP.NET fișierProvider, deoarece nu poate fi acceptat numai de caracteristicile standard din Core.

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

Pentru că este lung, nu voi explica detaliile, ci pentru a explica pe scurt, În primul rând, StaticFileOptions voi avea toată lista pe care am creat-o în această clasă. Voi seta acest curs env.WebRootFileProvider la o proprietate mai târziu.

Fiecare metodă este apelată atunci când este accesată de un client, deci căutați ce StaticFileOptions fișier static ați accesat pe baza URL-ului. Returnează StaticFileOptions calea relativă la fișierul lovit și FileProvider static. Dacă staticFileOptions nu este lovit, setarea wwwroot se aplică prin returnarea implicit FileProvider.

Returnarea informațiilor corecte despre fișier pentru fiecare operație asp-append-version va reflecta atributul.

Apropo, acest cod poate fi oriunde.

Aplicați propria clasă (CompositeStaticFileOptionsProvider)

Startup.Configure Să o reparăm după urmează: După s-a scris, nu este nimic de explicat. StaticFileOptions Doar le rezum într-o matrice.

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

Dacă îl executați acum, puteți vedea că atributul se reflectă în fișiere statice asp-append-version plasate în alte foldere decât wwwroot.