Använda asp-append-version förutom statiska filer i mappen wwwroot

Datum för skapande av sida :

Miljö

Visuell studio
  • Visual Studio 2019
ASP.NET kärna
  • 3.1 (Rakbladssida, MVC)

Statiska filer som placeras utanför mappen wwwroot återspeglar inte asp-append-version

app.UseStaticFiles Genom att ange ytterligare StaticFileOptions ett anrop till metoden Statiska filer kan också placeras i andra mappar än wwwroot. För statiska filer som placerats utanför wwwroot-mappen, länk- och skripttaggar asp-append-version Om du anger attributet lägger du inte till versionsinformation i URL:en.

Jag ska försöka. Filerna är ordnade i följande konfigurationer:

Startup.Configure metod för att även publicera mappen Områden/Webbplats1/Innehåll.

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

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

Följande kod index.cshtml har lagts till i . Var asp-append-version och en läggs till.

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

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

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

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

När du kör den visas bilden korrekt.

Men om du tittar på sidans HTML kan du se att strängen bara expanderas till filerna som placeras i wwwroot.

Orsaker när asp-append-version inte återspeglas

Det beror på egenskapen som avgör om asp-append-versionen env.WebRootFileProvider IFileProvider återspeglas. Som standard anges den angivna PhysicalFileProvider wwwrooten så att den inte återspeglas i andra mappar.

Det finns en klass IFileProvider som kan ha mer än CompositeFileProvider en Du kan packa mer än en här PhysicalFileProvider och ge den till env.WebRootFileProvider . Endast en fysisk mappsökväg kan skickas till den sista, StaticFileOptions.RequestPath Det är inte möjligt att specificera mer än en, så jag tror inte att det kommer att vara den avsedda åtgärden.

* env.WebRootFileProvider tas emot med Startup.Configure IWebHostEnvironment env metod.

Ärva IFileProvider och skapa dina egna klasser

ASP.NET FileProvider eftersom det inte kan stödjas av standardfunktioner bara i 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);
    }
  }
}

Eftersom det är långt, kommer jag inte att förklara detaljerna, utan att förklara kortfattat, Först StaticFileOptions har jag alla listan över som jag skapade i den här klassen. Jag ställer in den här klassen env.WebRootFileProvider på en fastighet senare.

Varje metod kallas när den nås av en klient, så sök efter vilken StaticFileOptions statisk fil du kom åt baserat på URL: en. Returnerar StaticFileOptions den relativa sökvägen till träff- och FileProvider statiskfilen. Om staticFileOptions inte träffas tillämpas wwwroot-inställningen genom att returnera standardfilprovidern.

Om du returnerar rätt filinformation för varje asp-append-version åtgärd återspeglas attributet.

Förresten, den här koden kan vara var som helst.

Använd din egen klass (CompositeStaticFileOptionsProvider)

Startup.Configure Låt oss fixa det på följande sätt: Som det står skrivet finns det inget att förklara. StaticFileOptions Jag sammanfattar dem bara i en rad.

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

Om du kör det nu kan du se att attributet återspeglas i statiska asp-append-version filer som placeras i andra mappar än wwwroot.