【问题标题】:ASP NET Core 2 Cannot find compilation library location for package 'Projectname.Model'ASP NET Core 2 找不到包“Projectname.Model”的编译库位置
【发布时间】:2017-09-18 12:41:42
【问题描述】:

在我的解决方案中,我有两个项目。其中之一是web 项目,另一个是Model 项目。您可以在下面看到我的解决方案结构:

现在当我运行应用程序时出现以下错误:

InvalidOperationException:找不到包“ContosoUniversity.Model”的编译库位置

这是完整的堆栈跟踪:

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

我使用 ASP NET Core 2 和 VS17。

如果您需要,这是我的ContosoUniversity.csproj 文件:

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

我应该怎么做才能解决这个问题?

【问题讨论】:

  • 当我在ConfigureServices 中使用IMvcBuilder 作为参数时,我收到以下错误:The ConfigureServices method must either be parameterless or take only one parameter of type IServiceCollection.

标签: asp.net-core asp.net-core-mvc


【解决方案1】:

为了 asp.net core 2.0 项目成功找到外部程序集 .NETStandard2.0,您需要覆盖内置的 MetadataReferenceFeatureProvider。为此,我们需要添加以下类:

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);
            }
        }
    }
}

并且还用以下代码替换您的启动“services.AddMvc()”:

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

【讨论】:

  • 这使用 ASP.NET Core v1.1.2 为我修复了它。为了匹配原始代码,应该进行额外的检查以确保这不是解析动态程序集的路径。否则,它与 ASP.NET Core 1.1.2 中找到的默认 MetadataReferenceFeatureProvider 代码匹配(当然,除了“引用”库类型的分支)。
  • 要添加上面的代码,只需创建一个新页面并粘贴上面的代码“ReferencesMetadataReferenceFeatureProvider”,或者您可以粘贴到您的启动页面,看看我的答案。
  • 感谢您发布答案
【解决方案2】:

如果您的应用在运行时编译 Razor 代码并且您在 .netcore2+ 中,您似乎需要将其添加到您的项目中:

<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>

这会在发布时复制 refs 文件夹 - 它很大 - 但似乎需要它

【讨论】:

    【解决方案3】:

    为了解决这个问题,你应该像这样在 Startup 构造函数中注入 IServiceProvider:

     public Startup(IConfiguration configuration, IHostingEnvironment env, IServiceProvider serviceProvider)
        {
            Configuration = configuration;
    
            var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
    
            var mvcBuilder = serviceProvider.GetService<IMvcBuilder>();
            new MvcConfiguration().ConfigureMvc(mvcBuilder);
    
            Configuration = builder.Build();
    
        }
    

    【讨论】:

    【解决方案4】:

    您发布的应用程序可能没有引用程序集。尝试设置

    <CopyRefAssembliesToPublishDirectory>true</CopyRefAssembliesToPublishDirectory>
    

    在您应用的项目文件中。

    【讨论】:

      【解决方案5】:

      对我来说,我需要在发布配置文件中选择“在目标位置删除其他文件”才能解决此问题。我们开发团队的另一位成员最近从他们的机器上发布了可能已经考虑在内的内容。

      但是请小心您的项目 - 如果您在服务器上拥有本地没有的资产,它们将被删除(例如用户上传的内容)。

      【讨论】:

        【解决方案6】:

        经过多次尝试,我解决了这个问题。 你只需要改变你的 .csproj 并切换

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

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

        我在 csproj 中添加了其他几行,但我相信这是唯一需要的。

        我还必须在发布之前清理之前生成的文件。

        【讨论】:

          猜你喜欢
          • 2019-05-08
          • 1970-01-01
          • 2018-12-07
          • 1970-01-01
          • 2019-02-26
          • 2017-05-04
          • 1970-01-01
          • 2022-01-11
          • 1970-01-01
          相关资源
          最近更新 更多