Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Optimal add-in code base approach to target multiple Revit releases

23 REPLIES 23
Reply
Message 1 of 24
jeremy_tammik
3895 Views, 23 Replies

Optimal add-in code base approach to target multiple Revit releases

Dear Revit API add-in developers,

 

Is there a common or typical approach that third-party add-in developers use to have one code base that builds add-ins for many Revit releases? 

 

If yes, can you please share an example?

 

Motivation: The next major release of the Revit API may target a different .NET development environment than Revit 2024. Therefore, the Revit development team would like to make an example application that multi-targets them both to demonstrate how one code base can build both add-ins. The goal will be to help customers supporting many Revit releases with one body of code.

 

Jeremy suggested: That sounds like a great idea and a very useful undertaking. Yes, there are numerous samples floating around illustrating various approaches to this. One problem might be to selecting the best choice. Here are a few that The Building Coder picked up:

 

 

There are several more mentioned in the Revit API discussion forum and shared in various GitHub projects; searching the former for multi brings up one or two:

 

 

Some of the Revit templates on GitHub also support multi-version compilation:

 

 

Which approach do you prefer to implement a Revit add-in code base targeting multiple Revit releases?

 

Thank you!

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
23 REPLIES 23
Message 2 of 24

For my Drafter https://w7k.pl/tools/drafter/ (Revit 2020 to 2024) I am using a mix of things which are floating around internet:

  1. Adding correct reference for Revit API;

    JulianWandzilak_0-1706877446369.jpeg

     

  2. Adding proper paths for correct debugging:
    JulianWandzilak_1-1706877446384.jpeg

     

  3. Post-build event to copy things to correct locations:
    JulianWandzilak_2-1706877446387.jpeg

     

  4. Regarding using different frameworks so far, I'm using only v4.8.1 as it is fairly backward-compatible with Revit 2020.

 

For coding I am simply using: 

#if RELEASE2020 || RELEASE2021 

#endif

with proper versions. 

 

So far everything works pretty well. It takes only a second to change the Revit version and deploy it. And it allows to find potential problems with compatibility fairly easy. 

 

I created for myself a templates project which I am using right now to create a new projects. It also has links to my separate shared projects where I keep most of my reusable classes and methods. I found it a really good way to keep things tidy (even after 200 separate buttons I already published 😉 ).

 

Frankly speaking I am a little bit afraid with incoming .net 8 and how it will affect my setup: 
I recently viewed a great video by @ricaun showing how to migrate to .Net

Link below:

https://youtu.be/EysAn87iqWo?si=ZYFg2VOSD00rGbIH

After watching this video, I hope I will be able to migrate to .net 8 similarly with just adding proper <TargetFramework>. Still, I am more than sure I will come to this forum with plenty of questions 😉

blog: w7k.pl more about me: Linkedin Profile
My add-ins for Revit: Drafter(180+ scripts) & Leveler
Message 3 of 24
Kennan.Chen
in reply to: jeremy_tammik

After experimenting with various approaches, I personally find that using a Shared Project to target multiple frameworks is preferable. I believe it is the official solution provided by Visual Studio for building to multiple targets with only one code base.

Message 4 of 24
RPTHOMAS108
in reply to: jeremy_tammik

To be honest doesn't all of this depend on target audience i.e. if this is for something similar to 'my first plugin' then it should be just 'my second plugin' (updated solution file targeting .net).

 

As much as we all like conditional statements and solution files with various build configurations someone starting out just needs to know about current situation, if they care about history we can all revisit that. Isn't it really true that the kind of developer considering mufti-targeting is probably someone that doesn't need examples of how to do it i.e. a commercial developer. 

 

Personally after years of just updating the solution file I tried multi targeting approaches but I just found myself contaminating old code with new changes. Perhaps that always inevitably happens as the common code we should be leaving alone becomes something we want to improve or in reality the common code between versions is like common sense (not that common). Obviously if my solution files had vast quantity of source files within a project I would perhaps opt for multi targeting over just upgrading solution but for my personal situation the former just seems not required.

 

Tasks are quite an interesting feature

For example I made a dll file that replaced all the strings  in a template add-in file. There are probably other ways of doing this but it was a good experiment. It got to the point where all I had to do was add the new configuration name for the Revit version and everything was dealt with in terms of references, .addin manifest etc.

 

 

 <UsingTask TaskName="RTBuildTasks.StringsInFileReplace" AssemblyFile="..\..\RTBuildTasks\RTBuildTasks\bin\Release\netstandard2.0\RTBuildTasks.dll"></UsingTask>

<RTBuildTasks.StringsInFileReplace TxtTemplateFilePath="$(ProjectDir)AddInManifest.addin" DestinationFilePath="C:\ProgramData\Autodesk\Revit\Addins\$(RevitVersion)\$(ProjectName).addin" UniqueLabels="{AssemblyPath}" LabelReplacements="$(TargetPath)">

 

 

Message 5 of 24
michaelmorris
in reply to: Kennan.Chen

Hi @Kennan.Chen ,

 

When you say you are using a shared project, do you mean a ".shproj" like this?

 

Thanks,

Michael

 


Michael Morris
Software Engineer
Message 6 of 24
jeremy_tammik
in reply to: RPTHOMAS108

in reality the common code between versions is like common sense (not that common).

  

That made me laugh out loud. Unfortunately, you are so right. Regarding the common sense, at least. And it's getting worse day by day, isn't it?

  

In my simple samples, the amount of common code is often huge, 90% or even 99%.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 7 of 24

Hi everyone,

 

As an illustration of how Revit addin developers could support three versions of Revit and two versions .NET with common code, I wrote an evolution of the Autodesk “My First Revit Plug-in” (attached).

 

The basic structure is this:
* There are three csproj files, one for each supported version of Revit.

* The csproj files specify the .NET target version (to match Revit) and define constants that can be used to modify behavior for specific Revit or .NET releases.

* A shproj project contains the shared C# code for the addin.  (In this simple example, all the code is shared.)

michaelmorris_0-1707238131040.png

 

While the example works, it is a lot less elegant or comprehensive than the multiversion-revit-plugin-sample in github.  The multiversion-revit-plugin-sample uses conditional logic in one csproj to support many releases of Revit/.NET.  It also does nice tricks like filling out the .addin files for each supported release.

 

At this point, I'm not sure my "My First Revit Plug-in" example improves upon the multiversion-revit-plugin-sample.  Perhaps sharing an updated version of multiversion-revit-plugin-sample with developers who need to support many Revit/.NET versions is the best approach?

 

Thoughts?

 

Best,

Michael


Michael Morris
Software Engineer
Message 8 of 24
RPTHOMAS108
in reply to: michaelmorris

Looks like a good compromise between something understandable to beginner and full multi-targeting approach. One could say difference between 2023 and 2024 is insignificant, in fact probably the build results of 2024 version would also likely work in 2023 anyway i.e. cycle is often two years so if we were really trying to minimise our work we would only create a new solution every other year (unless two year cycle is changing?). I'm a strong believer in my interpretation of the phase 'action through in-action'. 

 

@jeremy_tammik I think your high percentage volume of common code shows you are far more organised than I.  I've lost count of how many times I written code for a collector that collects something, often the same type of something I've collected many times before or the number of times I've implemented ISelectionFilter exactly the same way. I think sometimes it is easier to just write it out again rather than find what I did for it previously.

Message 9 of 24
michaelmorris
in reply to: RPTHOMAS108

Yes, you are right that the code for R2024 would have built fine against R2023. 

 

I was looking for something in the My First Revit Plug-in code that changed its API in a recent release, and the change of ElementIds from 32-bit to 64-bit is what I found.  🙂

 


Michael Morris
Software Engineer
Message 10 of 24
RPTHOMAS108
in reply to: michaelmorris

Yes the change to ElementId is a good one but in practice if you never used the integer value from it then you should never really notice the change. Someone asked the question long ago why ElementId existed and they didn't just use the Integer value type for it (shows forward thinking that this wasn't the design choice). So if we stop thinking of ElementId as Int32 or Int64 then it has always just been ElementId. It is rare that we have to use the underlying number or create an ElementId from it but it does happen sometimes.

Message 11 of 24
ricaun
in reply to: RPTHOMAS108

Hello everyone,

 

One configuration for each Revit version is the easiest way to create a multi-version plugin. One configuration for Debug and one for Release for each version. (Debug 2021;2021;Debug 2022;2022;Debug 2023;2023;Debug 2024;2024;Debug 2025;2025...)

 

The csproj has all the settings to select the Revit API reference, target framework, and other configurations for the project.

 

With some automation is possible to build all the configurations that do not have 'Debug' in the name, create the .addin, .bundle, and the installation.

 

All my projects use this approach, like in the video already shared by @Julian.Wandzilak: https://youtu.be/EysAn87iqWo?si=fMGUjhohRX0vaswL

 

And here is the RevitAddin.CommandLoader project/csproj that I'm planning to update to Revit 2025/NET 8.0 in a live on YouTube.


I hope I'm not gonna be in trouble for sharing that.

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 12 of 24
jeremy_tammik
in reply to: ricaun

Dear Ricaun, 

  

Thank you for your extremely valuable input. I hope so too. Maybe avoid mentioning the number '2025' and just say something like 'potential future release with API possibly based on .NET Core' instead...

  

Cheers

  

Jeremy

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 13 of 24

I wrote Drafter in revit 2024. In the end while checking the code in previous versions I had to lock a number of tools helping with title lines, tags and legends - mostly for the users of 2020, 2021 and a little bit of 2022.

 

Nothing that could be solved - Simply these part of Revit were not open to the Revit API.

 

Except that, nothing serious to do. ElementIds were simple to solve. 

blog: w7k.pl more about me: Linkedin Profile
My add-ins for Revit: Drafter(180+ scripts) & Leveler
Message 14 of 24
Kennan.Chen
in reply to: michaelmorris

Yes.

 

I used the Visual Studio shared project to distribute code for a Revit family library project across multiple platforms. In addition, I created an abstract layer between the Revit API and my business logic to enable decoupling. This allowed for the dynamic loading of the appropriate DLL file corresponding to the current running Revit version. When a new Revit version is released, I only need to create a new implementation of the abstraction layer, reference the shared project to access all the code, and manage the changes through conditional compilation.

Message 15 of 24
EvanGeer
in reply to: jeremy_tammik

Wow! Lots of great ideas here. I'm excited to see lots of folks are thinking about this especially as 2025 is on the horizon. 

 

I just wrote a blog the details out my preferred approach step-by-step: 

https://levelup.gitconnected.com/multi-year-revit-addin-a-better-way-54ef441b5b4b

EvanGeer_1-1711484233933.png

 

The gist is to use features of the newer sdk-style .csrpoj files:

  1. Create abstract base .csproj
  2. Import that .csproj into year-specific files that only include the stuff needed for those years
  3. All .cs files are automatically included in subfolders
  4. Any file added to any project is automatically added to all projects

 

In the end, you end up with X (one per year you support) number of projects that look like this:

 

<Project>
  <PropertyGroup>
    <RevitYear>2021</RevitYear>
    <TargetFramework>net481</TargetFramework>
  </PropertyGroup>

  <!-- The base project should contain all the stuff that's the same between projects -->
  <Import Project="SampleProject.csproj" />
</Project>

 

 

And one project that looks like this:

 

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

  <!-- Configurations/Defined Pre-compiler Flags -->
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DefineConstants>$(DefineConstants);RV$(RevitYear)</DefineConstants>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <DefineConstants>$(DefineConstants);RV$(RevitYear)</DefineConstants>
  </PropertyGroup>

  <!-- Revit API References -->
  <!-- ToDo: update to your project path -->
  <ItemGroup>
    <Reference Include="AdWindows">
      <HintPath>dependencies\$(RevitYear)\AdWindows.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RevitAPI">
      <HintPath>dependencies\$(RevitYear)\RevitAPI.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RevitAPIUI">
      <HintPath>dependencies\$(RevitYear)\RevitAPIUI.dll</HintPath>
      <Private>False</Private>
    </Reference>
  </ItemGroup> 

</Project>

 

 

The result is that you can use preprocessor directives to control which code is executed:

 

EvanGeer_0-1711484155311.gif

 

Evan Geer
evangeer.com
Message 16 of 24
nice3point
in reply to: jeremy_tammik

@jeremy_tammik I am announcing a new version of my templates with the Revit 25 release, it will have all things you need and support for Revit 2020-2025. Stay tuned

Message 17 of 24
jeremy_tammik
in reply to: EvanGeer

Cool. I am a great fan of combining all repetitive stuff in one place, and splitting out the essentials only. Thank you for mentioning it here and for your extensive blog post documenting the rationals and how to set it up.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 18 of 24
jeremy_tammik
in reply to: nice3point

Cool again! Thank you for sharing. Looks like the community will be well prepared, whatever comes.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 19 of 24
nice3point
in reply to: jeremy_tammik

@jeremy_tammik 

What's great about my templates is that they work in any IDE, support as many versions of Revit as you want in one solution, and contain many development options. https://github.com/Nice3point/RevitTemplates/wiki/Templates

What's wrong with 95% of the other variants? Because either they are only supported in VS, don't contain any customisation or are sample code, which implies copying. They are also written by beginners developers and engineers, not programmers. My version is fully automated. If Autodesk needs really high quality templates, write me an email or wait for the next version of Revit to be released

Message 20 of 24
spacefrog_
in reply to: nice3point

Whoa... just stumbled over your nice github repos

Seems to be a treasure trove for me as i'm just busy doing ( and learning ) Revit addin development


Josef Wienerroither
Software Developer & 3d Artist Hybrid

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report