Search code examples
c#asp.netasp.net-core.net-coreportable-class-library

PCL - Targetting .NET 4.5.2 and ASPNetCore 1.0


I have a PCL where I target .NET 4.5.2 and ASP.NET Core 1.0, but whenever I reference this PCL from my DotNetCore AspNetCore 1.0 app.

Fix:

Turned out to be an issue with ReSharper, after installing 2017.1 EAP 3, (going from 2016.3) referencing a shared .NET Standard 1.2 project is working perfectly fine!

Question

UPDATE

Managed to get it to compile by changing the Target Framework of my PCL to .NET Framework 4.5 rather than .NET Framework 4.6 (don't ask me why it worked, but would definitely like to find out why).

It is now compiling successfully but my IDE is not resolving references correctly

enter image description here

Original Error

I get a compilation error, saying that it is is not compatible.

  1. Is it possible to have a single PCL targeting .NET 4.5.2 and DotNetCore (not using .NET Standard which is not out yet)
  2. How do you do it?
  3. Can I do this in latest VS 2017 RC? (or should I install VS2015?)

Error Message

enter image description here

PCL Targets

enter image description here

PCL Referenced in AspNetCore

enter image description here

AspNetCore 1.0 Project Setup

enter image description here

.NET Standard Implementations

Reason why I cannot use .NET Standard is highlighted in the following:

enter image description here


Solution

  • In your screenshots you can see that your ASP.NET Core application is targeting NETCoreApp1.0.

    Under NO CIRCUMSTANCES you can use .NET 4.5 libraries in .NET Core. You have to either a library/package which targets netstandard1.x (1.2 in your case, if minimum API is .NET 4.5.1 or 4.5.2) or which targets a compatible PCL (i.e. portable-net45+win8 or similar).

    If you need/have to use a .NET 4.5/4.6 library which doesn't target netstandard1.x, then you must change NETCoreApp1.0 from your ASP.NET Core application (not the PCL) Project settings to .NET Framework 4.5.

    I know, but I would have to target .NET Standard 2.0 which isn't implemented by Core 1.0. Where as according to apisof.net it is referenced System.Data.Common in .Net Core 1.0 but never made the cut into any of the Standards until 2.0!

    But then you can't just run it on Linux/MacOS on .NET Core. This limits you to use your ASP.NET Core application on Windows or Mono on Linux/MacOS.

    Update

    With .NETStandard you can also target net451 and netstandard1.x at the same time and use preprocessing directives to conditionally compile code into one of the assemblies.

    For that you need to create a new "Class Library (.NET Standard)" project and edit project.json (if you are using VS2015) or the csproj (VS2017) to add the targets.

    project.json

      "frameworks": {
        "netstandard1.2": {
          "imports": [
            "dotnet5.6",
            "portable-net45+win8"
          ],
          "dependencies": {
            "Some.NetCore.Only.Dependency": "1.2.3"
          }
        },
        "net451": {
          "dependencies": {
            "Some.Net451.Only.Dependency": "1.2.3"
          }
        }
      },
    

    or csproj file

    <PropertyGroup>
      <TargetFramework>netstandard1.2;net451</TargetFramework>
    </PropertyGroup>
    <ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
      <!-- Framework references -->
      <Reference Include="System.Runtime.Serialization" />
      <!-- Framework references -->
      <PackageReference Include="Some.Net451.Only.Dependency" Version="1.2.3" />
      <!-- Projects within solution references -->
      <ProjectReference Include="My.Domain.Core" Version="1.0.0" />
    </ItemGroup>
    
    <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.2' ">
      <PackageReference Include="Some.NetCore.Only.Dependency" Version="1.2.3" />
    </ItemGroup>
    

    When compiled/packaged it will create two binaries, one for netstandard1.2 and one for net451.

    In code, use your well known #if directives (see here for a list of netstandard directives)

    #if NETSTANDARD1_2
    using Some.NetStandardOnly.Namespace;
    #endif
    using System;
    
    #if NET451
    public DataTable GetDataTable() 
    {
        ...
    }
    #endif