นอกจากไฟล์แบบคงที่ในโฟลเดอร์ wwwroot แล้ว asp-append-version ยังใช้อยู่ด้วย

วันที่สร้างเพจ :

สิ่งแวดล้อม

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 3.1 (หน้า Razor, MVC)

แฟ้มแบบคงที่ที่วางอยู่นอกโฟลเดอร์ wwwroot ไม่สะท้อนถึง asp-append-version

app.UseStaticFiles โดยการระบุการเรียก StaticFileOptions ไปยังวิธีการอื่น ไฟล์แบบคงที่ยังสามารถวางไว้ในโฟลเดอร์อื่นที่ไม่ใช่ wwwroot อย่างไรก็ตาม สําหรับแฟ้มแบบคงที่ ที่วางอยู่นอกโฟลเดอร์ wwwroot การเชื่อมโยงและแท็กสคริปต์ asp-append-version การตั้งค่าคุณสมบัติจะไม่แนบข้อมูลรุ่นกับ URL

ฉันจะพยายามที่จะตรวจสอบออก แฟ้มมีการกําหนดค่าต่อไปนี้:

Startup.Configure วิธีการยังถูกตั้งค่าให้แสดงโฟลเดอร์ Areas/Site1/Content

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

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

นี่คือ index.cshtml รหัสที่คุณเพิ่มลงใน asp-append-version แต่ละคนถูกแนบมา

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

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

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

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

เมื่อคุณทําเช่นนี้ ภาพจะแสดงอย่างถูกต้อง

อย่างไรก็ตาม ถ้าคุณดู HTML ของเพจ คุณจะพบว่า สายอักขระถูกปรับใช้เฉพาะกับแฟ้มที่วางไว้ใน wwwroot

เหตุผลที่ asp-append-version ไม่สะท้อน

ตั้งค่าโดยคุณสมบัติเพื่อตรวจสอบว่า asp-append-version env.WebRootFileProvider IFileProvider มีผลหรือไม่ โดยค่าเริ่มต้น wwwroot PhysicalFileProvider ระบุการตั้งค่า ดังนั้นจึงไม่สะท้อนให้เห็นในโฟลเดอร์อื่น

มีคลาส IFileProvider ที่สามารถมี CompositeFileProvider ได้มากกว่าหนึ่งคลาสในขณะนี้ PhysicalFileProvider คุณสามารถใส่ไม่กี่ env.WebRootFileProvider ที่นี่และส่งผ่านไปยัง สามารถส่งผ่านเส้นทางโฟลเดอร์ที่มีอยู่จริงได้เพียงเส้นทางเดียวเท่านั้น StaticFileOptions.RequestPath เนื่องจากไม่สามารถระบุได้มากกว่าหนึ่งรายการ ฉันไม่คิดว่าเป็นลักษณะการทํางานที่คาดไว้

env.WebRootFileProvider Startup.Configure * เป็น IWebHostEnvironment env วิธีการที่ได้รับ

สืบทอด IFileProvider และสร้างคลาสของคุณเอง

ASP.NET คุณสมบัติมาตรฐานใน Core ดังนั้นโปรดสร้าง FileProvider ของคุณเอง

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

เพราะมันยาวมากผมละเว้นคําอธิบายรายละเอียด แต่ใส่เพียง ขั้น StaticFileOptions แรก ให้เก็บรายการทั้งหมดที่คุณสร้างไว้ในคลาสนี้ ตั้งค่าคลาส env.WebRootFileProvider นี้ลงในคุณสมบัติในภายหลัง

เมื่อลูกค้าเข้าถึงได้แต่ละวิธีจะถูกเรียกดังนั้นเราจึง StaticFileOptions ค้นหาไฟล์แบบคงที่ที่เราเข้าถึงตามการค้นหา URL ส่งกลับ StaticFileOptions พาธ FileProvider สัมพัทธ์ของไฟล์ Hit และไฟล์สแตติก หาก StaticFileOptions พลาด การตั้งค่า wwwroot จะถูกนําไปใช้โดยการส่งคืน FileProvider เริ่มต้น

คุณสมบัติจะมีผลถ้าแต่ละ asp-append-version การดําเนินการส่งกลับข้อมูลแฟ้มที่ถูกต้อง

โดยวิธีการที่มันไม่สําคัญว่าฉันจะสร้างรหัสนี้

ใช้คลาสของคุณเอง (CompositeStaticFileOptions Provider)

Startup.Configure ตอนนี้คุณสามารถแก้ไขได้ดังนี้: เพราะมันถูกเขียนขึ้นจึงไม่มีสิ่งพิเศษที่จะอธิบาย StaticFileOptions ฉันใช้อาร์เรย์เพื่อสรุปมัน

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

เมื่อคุณทําเช่นนี้ คุณจะเห็นคุณสมบัติยังสะท้อนให้เห็นในแฟ้มแบบคงที่ที่วาง asp-append-version อยู่ในโฟลเดอร์อื่นที่ไม่ใช่ wwwroot