Appliquer asp-append-version en plus des fichiers statiques dans le dossier wwwroot

Date de création de la page :

environnement

Studio visuel
  • Studio visuel 2019
ASP.NET noyau
  • 3.1 (Page Razor, MVC)

Les fichiers statiques placés en dehors du dossier wwwroot ne reflètent pas la version asp-append

app.UseStaticFiles En spécifie un StaticFileOptions appel supplémentaire à la méthode Les fichiers statiques peuvent également être placés dans des dossiers autres que wwwroot. Toutefois, pour les fichiers statiques placés en dehors du dossier wwwroot, les balises de lien et de script asp-append-version La configuration de l’attribut n’ajoute pas d’informations de version à l’URL.

Je vais essayer. Les fichiers sont disposés dans les configurations suivantes :

Startup.Configure également publier le dossier Zones/Site1/Contenu.

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

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

Le index.cshtml code suivant a été ajouté à . Chacun asp-append-version est ajouté.

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

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

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

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

Lorsque vous l’exécutez, l’image s’affiche correctement.

Toutefois, si vous regardez le HTML de la page, vous pouvez voir que la chaîne n’est étendue qu’aux fichiers placés dans wwwroot.

Causes lorsque la version asp-append n’est pas reflétée

Cela dépend de la propriété qui détermine si la version asp-append est env.WebRootFileProvider IFileProvider reflétée. Par défaut, le wwwroot spécifié PhysicalFileProvider est défini de sorte qu’il ne soit pas reflété dans d’autres dossiers.

Il y a une classe IFileProvider qui peut avoir plus d’un CompositeFileProvider Vous pouvez emballer plus d’un PhysicalFileProvider ici et le donner à env.WebRootFileProvider . Seul un chemin de dossier physique peut être transmis au dernier, StaticFileOptions.RequestPath Il n’est pas possible d’en préciser plus d’un, donc je ne pense pas que ce sera l’action prévue.

* env.WebRootFileProvider est reçu par Startup.Configure IWebHostEnvironment env méthode.

Héritez d’IFileProvider et créez vos propres classes

ASP.NET fichierProvider parce qu’il ne peut pas être pris en charge par des fonctionnalités standard dans Core seul.

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

Parce que c’est long, je n’expliquerai pas les détails, mais pour expliquer brièvement, Tout StaticFileOptions d’abord, je vais avoir toute la liste de ce que j’ai créé dans cette classe. Je vais mettre ce cours dans env.WebRootFileProvider une propri été plus tard.

Chaque méthode est appelée lorsqu’elle est consultée par un client, alors recherchez le StaticFileOptions fichier statique auquel vous avez accé en fonction de l’URL. Renvoie StaticFileOptions le chemin relatif au fichier touché et FileProvider statique. Si staticFileOptions n’est pas touché, le paramètre wwwroot est appliqué en renvoyant le FileProvider par défaut.

Le retour des informations de fichier correctes pour chaque asp-append-version opération reflétera l’attribut.

Soit dit en passant, ce code peut être n’importe où.

Appliquez votre propre classe (CompositeStaticFileOptionsProvider)

Startup.Configure Réparons-le comme suit : Tel qu’il est écrit, il n’y a rien à expliquer. StaticFileOptions Je les résume dans un tableau.

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

Si vous l’exécutez maintenant, vous pouvez voir que l’attribut est reflété dans les fichiers asp-append-version statiques placés dans des dossiers autres que wwwroot.