Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Referencing Framework 4.6 Library in in .NET Core App 1.0.0 project

I'm been investigating options available to me for referencing existing .NET Framework 4.6 libraries in new .NET Core App projects.

As a proof of concept I've built a very simple .NET Framework 4.6 library, published it as a NuGet package and included it in a simple .NET Core Web app.

As of now the only way I seem to be able to get the project building and running is to remove the Microsoft.NETCore.App reference from the project.json dependencies block and replace the netcoreapp1.0 section from the frameworks property with a net461 block.

Full project.json below:

{
  "dependencies": {
    /*"Microsoft.NETCore.App": {
      "version": "1.0.0",
      "type": "platform"
    },*/
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "FileIOLibrary_1_0_0_0": "1.0.0"
  },

  "tools": {
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
  },

  /*"frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8",
        "net461"
      ]
    }
  },*/

  "frameworks": {
    "net461": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "runtimeOptions": {
    "configProperties": {
      "System.GC.Server": true
    }
  },

  "publishOptions": {
    "include": [
      "wwwroot",
      "web.config"
    ]
  },

  "scripts": {
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

This basically means that all references are .NET Framework 4.6 libraries.

Anyway I've a few questions regarding other options available to me:

  1. Is it possible to specify that only my imported library should be targeted towards the .NET 4.6 Framework and all other references should use .NET core? If so this would mean I could add the the Microsoft.NETCore.App reference back into the project.
  2. If the above is not possible can I rebuild my library as a compatible .NET standard library (I believe version 1.6 is compatible between Framework 4.6 and Core 1.0.0)? I've been unable to see an option in Visual Studio to allow me to build libraries against the .NET Standard so would appreciate some pointers in this direction if its an option.
like image 399
kh25 Avatar asked Sep 27 '16 09:09

kh25


Video Answer


1 Answers

I'm afraid you cannot load a .NET 4.6.2 DLL into a .NET Core application.

The alternative plan

In some circumstances, you can write the code once and then have a project for .NET 4.6.2 and a project for .NET Core. Both projects point at the same code files but each project has a different framework target. Once you have that working, you can build a nuget package that has both the .NET 4.6.2 DLLs and the .NET Core DLLs in it, which will make deployment and build much simpler.

How to get the same code files building for each framework

Assuming you have a MyProject.csproj in a folder ./NET462/MyProject/ and a solution MySolution.sln.

  1. First create an empty .NET Core Library. We'll call it MyProject.Core and we'll put it in ./Core/MyProject.Core/. We'll also have a Solution too, call that ./Core/MySolution.Core.sln.
  2. Now copy all the files from the original ./NET462/MyProject/ into ./Core/MyProject, including the .csproj. Copy the solution too, they're going to live side-by-side.
  3. If you load the original solution right now then Visual Studio will throw errors because there will be a conflict between the project.json (which is used by the Core project) and the .csproj (which is used by the .NET 4.6.2 project).
  4. To stop that, create a new file called MyProject.project.json. This acts as a companion to the project.json when the .NET 462 project is loaded. Put the following into it:

MyProject.project.json

{
    "version": "1.0.0-*",
    "description": "My Class Library",
    "authors": [
      "Your Name"
    ],
    "tags": [
      ""
    ],
    "projectUrl": "",
    "licenseUrl": "",
    "runtimes": {
      "win": {}
    },
    "frameworks": {
      "net452": {} // You might want net462
    },
    "dependencies": { 
      "Newtonsoft.Json": "9.0.1" /// Just an example of a nuget package
    }
  }
  1. Your .NET 4.6.2 project should now build just as before.
  2. Now open the Core solution (it's OK to have both Visual Studios open at the same time) and you'll see that all the files are added in there. Under .NET Core / xproj, Project.json files are include-by-default. You will need to ignore the files specific to .NET 462, which are the .csproj and MyProject.project.json.
  3. It probably won't build until you get the nuget packages added.

How to get .NET Core and .NET into the same Nuget

  1. Once each solution is built in Release mode, you will have two outputs, a DLL for each of the frameworks. You can change the name of the DLLs in the project files (.csproj and project.json respectively) but nuget doesn't care.
  2. Create a package.nuspec file and put the following in it:

    <!-- language: lang-xml -->
    <?xml version="1.0"?>
    <package>
      <metadata>
        <id>MyProject</id>
        <version>1.0.0</version>
        <authors>Me</authors>
        <owners>Me</owners>
        <projectUrl></projectUrl>
        <iconUrl>FILL ME IN</iconUrl>
        <description>FILL ME IN</description>
        <copyright>FILL ME IN</copyright>
        <releaseNotes>First attempt</releaseNotes>
        <tags>FILL ME IN</tags>
        <dependencies>
          <group targetFramework="dotnet">
            <dependency id="Newtonsoft.Json" version="9.0.1" />
          </group>
          <group targetFramework="net452">
            <dependency id="Newtonsoft.Json" version="9.0.1" />
          </group>
        </dependencies>
        <frameworkAssemblies>
          <frameworkAssembly assemblyName="System.Core" targetFramework="net452"/>
          <frameworkAssembly assemblyName="System.Core" targetFramework="dotnet" />
        </frameworkAssemblies>
      </metadata>
      <files>
        <file src="Core\MyProject\bin\release\MyProject.dll" target="lib/net452" />
        <file src="Core\MyProject\bin\release\MyProject.Core.dll" target="lib/dotnet" />
      </files>
    </package>
    
  3. Use this to build your nuget package and when including in your main system, nuget will serve the correct package.

Bigger Example

My JsonApi library does this and additionally it has two Web projects, one for .NET 4.6.2 and one for .NET Core because they use different base classes. The main shared library is used by both.

Big caveat

Some libraries that your .NET 4.6.2 rely upon will not be available to your Core application. The two times I've done this it has been System.Web that has caught me out. System.Web in .NET 4.6.2 is really a wrapper for IIS. The best way to find out is to try merging the projects above and keep adding nuget packages to project.json until you hit something that doesn't exist for Core.

Things are changing

The .NET team in May 2016 said that they were moving away from using the project.json at the end of 2016. At which point, I imagine that these problems might go away as visual studio should be able to handle two kinds of .csproj living side by side. Depending on your commercial situation, I'd wait for that change!

like image 123
Dr Rob Lang Avatar answered Oct 12 '22 12:10

Dr Rob Lang