החלת גירסת asp-append בנוסף לקבצים סטטיים בתיקיה wwwroot

תאריך יצירת דף :

בסביבה

סטודיו חזותי
  • סטודיו ויזואלי 2019
הליבה ASP.NET
  • 3.1 (דף גילוח, MVC)

קבצים סטטיים הממוקמים מחוץ לתיקיית wwwroot אינם משקפים גירסת asp-append

app.UseStaticFiles על-ידי ציון קריאה נוספת StaticFileOptions לפעולת השירות ניתן למקם קבצים סטטיים גם בתיקיות שאינן wwwroot. עם זאת, עבור קבצים סטטיים הממוקמים מחוץ לתיקיה wwwroot, קישור ותגי Script asp-append-version הגדרת התכונה אינה מוסיפה פרטי גירסה לכתובת ה- URL.

אני אנסה. הקבצים מסודרים בתצורות הבאות:

Startup.Configure כדי לפרסם גם את התיקיה אזורים/אתר1/תוכן.

// 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 אינה משתקפת

הדבר תלוי במאפיין הקובע אם גירסת ה- asp-append env.WebRootFileProvider IFileProvider משתקפת. כברירת מחדל, ה- wwwroot PhysicalFileProvider שצוין מוגדר כך שהוא אינו משתקף בתיקיות אחרות.

יש כיתה IFileProvider שיכולה להיות יותר CompositeFileProvider מאחד אתה יכול לארוז יותר מאחד כאן PhysicalFileProvider ולתת אותו env.WebRootFileProvider . ניתן להעביר רק נתיב תיקיה פיזית לנתיב האחרון, StaticFileOptions.RequestPath לא ניתן לציין יותר מאחד, ולכן אני לא חושב שזה יהיה הפעולה המיועדת.

* env.WebRootFileProvider Startup.Configure מתקבל IWebHostEnvironment env בשיטה.

קבל בירושה את IFileProvider וצור מחלקות משלך

ASP.NET הקובץProvider מכיוון שלא ניתן לתמוך בו על-ידי תכונות סטנדרטיות ב- 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 והקובץ הסטטי. אם staticFileOptions אינו נפגע, הגדרת wwwroot מוחלת על-ידי החזרת FileProvider המוגדר כברירת מחדל.

החזרת פרטי הקובץ הנכונים עבור כל פעולה asp-append-version תשקף את התכונה.

דרך אגב, הקוד הזה יכול להיות בכל מקום.

החל כיתה משלך (מרוכביםסטטיסטיקהפילההאופידר)

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.