Christoph Fink
Christoph Fink

Reputation: 23093

ASP.NET Core Runtime Compilation fails with "Cannot find compilation library location for package" for dynamically loaded Razor Class Library

I am using the following code to dynamically load a Razor Class Library into my ASP.NET Core 3.0 app:

var pluginAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName);
var partFactory = ApplicationPartFactory.GetApplicationPartFactory(pluginAssembly);
foreach (var part in partFactory.GetApplicationParts(pluginAssembly))
    MvcBuilder.PartManager.ApplicationParts.Add(part);

var relatedAssemblies = RelatedAssemblyAttribute.GetRelatedAssemblies(pluginAssembly, throwOnError: true);
foreach (var assembly in relatedAssemblies)
{
    partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly);
    foreach (var part in partFactory.GetApplicationParts(assembly))
        MvcBuilder.PartManager.ApplicationParts.Add(part);
}

This works fine and controllers and views are initially working. But if I also add the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation package and the following to the Startup.cs:

services.Configure<MvcRazorRuntimeCompilationOptions>(options =>
    {
        options.FileProviders.Add(new PhysicalFileProvider(Path.Combine(WebHostEnvironment.ContentRootPath, "..\\AppPlugin")));
    });

I get the following exception as soon as I edit a *.cshtml-file:

InvalidOperationException: Cannot find compilation library location for package 'AppPlugin'

  • Microsoft.Extensions.DependencyModel.CompilationLibrary.ResolveReferencePaths(ICompilationAssemblyResolver resolver, List assemblies)
  • Microsoft.Extensions.DependencyModel.CompilationLibrary.ResolveReferencePaths()

  • Microsoft.AspNetCore.Mvc.ApplicationParts.AssemblyPartExtensions+<>c.b__0_0(CompilationLibrary library)

  • System.Linq.Enumerable+SelectManySingleSelectorIterator.MoveNext()
  • System.Collections.Generic.List.InsertRange(int index, IEnumerable collection)
  • Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.RazorReferenceManager.GetReferencePaths()

  • Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.RazorReferenceManager.GetCompilationReferences()

Is there something else I need to load to get this to work?
If I omit the plugin-path from the FileProviders runtime-compilation works for "non-plugin-views".

Upvotes: 4

Views: 1553

Answers (3)

C&#233;dric SICARD
C&#233;dric SICARD

Reputation: 23

Issue In .net6 when you use both:

  • Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
  • Microsoft.VisualStudio.Web.CodeGeneration.Design

you have the error message:

Cannot find compilation library location for package 'Microsoft.Build'`

Solution Uninstall Microsoft.VisualStudio.Web.CodeGeneration.Design package and you'll be able to use razor runtime compile.

Upvotes: 2

Pavel Anpin
Pavel Anpin

Reputation: 44

If you are still missing references after defining razor runtime compilation as described in other answers and missing types are located in namespaces referenced as global using e.g. global using MyNamespace.Extensions; try to explicitly add your namespaces to _ViewImports.cshtml or directly into view with @using MyNamespace.Extensions

Upvotes: 0

Preston S
Preston S

Reputation: 2771

I was able to get this working by using the following project settings for the razor class library. The key piece was to set PreserveCompilationContext to false.

<Project Sdk="Microsoft.NET.Sdk.Razor">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
    <PreserveCompilationContext>false</PreserveCompilationContext>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

In Addition to this, you'll have to add a reference to your main plugin assembly and any additional assemblies used in your views.

services.Configure<MvcRazorRuntimeCompilationOptions>(options =>
{
    options.FileProviders.Add(new PhysicalFileProvider(Path.Combine(WebHostEnvironment.ContentRootPath, "..\\AppPlugin")));
    opts.AdditionalReferencePaths.Add(pluginAssembly.Location);
});

Upvotes: 5

Related Questions