Can Razor Class Library pack static files (js, css

2019-02-17 02:29发布

问题:

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).

回答1:

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.

  1. 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>
    
  2. 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);
        }
    }
    
  3. 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));
    
  4. 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>