Použiť asp-pripojiť-verzia okrem statických súborov v priečinku wwwroot

Dátum vytvorenia strany :

Životné prostredie

Vizuálne štúdio
  • Visual Studio 2019
ASP.NET jadro
  • 3.1 (Britva strana, MVC)

Statické súbory umiestnené mimo priečinka wwwroot neodrážajú verziu asp-append-version

app.UseStaticFiles Zadaním dodatočného StaticFileOptions hovoru k metóde Statické súbory môžu byť tiež umiestnené v iných priečinkoch ako wwwroot. Avšak pre statické súbory umiestnené mimo priečinka wwwroot, odkaz a skript tagy asp-append-version Nastavenie atribútu nepridá informácie o verzii url.

Skúsim to. Súbory sú usporiadané v nasledujúcich konfiguráciách:

Startup.Configure na publikovanie priečinka Oblasti/Lokalita1/Obsah.

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

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

Nasledujúci index.cshtml kód bol pridaný do . Každá asp-append-version sa pridá.

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

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

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

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

Keď ho spustíte, obrázok sa zobrazí správne.

Avšak, ak sa pozriete na HTML stránky, môžete vidieť, že reťazec je len rozšírený na súbory umiestnené v wwwroot.

Príčiny, keď asp-pripojiť-verzia sa neodráža

Závisí to od vlastnosti, ktorá určuje, či asp-pripojiť-verzia sa env.WebRootFileProvider IFileProvider odráža. V predvolenom nastavení wwwroot zadaný PhysicalFileProvider je nastavený tak, že sa neprejavia v iných priečinkoch.

Existuje trieda, IFileProvider ktorá môže mať viac ako CompositeFileProvider jednu Môžete tu zbaliť viac ako PhysicalFileProvider jeden a dať ho env.WebRootFileProvider . Do posledného priečinka je možné preniesť iba cestu k fyzickému priečinku, StaticFileOptions.RequestPath Nie je možné špecifikovať viac ako jednu, takže si nemyslím, že to bude zamýšľaná akcia.

* env.WebRootFileProvider Startup.Configure je prijímaný IWebHostEnvironment env metódou.

Zdediť IFileProvider a vytvoriť vlastné triedy

ASP.NET fileProvider, pretože ho nie je možné podporovať štandardnými funkciami len v 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);
    }
  }
}

Pretože je to dlhé, nebudem vysvetľovať detaily, ale stručne vysvetľovať, Najprv StaticFileOptions budem mať zoznam toho, čo som vytvoril v tejto triede. Túto triedu nastavím env.WebRootFileProvider na pozemok neskôr.

Každá metóda sa nazýva pri prístupe klienta, takže vyhľadajte, ktorý StaticFileOptions statický súbor ste pristupovali na základe adresy URL. Vráti StaticFileOptions relatívnu cestu k prístupu a statickému FileProvider súboru. Ak staticFileOptions nie je hit, wwwroot nastavenie sa použije vrátením predvoleného FileProvider.

Vrátenie správnych informácií o súbore pre každú asp-append-version operáciu bude odrážať atribút.

Mimochodom, tento kód môže byť kdekoľvek.

Použiť vlastnú triedu (CompositeStaticFileOptionsProvider)

Startup.Configure Poďme to opraviť takto: Ako bolo napísané, nie je čo vysvetľovať. StaticFileOptions Len ich sumarizujem v poli.

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

Ak ho spustíte teraz, môžete vidieť, že atribút sa odráža v statických súboroch asp-append-version umiestnených v iných priečinkoch ako wwwroot.