csproj.net-sdk

Target both .NET Framework 4.8 and .NET 8.0 in SDK project?


I have an application that is an addin to another larger application developed by another company (i.e. I have no control over the parent application). The parent application is updating to .NET 8.0 for their next release but currently is on .NET Framework 4.8. I will need to support this new version but continue supporting old versions for a few years. We have traditionally done this with conditional references in the csproj file. We are now "moving up" to the new SDK project format. I'm trying to get this to work but I'm having trouble crossing the different targets.

I have set up a basic sample for testing by creating a new solution that just has 2 default projects in it with the basic modifications for multi-targeting. Here is the .csproj file content for the referenced library:

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

  <PropertyGroup>
    <TargetFrameworks>net48;net8.0-windows</TargetFrameworks>
    <Configurations>Release2024;Release2025</Configurations>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'Release2025'">
    <TargetFramework>net8.0-windows</TargetFramework>
    <OutputPath>..\Build 2025\</OutputPath>
    <DefineConstants>TRACE;r2025</DefineConstants>
    <Optimize>true</Optimize>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'Release2024'">
    <TargetFramework>net48</TargetFramework>
    <OutputPath>..\Build 2024\</OutputPath>
    <DefineConstants>TRACE;r2024</DefineConstants>
    <Optimize>true</Optimize>
  </PropertyGroup>
</Project>

And here is for the 'top level' project that references that one:

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

  <PropertyGroup>
    <TargetFrameworks>net48;net8.0-windows</TargetFrameworks>
    <Configurations>Release2024;Release2025</Configurations>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'Release2025'">
    <TargetFramework>net8.0-windows</TargetFramework>
    <OutputPath>..\Build 2025\</OutputPath>
    <DefineConstants>TRACE;r2025</DefineConstants>
    <Optimize>true</Optimize>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'Release2024'">
    <TargetFramework>net48</TargetFramework>
    <OutputPath>..\Build 2024\</OutputPath>
    <DefineConstants>TRACE;r2024</DefineConstants>
    <Optimize>true</Optimize>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\TestReferenced\TestReferenced.csproj" />
  </ItemGroup>
</Project>

I then have solution configs that are the same name. The idea is that when I build 'Release2024' everything targets 4.8 and when I build 'Release2025' everything targets 8.0. However, when I try to build Release2025 it tells me:

'..\TestReferenced\TestReferenced.csproj' targets 'net8.0-windows'. It cannot be referenced by a project that targets '.NETFramework,Version=v4.8'. TestLibrary C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets 1860

I know that TestReferenced has the option to reference 4.8, but for that configuration it should target 8.0...

Is there any way to get it to target this way and build correctly?

EDIT I should also mention that I have WPF components in my project that I will need to use.


Solution

  • For anyone else coming along I did end up getting this working. I just set the initial TargeFramework to 8.0 and reset that based on the conditions, something like this (removed extra properties to highlight the differences):

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net8.0-windows</TargetFramework>
        <Configurations>Release2024;Release2025</Configurations>
      </PropertyGroup>
      <PropertyGroup Condition="'$(Configuration)' == 'Release2025'">
        <TargetFramework>net8.0-windows</TargetFramework>
      </PropertyGroup>
      <PropertyGroup Condition="'$(Configuration)' == 'Release2024'">
        <TargetFramework>net48</TargetFramework>
      </PropertyGroup>
      <ItemGroup>
        <ProjectReference Include="..\TestReferenced\TestReferenced.csproj" />
      </ItemGroup>
    </Project>
    

    This seems to allow it to see only the relevant framework for the build configuration and use that one and all seems to work as expected.