Anvende asp-append-version ud over statiske filer i mappen wwwroot

Dato for oprettelse af side :

Miljø

Visual Studio
  • Visual Studio 2019
ASP.NET Kerne
  • 3.1 (Barberbladsside, MVC)

Statiske filer placeret uden for mappen wwwroot afspejler ikke asp-append-version

app.UseStaticFiles Ved at angive et ekstra StaticFileOptions kald til metoden Statiske filer kan også placeres i andre mapper end wwwroot. Men for statiske filer placeret uden for wwwroot mappe, link og script tags asp-append-version Hvis du angiver attributten, føjes versionsoplysninger ikke til URL-adressen.

Jeg vil give det en chance. Filerne er arrangeret i følgende konfigurationer:

Startup.Configure til også at udgive mappen Områder/Websted1/Indhold.

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

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

Følgende index.cshtml kode er føjet til . Hver asp-append-version er tilføjet.

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

<!-- 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ører det, vises billedet korrekt.

Men hvis man ser på HTML på siden, kan du se, at strengen kun er udvidet til de filer, der er placeret i wwwroot.

Forårsager, når asp-append-version ikke afspejles

Det afhænger af den egenskab, der bestemmer, om asp-append-versionen env.WebRootFileProvider IFileProvider afspejles. Den angivne wwwroot er som standard PhysicalFileProvider angivet, så den ikke afspejles i andre mapper.

Der er en IFileProvider klasse, der kan have mere end CompositeFileProvider én Du kan pakke mere end én her PhysicalFileProvider og give det til env.WebRootFileProvider . Kun en sti til en fysisk mappe kan overføres til den sidste, StaticFileOptions.RequestPath Det er ikke muligt at specificere mere end én, så jeg tror ikke, at det vil være den tilsigtede handling.

* env.WebRootFileProvider Startup.Configure modtages efter IWebHostEnvironment env metode.

Arv IFileProvider, og opret dine egne klasser

ASP.NET fileProvider, fordi den ikke kan understøttes af standardfunktioner alene 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);
    }
  }
}

Fordi det er lang, vil jeg ikke forklare detaljerne, men at forklare kort, Først StaticFileOptions vil jeg have alle de liste over, at jeg har oprettet i denne klasse. Jeg vil sætte denne klasse env.WebRootFileProvider til en ejendom senere.

Hver metode kaldes, når en klient får adgang til den, så søg efter StaticFileOptions den statiske fil, du har fået adgang til, baseret på URL-adressen. Returnerer den StaticFileOptions relative sti til hitfilen og den statiske FileProvider fil. Hvis staticFileOptions ikke rammes, anvendes indstillingen wwwroot ved at returnere standardfilenProvider.

Hvis du returnerer de korrekte filoplysninger for hver asp-append-version handling, afspejles attributten.

Forresten kan denne kode være hvor som helst.

Anvende din egen klasse (CompositeStaticFileOptionsProvider)

Startup.Configure Lad os ordne det på følgende måde: Som skrevet, er der intet at forklare. StaticFileOptions Jeg opsummerer dem bare i en matrix.

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

Hvis du kører den nu, kan du se, at attributten afspejles i statiske filer, der er asp-append-version placeret i andre mapper end wwwroot.