Maybe duplicate of this already, but since that post does not have any answer, I am posting this question.
The new Razor Class Library is awesome, but it cannot pack libraries files (like jQuery, shared CSS).
Can I somehow reuse the CSS across multiple Razor Page projects, either using Razor Class Library or anything else (my purpose is that, multiple websites use the same CSS, and a single change applies to all projects).
I have tried creating the folder wwwroot
in the Razor Class Library project, but it does not work as expected (and I can understand why).
You need to embed your static assets into your Razor Class Library assembly. I think the best way to get how to do it is to take a look at ASP.NET Identity UI source codes.
You should take the following 4 steps to embed your assets and serve them.
Edit the csproj file of your Razor Class Library and add the following lines.
<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>
In your Razor Class Library, create the following class to serve and route the assets. (it assumes your assets are located at wwwroot folder)
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);
}
}
Make the dependent web application to use your Razor Class Library router. In the ConfigureServices method of Startup Class, add the following line.
services.ConfigureOptions(typeof(UIConfigureOptions));
So, now you can add a reference to your file. ( let's assume it's located at wwwroot/js/app.bundle.js).
<script src="~/js/app.bundle.js" asp-append-version="true"></script>