اعمال asp-append-version علاوه بر فایل های استاتیک در پوشه wwwroot

تاریخ ایجاد صفحه :

محیط

ویژوال استودیو
  • ویژوال استودیو ۲۰۱۹
ASP.NET هسته
  • 3.1 (صفحه تیغ، 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 به تنهایی پشتیبانی می شود.

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 برمیگرداند. اگر استاتیکFileOptions ضربه نیست ، تنظیمات wwwroot با بازگشت فایل پیش فرض اعمال می شود.

بازگشت اطلاعات پرونده صحیح برای هر عملیات ویژگی asp-append-version را منعکس خواهد کرد.

به هر حال، اين کد ميتونه هر جايي باشه.

درخواست کلاس خود را (CompositeStaticFileOptionsProvider)

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

اگر اکنون آن را اجرا کنید، می بینید که ویژگی در فایل های ایستا که در پوشه هایی غیر از wwwroot قرار داده شده asp-append-version اند منعکس شده است.