.NET 8 migration

.NET 8 migration

amir.dU8TAR
Participant Participant
2,349 Views
7 Replies
Message 1 of 8

.NET 8 migration

amir.dU8TAR
Participant
Participant

Hi,

 

Currently I have completed the migration from .NET 4.8 to .NET 8 and I am able to load and use the migrated project in Revit 2025 but not in older versions.

 

Do I have to use separate project/solution for the purpose of using my code in Revit 2025?

Or in other words, is there a way to use the existing solution without duplicating my code for both cases:

Revit <= 2024

Revit >= 2025

 

Thank you.

0 Likes
Accepted solutions (2)
2,350 Views
7 Replies
Replies (7)
Message 2 of 8

jeremy_tammik
Alumni
Alumni
Accepted solution

Yes, this topic has been discussed and solutions presented both here in this forum and elsewhere, e.g., on GitHub. Have you searched for any of those? I could do so for you, but I am lazy, so I prefer to ask Gemini instead, as I described in my blog. Here is the response I get:

   

Let's tackle this dual .NET framework Revit add-in challenge for Revit 2025 and earlier versions. You're on the right track wanting to avoid code duplication – maintaining two separate projects is a real headache. Here's a breakdown of the best approach, combining best practices and practical examples.

The Core Problem: .NET Version Conflicts

Revit 2025 requires .NET 8, while older versions rely on earlier .NET frameworks (e.g., .NET 4.8 for Revit 2024 and earlier). Directly compiling a .NET 8 add-in won't work with older Revit versions because they lack the necessary runtime.

The Solution: Conditional Compilation and Target Frameworks

The most elegant solution is to use a single project with conditional compilation and multiple target frameworks. This allows you to build one codebase that produces separate DLLs for different Revit versions.

1. Project Setup (Visual Studio)

  • Create a New Revit Add-in Project: Start with a standard Revit add-in project template.
  • Modify the Project File (.csproj): This is where the magic happens. You'll add multiple target frameworks and conditional compilation directives. Here's an example:
XML
 
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>net48;net8.0</TargetFrameworks>  <AssemblyName>MyRevitAddin</AssemblyName>
    <OutputType>Library</OutputType>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo> </PropertyGroup>

  <ItemGroup>
    <Reference Include="RevitAPI">
      <HintPath>$(RevitAPIDLLPath)\RevitAPI.dll</HintPath>  </Reference>
    <Reference Include="RevitAPIUI">
      <HintPath>$(RevitAPIDLLPath)\RevitAPIUI.dll</HintPath>
    </Reference>
    </ItemGroup>

  <PropertyGroup Condition="'$(TargetFramework)' == 'net48'">
    <DefineConstants>REVIT2024_OR_EARLIER</DefineConstants>  <OutputPath>bin\$(Configuration)\$(Platform)\net48\</OutputPath> </PropertyGroup>

  <PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
    <DefineConstants>REVIT2025_OR_LATER</DefineConstants>  <OutputPath>bin\$(Configuration)\$(Platform)\net8.0\</OutputPath> </PropertyGroup>

  </Project>

2. Conditional Compilation in Code

Now, use the defined preprocessor symbols (REVIT2024_OR_EARLIER and REVIT2025_OR_LATER) in your C# code to handle version-specific logic:

C#
 
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
// ... other using statements

namespace MyRevitAddin
{
    public class MyAddin : IExternalApplication
    {
        public Result OnStartup(UIControl application)
        {
            // ... common code

#if REVIT2024_OR_EARLIER
            // Revit 2024 and earlier specific code (e.g., older API calls)
            TaskDialog.TaskDialog.Show("Message", "Running in Revit 2024 or earlier");
#elif REVIT2025_OR_LATER
            // Revit 2025 specific code (e.g., .NET 8 features, new API calls)
            TaskDialog.TaskDialog.Show("Message", "Running in Revit 2025 or later");
#endif

            // ... more common code

            return Result.Succeeded;
        }

        // ... other methods
    }
}

3. Revit API DLL Paths

The crucial part is setting up the $(RevitAPIDLLPath) property. You can do this in a few ways:

  • Environment Variable: The cleanest approach. Set a system environment variable named RevitAPIDLLPath to the directory containing the Revit API DLLs for each Revit version you want to support. Your code will then automatically pick up the correct path.
  • Project Properties: You can define project-level properties in Visual Studio, but this is less flexible.

4. Build Process

When you build your project, Visual Studio will create separate DLLs in the specified output directories (bin\$(Configuration)\$(Platform)\net48\ and bin\$(Configuration)\$(Platform)\net8.0\). You'll then need to distribute the correct DLL to the appropriate Revit version's AddIns folder.

5. Add-in Manifest (for Revit 2025)

For Revit 2025, your add-in manifest file will point to the .NET 8.0 DLL. For older Revit versions, you'll have a separate manifest pointing to the .NET 4.8 DLL. You can automate this process with a post-build event in your project file.

Key Advantages:

  • Single Codebase: Maintainability is vastly improved.
  • Conditional Compilation: Handle version differences elegantly.
  • Organized Output: Separate DLLs for each Revit version.

Addressing Specific Questions:

  • Open Source Template: While there isn't one single "official" template for this, the principles above are the standard approach. Many open-source Revit add-ins use this technique, so examining their .csproj files will be highly beneficial.
  • No Code Duplication: You avoid duplicating your core logic. The conditional compilation handles the small version-specific tweaks.

This detailed approach should give you a robust and maintainable solution for your dual .NET framework Revit add-in. Remember to test thoroughly in all target Revit versions! Let me know if you have any more questions.

    

I hope this helps and leave it up to you to dive in and research deeper if desired or required. Good luck, and please share the final solution that you end up with. Thank you!

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 8

sensiblehira
Advocate
Advocate

can someone create a template for this project and send me please.

0 Likes
Message 4 of 8

sensiblehira
Advocate
Advocate

I could not figure out how to set environment variable properly

0 Likes
Message 5 of 8

mmaso64U7Y
Enthusiast
Enthusiast
Accepted solution

Hi, you can check out this project or that blog that I found on the internet and they were very useful to me.

 

From my experience, it is very handy to define several project configurations containing the Revit year and then use conditionals in the .csproj file like this:

<Choose>
	<When Condition="$(Configuration.Contains('2025'))">
		<PropertyGroup>
			<TargetFramework>net8.0-windows</TargetFramework>
			<RevitVersion>2025</RevitVersion>
			<DefineConstants>$(DefineConstants);REVIT_2025_OR_GREATER;REVIT_2024_OR_GREATER;...</DefineConstants>
		</PropertyGroup>
	</When>
	...

 

Later, you can reuse the Revit version to define the dll locations and where to copy the project output

<ItemGroup>
	<Reference Include="RevitAPI">
		<HintPath>...\Autodesk\Revit $(RevitVersion)\RevitAPI.dll</HintPath>

 

Message 6 of 8

amir.dU8TAR
Participant
Participant

Edit: I found the problem and it was in the conditions within the code I provided.

Your solution seems to work for me, thank you!

 

@jeremy_tammik @mmaso64U7Y 

Thank you guys for trying to help.

 

I am familiar and using configurations & constants in a project, but dealing with .csproj file and multi target frameworks is new to me, so Im probably missing something that im not familiar with.

 

I tried to applying your suggestions regarding the target frameworks by stating <TargetFrameworks>net8.0-windows;net48</TargetFrameworks> at the top of my .csproj file and then conditionally depending on the configuration set <TargetFramework></TargetFramework> in which I state net8.0-windows or net48.

 

now the project does not build for 2025 and still not loading the addin for 2024, what a mess 😀

 

Also, when removing <TargetFrameworks>net8.0-windows;net48</TargetFrameworks> from the first <PropertyGroup> I am not able to build the project at all, an error being thrown saying the the TargetFramework is ''.

 

Im adding the .csproj contents, trying to remove as much unnecessary code such as 2019-20223 configs and assemblies references.

 

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net8.0-windows;net48</TargetFrameworks>
    <OutputType>Library</OutputType>
    <AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <UseWindowsForms>true</UseWindowsForms>
    <UseWPF>true</UseWPF>
    <ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
    <Configurations>Debug;Debug-Revit2019;Debug-Revit2020;Debug-Revit2021;Debug-Revit2022;Debug-Revit2023;Debug-Revit2024;Release;Release-Revit2019;Release-Revit2020;Release-Revit2021;Release-Revit2022;Release-Revit2023;Release-Revit2024;Debug-Revit2025</Configurations>
  </PropertyGroup>
  <PropertyGroup>
    <StartupObject />
  </PropertyGroup>
  <PropertyGroup>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
  </PropertyGroup>
	<!--2024-->
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug-Revit2024|x64' ">
	  <TargetFramework>net48</TargetFramework>
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x64\Debug-Revit2024\</OutputPath>
    <DefineConstants>TRACE;DEBUG;NEW_UNITS;LONG_ID;Selection_Refence,RevitLinkGraphicsSettings</DefineConstants>
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
	<!--2025-->
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug-Revit2025|x64'">
	  <TargetFramework>net8.0-windows</TargetFramework>
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x64\Debug-Revit2025\</OutputPath>
    <DefineConstants>TRACE;DEBUG;NEW_UNITS;LONG_ID;Selection_Refence,RevitLinkGraphicsSettings</DefineConstants>
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
	

 

 

 

0 Likes
Message 7 of 8

jeremy_tammik
Alumni
Alumni

Well, then. Please do not struggle or fight. Go with the flow. Maybe back to the basics, e.g., the blog post:

  

  

That in turn points back to a discussion here in the forum in which several experienced developers share their approaches:

  

  

If your current solution does not work, I would ditch it and take a look at the other suggestions that might just work right out of the box.

  

 

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 8 of 8

MarryTookMyCoffe
Collaborator
Collaborator

I was fighting with similar problem and in the end it was easier to make separate solution and just link cs files.

-------------------------------------------------------------
--------------------------------|\/\/|------------------------
do not worry it only gonna take Autodesk 5 years to fix bug