14
votes

Overview

I've got an ASP.NET Core RC2 .NET framework web project, and I'd like to add a project reference to my regular C# class library contained within the same solution.

Steps to repro:

Using Visual Studio 2015 Update 2

File -> New Project -> ASP.NET Core Web Application (.NET Framework)

Right click solution -> New Project -> Class Library

I'm not making any of these:

  • Class Library (.NET Core)
  • Class Library (Portable for iOS, Android, and Windows)
  • Class Library (Portable)

Add the following to dependencies in project.json:

"ClassLibrary1": {
  "version": "*",
  "target": "project"
}

Issue

Why can I not add "target":"project" to my dependencies when specifying a project dependency?

enter image description here

Expectation

I expect this ASP.NET Core RC2 web application (.NET Framework) to be able to reference a regular class library as a project reference.

This works

"ClassLibrary1": "*"

This does not work

"ClassLibrary1": {
  "version": "*",
  "target": "project"
}

My Question

How do I add a project reference to my regular class library from an ASP.NET Core RC2 web project?

Additional Information

If I run dotnet restore I get a better error message on why this can not be resolved.

dotnet : 
At line:1 char:1
+ dotnet restore
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

Errors in C:\users\joshs\documents\visual studio 2015\Projects\WebApplication4\src\WebApplication4\project.json

    Unable to resolve 'ClassLibrary1' for '.NETFramework,Version=v4.6.1'.

I doubled checked the class library targets .NET Framework 4.6.1

enter image description here

I've already taken a look at cannot add reference to .net core Class library asp.net core rc2, but that's for a .NET Core class library.

I also looked at Reference a Full Framework Library Project from ASP.NET Core MVC Web Application (RC2)?, but that's because the user was trying to create a web project not targeting .NET Framework. My project.json contains:

  "frameworks": {
    "net461": { }
  },

If I right click my web project and 'Add reference' and then proceed to pick my class library, it puts the project dependency in a different part of the project.json, but it still gives me the same error message.

"frameworks": {
  "net461": {
    "dependencies": {
      "ClassLibrary1": {
        "target": "project"
      }
    }
  }
},
3

3 Answers

3
votes

You can reference:

  • A classic C# class library from a project.json targeting full dotnet framework
  • A PCL C# class library from a project.json targeting full dotnet framework and/or CoreCLR

If your C# class library is not PCL then you can only reference it from the full dotnet section (net*) in project.json

To reference from VS, right click on the project -> References -> Select the project

3
votes

Once https://github.com/dotnet/cli/issues/3199 gets resolved, Victor's answer should work. In the meantime, I'm using the following work around:

Overview


Every time I build my class library project, I'm creating a NuGet package with new version numbers. My ASP.NET Core RC2 project.json references that NuGet package as a regular dependency with a wildcard (*) version reference. I then, have my ASP.NET Core RC2 project restore packages after each time it builds, that way it picks up the latest changes.

Solution


Create NuGet Package After Each Build

In your class library project, add a NuGet reference to https://www.nuget.org/packages/CreateNewNuGetPackageFromProjectAfterEachBuild

This will create a folder structure in your project like this:

Create NuGet Package From Project After Each Build folder structure

Edit the Config.ps1 file and change $appendConfigurationAndPlatformToNuGetPackageFileName to $false. (I found my reference wasn't working correctly with this set to $true)

If you want to be able to debug into your class library project, change $packOptions = "" to $packOptions= "-Symbols"

At this point, if you were to build your project, a NuGet package would be created in your output directory (typically bin). This script uses the AssemblyInfo.cs file to drive the version number of the package.

Update AssemblyInfo.cs version

Let's add a script to update that assemblyinfo.cs file version after each build now, and change the location of our NuGet packages to a local repository.

I went and added this script to my project: https://github.com/eoincampbell/powershell-scripts/blob/master/Update-AssemblyFileVersion.ps1 Everytime you call it, it will update the AssemblyInfo.cs version numbers.

I tweaked the script a bit to update the AssemblyFileVersion and AssemblyVersion lines. Change

if ($_.StartsWith("[assembly: AssemblyFileVersion")) {

to

if ($_.StartsWith("[assembly: AssemblyFileVersion") -or $_.StartsWith("[assembly: AssemblyVersion")) {

Build Automation

Now we want this script to happen after each build, that way we don't have to manually run the script each time. Also, I'm going to change the location of the NuGet output of my class library, since I have multiple class library projects in my solution referenced by the ASP.NET Core project.

Edit your class library .csproj file. You'll find something similar to this:

  <PropertyGroup>
    <PostBuildEvent>REM Create a NuGet package for this project and place the .nupkg file in the project's output directory.
REM If you see this in Visual Studio's Error List window, check the Output window's Build tab for the actual error.
ECHO Creating NuGet package in Post-Build event...
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "&amp; '$(ProjectDir)_CreateNewNuGetPackage\DoNotModify\CreateNuGetPackage.ps1' -ProjectFilePath '$(ProjectPath)' -OutputDirectory '$(TargetDir)' -BuildConfiguration '$(ConfigurationName)' -BuildPlatform '$(PlatformName)'"</PostBuildEvent>
  </PropertyGroup>

Add a PreBuildEvent to run your script, and change your -OutputDirectory to a local NuGet repository (should you already have one). Otherwise, you can dump the packages to a shared folder for all class libraries of this solution (which is what I did)

  <PropertyGroup>
    <PreBuildEvent>
      ECHO Starting Pre Build Event
      PowerShell -NoProfile -ExecutionPolicy Bypass -Command "&amp; '$(ProjectDir)_CreateNewNuGetPackage\DoNotModify\Update-AssemblyFileVersion.ps1' -assemblyInfoFilePath '$(TargetDir)..\\..\\Properties\\AssemblyInfo.cs'
    </PreBuildEvent>
    <PostBuildEvent>REM Create a NuGet package for this project and place the .nupkg file in the project's output directory.
REM If you see this in Visual Studio's Error List window, check the Output window's Build tab for the actual error.
ECHO Creating NuGet package in Post-Build event...
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "&amp; '$(ProjectDir)_CreateNewNuGetPackage\DoNotModify\CreateNuGetPackage.ps1' -ProjectFilePath '$(ProjectPath)' -OutputDirectory '$(TargetDir)..\\..\\..\\LocalPackages\' -BuildConfiguration '$(ConfigurationName)' -BuildPlatform '$(PlatformName)'"</PostBuildEvent>
  </PropertyGroup>

If you were to build now, the NuGet packages would be created each time, but your ASP.NET Core application wouldn't pick up the new packages. To resolve, this, I added a pre compile command to dotnet restore.

Note: intellisense is not right, use precompile not prebuild (see https://github.com/dotnet/cli/issues/3338 for more info)

  "scripts": {
    "precompile": "dotnet restore",
    "prepublish": [ "npm install", "bower install", "gulp copy", "gulp clean", "gulp min" ],
  }

ASP.NET Core RC2 project.json

My references are just normal dependencies:

"dependencies": {
    "Microsoft.AspNetCore.Mvc.Core": "1.0.0-rc2-final",
    .
    .
    "Lib.IO": "*",
    "Lib.Core": "*",
    "Lib.Data": "*",
}

Outstanding Issues


  • I haven't bothered writing a script to clean up my NuGet repository, because after a day of coding, I'll find dozens of my class library packages. For now, I just manually clean them out at the end of the day/week.

  • Every time you build ASP.NET Core, it may take quite a while, since your restoring packages prior to every build. If you're really creative, you could execute a script instead to detect if a newer class library package is available, and run dotnet restore then.

  • This is the biggest pain. Every time you make a change to your class library, you must remember to build it, since your web project no longer has a project reference, it won't automatically build your class libraries.

2
votes

I've been fighting similar project reference errors all day today, after working 3 days to convert a solution from RC1 to RC2. Here are some of my findings that may be relevant to this question:

  1. Adding a project reference by editing project.json directly didn't work well, because an ItemGroup->ProjectReference entry needs to be added to the xproj file too, and this only seems to happen when using References -> Add Reference.. -> Select project.
  2. The referenced project name AND its assembly name MUST match (no space characters) in RC2 (this was not an issue in RC1).
  3. I had non-nuget assembly dependencies (added using Browse... button), this did not work in RC2, and the following error was displayed: ".Net Core projects only support referencing .NET framework assemblies in this release. To reference other assemblies, they need to be included in a NuGet package and reference that package.". My solution for RC 2 was to create nuget packages for these assemblies and setup a private nuget server: http://docs.nuget.org/Contribute/Ecosystem#nuget-server-project

BTW, I'm using VS 2015 Update 2. To be clear, these issues are probably due to limitations/bugs in the VS 2015 Tooling/SDK Preview 1 and not issues with ASP Core 1.0 RC2 itself.