たぶん これの複製 はすでにありますが、その投稿には回答がないため、この質問を投稿しています。
新しい Razor Class Library はすばらしいですが、ライブラリファイル(jQuery、共有CSSなど)をパックできません。
Razorクラスライブラリなどを使用して、CSSを複数のRazorページプロジェクト間でどうにか再利用できますか(私の目的は、複数のWebサイトが同じCSSを使用し、1つの変更がすべてのプロジェクトに適用されることです)。
Razor Class Libraryプロジェクトでwwwroot
フォルダーを作成しようとしましたが、期待どおりに機能しません(私はcan理由を理解しています動作しないはずです)。
Ehsanの回答は、(。NET Core 2.2の場合)、. NET Core 3.0の場合 RCLは静的アセットを含めることができます に質問する時点で正解でした。
RCLの一部としてコンパニオンアセットを含めるには、クラスライブラリにwwwrootフォルダーを作成し、そのフォルダーに必要なファイルを含めます。
RCLをパックすると、wwwrootフォルダー内のすべてのコンパニオンアセットが自動的にパッケージに含まれます。
RCLのwwwrootフォルダーに含まれるファイルは、プレフィックス_content/{LIBRARY NAME} /の下で使用中のアプリに公開されます。たとえば、Razor.Class.Libという名前のライブラリは、_content/Razor.Class.Lib /にある静的コンテンツへのパスになります。
静的アセットをRazorクラスライブラリアセンブリに埋め込む必要があります。それを行う方法を得る最良の方法は、 ASP.NET Identity UIソースコード を確認することだと思います。
アセットを埋め込み、提供するには、次の4つの手順を実行する必要があります。
Razorクラスライブラリのcsprojファイルを編集し、次の行を追加します。
<PropertyGroup>
....
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
....
</PropertyGroup>
<ItemGroup>
....
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.2" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="2.1.1" />
<PackageReference Include="Microsoft.NET.Sdk.Razor" Version="$(MicrosoftNETSdkRazorPackageVersion)" PrivateAssets="All" />
.....
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="wwwroot\**\*" />
<Content Update="**\*.cshtml" Pack="false" />
</ItemGroup>
Razorクラスライブラリで、アセットを提供およびルーティングする次のクラスを作成します。 (アセットがwwwrootフォルダにあると想定しています)
public class UIConfigureOptions : IPostConfigureOptions<StaticFileOptions>
{
public UIConfigureOptions(IHostingEnvironment environment)
{
Environment = environment;
}
public IHostingEnvironment Environment { get; }
public void PostConfigure(string name, StaticFileOptions options)
{
name = name ?? throw new ArgumentNullException(nameof(name));
options = options ?? throw new ArgumentNullException(nameof(options));
// Basic initialization in case the options weren't initialized by any other component
options.ContentTypeProvider = options.ContentTypeProvider ?? new FileExtensionContentTypeProvider();
if (options.FileProvider == null && Environment.WebRootFileProvider == null)
{
throw new InvalidOperationException("Missing FileProvider.");
}
options.FileProvider = options.FileProvider ?? Environment.WebRootFileProvider;
var basePath = "wwwroot";
var filesProvider = new ManifestEmbeddedFileProvider(GetType().Assembly, basePath);
options.FileProvider = new CompositeFileProvider(options.FileProvider, filesProvider);
}
}
Razorクラスライブラリルーターを使用する依存型Webアプリケーションを作成します。 StartupクラスのConfigureServicesメソッドで、次の行を追加します。
services.ConfigureOptions(typeof(UIConfigureOptions));
これで、ファイルへの参照を追加できるようになりました。 (wwwroot/js/app.bundle.jsにあるとしましょう)。
<script src="~/js/app.bundle.js" asp-append-version="true"></script>
.NET Core 3.1では、RCLは_content/{LIBRARY NAME}の下の消費アプリへのwwwrootフォルダー内のアセットを含みます。
RCLプロジェクトプロパティを編集してStaticWebAssetBasePathを配置することにより、_content/{LIBRARY NAME}パスを別のパス名に変更できます。
PropertyGroup>
<StaticWebAssetBasePath Condition="$(StaticWebAssetBasePath) == ''">/path</StaticWebAssetBasePath>
</PropertyGroup>
これで、/ path/test.jsを使用してファイルにアクセスできます。
役立つ情報のEhsanをありがとう。
これは、javascriptとTypeScriptのデバッグを可能にする拡張バージョンで、再コンパイルせずに変更を加えることができます。 TypeScriptのデバッグはChrome=では機能しませんが、IEでは機能します。なぜかわからない場合は、返信を投稿してください。ありがとうございます。
public class ContentConfigureOptions : IPostConfigureOptions<StaticFileOptions>
{
private readonly IHostingEnvironment _environment;
public ContentConfigureOptions(IHostingEnvironment environment)
{
_environment = environment;
}
public void PostConfigure(string name, StaticFileOptions options)
{
// Basic initialization in case the options weren't initialized by any other component
options.ContentTypeProvider = options.ContentTypeProvider ?? new FileExtensionContentTypeProvider();
if (options.FileProvider == null && _environment.WebRootFileProvider == null)
{
throw new InvalidOperationException("Missing FileProvider.");
}
options.FileProvider = options.FileProvider ?? _environment.WebRootFileProvider;
if (_environment.IsDevelopment())
{
// Looks at the physical files on the disk so it can pick up changes to files under wwwroot while the application is running is Visual Studio.
// The last PhysicalFileProvider enalbles TypeScript debugging but only wants to work with IE. I'm currently unsure how to get TS breakpoints to hit with Chrome.
options.FileProvider = new CompositeFileProvider(options.FileProvider,
new PhysicalFileProvider(Path.Combine(_environment.ContentRootPath, $"..\\{GetType().Assembly.GetName().Name}\\wwwroot")),
new PhysicalFileProvider(Path.Combine(_environment.ContentRootPath, $"..\\{GetType().Assembly.GetName().Name}")));
}
else
{
// When deploying use the files that are embedded in the Assembly.
options.FileProvider = new CompositeFileProvider(options.FileProvider,
new ManifestEmbeddedFileProvider(GetType().Assembly, "wwwroot"));
}
_environment.WebRootFileProvider = options.FileProvider; // required to make asp-append-version work as it uses the WebRootFileProvider. https://github.com/aspnet/Mvc/issues/7459
}
}
public class ViewConfigureOptions : IPostConfigureOptions<RazorViewEngineOptions>
{
private readonly IHostingEnvironment _environment;
public ViewConfigureOptions(IHostingEnvironment environment)
{
_environment = environment;
}
public void PostConfigure(string name, RazorViewEngineOptions options)
{
if (_environment.IsDevelopment())
{
// Looks for the physical file on the disk so it can pick up any view changes.
options.FileProviders.Add(new PhysicalFileProvider(Path.Combine(_environment.ContentRootPath, $"..\\{GetType().Assembly.GetName().Name}")));
}
}
}
より簡単な解決策があります。RCLのプロジェクトで、wwwroot
にフラグを付けて、publishディレクトリにコピーすることができます。
<ItemGroup>
<Content Include="wwwroot\**\*.*" CopyToPublishDirectory="Always" />
</ItemGroup>
RCLに依存するアプリをデプロイすると、すべてのファイルに期待どおりにアクセスできます。名前の競合がないように注意する必要があります。
警告:これはAzureにデプロイする場合にのみ機能しますが、ローカルマシンでは機能しません(そのためのプロバイダーが必要です)。
提供されているこのソリューションはサーバー側のアプリケーションでのみ機能することに注意してください。 Blazorクライアント側を使用している場合は機能しません。かみそりクラスライブラリからBlazorクライアント側に静的アセットを含めるには、次のようにアセットを直接参照する必要があります。
<script src="_content/MyLibNamespace/js/mylib.js"></script>
これを理解しようと何時間も無駄にした。これが誰かを助けることを願っています。
私はずっと前にこの問題に達しました。この問題を回避する方法を説明する記事 かみそりライブラリに静的ファイルを含める方法 に従うことができます。
多くの調査の後に私が到達した解決策は、この質問で受け入れられた答えからほど遠くない:
<ItemGroup>
<EmbeddedResource Include="wwwroot\**\*" />
<EmbeddedResource Include="Areas\*\wwwroot\**\*" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>
(リンクされた記事で詳細を見つけることができます この記事 からこの検索を自動化することもできます)
// first we get the Assembly in which we want to embedded the files
var Assembly = typeof(TypeInFeatureAssembly).Assembly;
// we filter only files including a wwwroot name part
filePaths = (from rn in Assembly.GetManifestResourceNames().Where(rnn => rnn.Contains(".wwwroot."))
let hasArea = rn.Contains(".Areas.")
let root = rn.Substring(0, rn.LastIndexOf(".wwwroot.") + ".wwwroot.".Length)
let rootPath = !hasArea ? root : root.Substring(0, root.IndexOf(".Areas."))
let rootSubPath = !hasArea ? "" : root.Substring(root.IndexOf(".Areas.")).Replace('.', '/')
select hasArea ? rootSubPath.Substring(1, rootSubPath.Length - 2) : "wwwroot" )
.Distinct().ToList();
これにより、関連するパスにあるwwwroot
フォルダー内のすべての埋め込みリソースが抽出されます。
var allProviders = new List<IFileProvider>();
allProviders.Add(env.WebRootFileProvider);
allProviders.AddRange(filePaths.Select(t => new ManifestEmbeddedFileProvider(t.Assembly, t.Path)));
env.WebRootFileProvider = new CompositeFileProvider(allProviders);