ASP NET Core 2 Cannot find compilation library location for package 'Projectname.Model'

Viewed 13129

In my solution, I have two projects. One of them is web project and the other one is Model project. You can see my solution structure in below:

enter image description here

Now when I run application I get the following error:

InvalidOperationException: Cannot find compilation library location for package 'ContosoUniversity.Model'

And here is full stack trace :

An unhandled exception occurred while processing the request.
InvalidOperationException: Cannot find compilation library location for package 'ContosoUniversity.Model'
Microsoft.Extensions.DependencyModel.CompilationLibrary.ResolveReferencePaths(ICompilationAssemblyResolver resolver, List<string> assemblies)
InvalidOperationException: Cannot find compilation library location for package 'ContosoUniversity.Model'
Microsoft.Extensions.DependencyModel.CompilationLibrary.ResolveReferencePaths(ICompilationAssemblyResolver resolver, List<string> assemblies)
Microsoft.Extensions.DependencyModel.CompilationLibrary.ResolveReferencePaths()
Microsoft.AspNetCore.Mvc.ApplicationParts.AssemblyPart+<>c.<GetReferencePaths>b__8_0(CompilationLibrary library)
System.Linq.Enumerable+SelectManySingleSelectorIterator.MoveNext()
Microsoft.AspNetCore.Mvc.Razor.Compilation.MetadataReferenceFeatureProvider.PopulateFeature(IEnumerable<ApplicationPart> parts, MetadataReferenceFeature feature)
Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager.PopulateFeature<TFeature>(TFeature feature)
Microsoft.AspNetCore.Mvc.Razor.Internal.DefaultRazorReferenceManager.GetCompilationReferences()
System.Threading.LazyInitializer.EnsureInitializedCore<T>(ref T target, ref bool initialized, ref object syncLock, Func<T> valueFactory)
Microsoft.AspNetCore.Mvc.Razor.Internal.DefaultRazorReferenceManager.get_CompilationReferences()
Microsoft.AspNetCore.Mvc.Razor.Internal.LazyMetadataReferenceFeature.get_References()
Microsoft.CodeAnalysis.Razor.CompilationTagHelperFeature.GetDescriptors()
Microsoft.AspNetCore.Razor.Language.DefaultRazorTagHelperBinderPhase.ExecuteCore(RazorCodeDocument codeDocument)
Microsoft.AspNetCore.Razor.Language.RazorEnginePhaseBase.Execute(RazorCodeDocument codeDocument)
Microsoft.AspNetCore.Razor.Language.DefaultRazorEngine.Process(RazorCodeDocument document)
Microsoft.AspNetCore.Razor.Language.RazorTemplateEngine.GenerateCode(RazorCodeDocument codeDocument)
Microsoft.AspNetCore.Mvc.Razor.Internal.RazorViewCompiler.CompileAndEmit(string relativePath)
Microsoft.AspNetCore.Mvc.Razor.Internal.RazorViewCompiler.CreateCacheEntry(string normalizedPath) 
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.Razor.Internal.DefaultRazorPageFactoryProvider.CreateFactory(string relativePath)
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine.CreateCacheResult(HashSet<IChangeToken> expirationTokens, string relativePath, bool isMainPage)
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine.OnCacheMiss(ViewLocationExpanderContext expanderContext, ViewLocationCacheKey cacheKey)
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine.LocatePageFromViewLocations(ActionContext actionContext, string pageName, bool isMainPage)
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine.FindView(ActionContext context, string viewName, bool isMainPage)
Microsoft.AspNetCore.Mvc.ViewEngines.CompositeViewEngine.FindView(ActionContext context, string viewName, bool isMainPage)
Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor.FindView(ActionContext actionContext, ViewResult viewResult)
Microsoft.AspNetCore.Mvc.ViewResult+<ExecuteResultAsync>d__26.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeResultAsync>d__19.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResultFilterAsync>d__24.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()

I use ASP NET Core 2 and VS17.

Here is my ContosoUniversity.csproj file if you need it:

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

<PropertyGroup>
  <TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
  <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.0" />
</ItemGroup>

<ItemGroup>
  <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>

<ItemGroup>
  <Reference Include="ContosoUniversity.Model">
    <HintPath>..\ContosoUniversity.Model\bin\Debug\netcoreapp2.0\ContosoUniversity.Model.dll</HintPath>
  </Reference>
</ItemGroup>

</Project>

What should I do to solve this problem?

6 Answers

In order asp.net core 2.0 project had successfully found external assemblies .NETStandard2.0, you need to override a built-in MetadataReferenceFeatureProvider. For this we need to add the following class:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.PortableExecutable;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.DependencyModel;

namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
{
    /// <summary>Провайдер нужен для компенсации бага компиляции представлений при подключении сборок .NetStandart2.0</summary>
    public class ReferencesMetadataReferenceFeatureProvider : IApplicationFeatureProvider<MetadataReferenceFeature>
    {
        public void PopulateFeature(IEnumerable<ApplicationPart> parts, MetadataReferenceFeature feature)
        {
            var libraryPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
            foreach (var assemblyPart in parts.OfType<AssemblyPart>())
            {
                var dependencyContext = DependencyContext.Load(assemblyPart.Assembly);
                if (dependencyContext != null)
                {
                    foreach (var library in dependencyContext.CompileLibraries)
                    {
                        if (string.Equals("reference", library.Type, StringComparison.OrdinalIgnoreCase))
                        {
                            foreach (var libraryAssembly in library.Assemblies)
                            {
                                libraryPaths.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, libraryAssembly));
                            }
                        }
                        else
                        {
                            foreach (var path in library.ResolveReferencePaths())
                            {
                                libraryPaths.Add(path);
                            }
                        }
                    }
                }
                else
                {
                    libraryPaths.Add(assemblyPart.Assembly.Location);
                }
            }

            foreach (var path in libraryPaths)
            {
                feature.MetadataReferences.Add(CreateMetadataReference(path));
            }
        }

        private static MetadataReference CreateMetadataReference(string path)
        {
            using (var stream = File.OpenRead(path))
            {
                var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
                var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);

                return assemblyMetadata.GetReference(filePath: path);
            }
        }
    }
}

And also replace in your Startup "services.AddMvc()" with the following code:

services.AddMvc() // Следующий патч нужен для компенсации бага компиляции представлений при подключении сборок .NetStandart2.0
    .ConfigureApplicationPartManager(manager =>
    {
        manager.FeatureProviders.Remove(manager.FeatureProviders.First(f => f is MetadataReferenceFeatureProvider));
        manager.FeatureProviders.Add(new ReferencesMetadataReferenceFeatureProvider());
    });

If your app is compiling Razor code in runtime and you are in .netcore2+ it seems you need to add this to your project:

<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>

This copies the refs folder on publish - it is large - but it seems to be needed

It's likely that you are publishing the app without reference assemblies. Try setting

<CopyRefAssembliesToPublishDirectory>true</CopyRefAssembliesToPublishDirectory>

in your app's project file.

For me I needed to choose "Remove additional files at destination" in the publish profile for this to resolve. Another member of our dev team had recently published from their machine which may have factored in.

Be careful with your project however - if you have assets on the server you don't have locally, they will get deleted (user uploaded content for example).

Publish Profile

I solved this issue after many attempts. You just need to change your .csproj and switch

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

with

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

I have added few other lines in the csproj, but I believe this is the only one that is required.

Also I had to clean the previously generated files before publishing.

Related