revit-api
Skill1 starsChanged 2 months agoMITView on GitHub
Sviluppo avanzato di add-in, comandi e plugin BIM per Autodesk Revit in C# (.NET 10, .NET 8 e .NET Framework 4.8). Usare per IExternalCommand, IExternalApplication, Ribbon UI, transazioni e TransactionGroup, FilteredElementCollector ottimizzati, IExternalEventHandler/ExternalEvent asincroni, IUpdater, FailureHandling, add-in isolation di Revit 2027 e migrazione ForgeTypeId/ElementId a 64 bit.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- Hopesy/skillstheir own version, first seen Nov 4, 2026
- Hopesy/skillhubtheir own version, first seen Oct 20, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- Hopesy/skillhub★ 2same name
- Hopesy/skills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository34 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- construction-sequencingSkill
- materials-traceabilitySkill
- quantities-cost-linkingSkill
- aim-constructionSkill
- digital-twin-analyticsSkill
- maintenance-cmmsSkill
- grasshopperSkill
- pyrevitSkill
- revit-cpp-pluginSkill
- revit-dynamoSkill
- rhino-inside-revitSkill
- rhinoSkill
- cde-configurationSkill
- cde-cybersecuritySkill
- cde-workflowSkill
- bim-executionSkill
- construction-supervision-handoverSkill
- information-delivery-planningSkill
- information-protocolSkill
- safety-coordination-bimSkill
- sgpd-management-systemSkill
- clash-detectionSkill
- e-permit-complianceSkill
- gis-bim-georeferencingSkill
- ifc-loin-validatorSkill
- infrastructure-ifc-linearSkill
- naming-spatial-structureSkill
- normative-code-checkingSkill
- ci-draftingSkill
- ogi-evaluationSkill
- pgi-consolidationSkill
- project-validation-auditSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 383
ContextName: add-in installati in cartelle diverse ma con lo stesso ContextName vengono caricati nello stesso contesto.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
BIM Revit API Architecture & C# Add-In Engineering
Guida specialistica di riferimento per lo sviluppo professionale di add-in, estensioni e plugin per Autodesk Revit in linguaggio C# (.NET). Copre le migliori pratiche architetturali, la gestione delle transazioni, la manipolazione ad alte prestazioni dei modelli tramite FilteredElementCollector, le interfacce utente Ribbon, la gestione asincrona multithreading con ExternalEvent e i cambiamenti architetturali cruciali introdotti nelle versioni più recenti (migrazione a .NET 8 in Revit 2025/2026, a .NET 10 in Revit 2027, add-in isolation, ElementId a 64 bit e sistema ForgeTypeId).
Scope
Questa skill fornisce pattern architetturali, frammenti di codice riutilizzabili e best practice per:
- Architettura di Add-In: implementazione di
IExternalCommand(esecuzione sincrona),IExternalApplication(registrazione Ribbon e lifecycle di avvio/chiusura) e manifest.addin. - Evoluzione del Runtime (.NET Framework 4.8, .NET 8, .NET 10): supporto alla compilazione moderna con SDK-style
.csprojper Revit 2024-2027. - Add-In Isolation (Revit 2027): dichiarazione esplicita di contesto, assembly pubblici e dipendenze fra add-in per evitare conflitti di risoluzione degli assembly.
- Gestione Transazionale Avanzata:
Transaction,SubTransactioneTransactionGroupcon assimilazione delle modifiche (Assimilate()) in un singolo punto di Undo. - Querying ad Alte Prestazioni (
FilteredElementCollector): filtri rapidi nativi C++ a livello database, filtri lenti, e inversione della dipendenza LINQ per evitare memory leak. - Manipolazione dei Parametri e Sistema di Misura: gestione dei parametri Built-In, parametri di progetto e parametri condivisi (Shared Parameters); conversione di unità tramite
UnitUtilseForgeTypeId(superamento definitivo diDisplayUnitType). - Supporto al Nuovo Sistema ElementId (Int64 / Long): adozione di
ElementId.Valuee costruttori a 64 bit introdotti da Revit 2024. - Programmazione Asincrona e UI Non Modale: implementazione di
IExternalEventHandleredExternalEventper interfacciare finestre WPF o chiamate HTTP/REST esterne senza bloccare l'interfaccia di Revit. - Gestione Automatica degli Errori e Warning (Failure Handling): implementazione di
IFailuresPreprocessorper sopprimere messaggi bloccanti e warning durante elaborazioni batch non presidiate. - Reattività del Modello (Dynamic Model Update - DMU): implementazione di
IUpdatere registrazione dei trigger di modifica elementi conUpdaterRegistry.
NON fa
- Non genera codice legacy incompatibile per versioni obsolete di Revit (es. 2018-2021) salvo esplicita richiesta dell'utente.
- Non esegue chiamate dirette all'API di Revit da thread secondari non sincronizzati (violazione del modello single-thread di Revit).
- Non modifica il modello geometrico in assenza di una transazione aperta e attiva.
Matrice Compatibilità e Breaking Changes (Revit 2022 - 2027)
| Versione Revit | Target Framework .NET | Gestione Unità di Misura | Tipo ElementId | SDK Style Project File |
| Revit 2022 | .NET Framework 4.8 | ForgeTypeId / UnitTypeId | int (32 bit) | Opzionale |
| Revit 2023 | .NET Framework 4.8 | ForgeTypeId / UnitTypeId | int (32 bit) | Opzionale |
| Revit 2024 | .NET Framework 4.8 | ForgeTypeId / UnitTypeId | long (64 bit - ElementId.Value) | Consigliato |
| Revit 2025 (fino a 2025.4) | .NET 8.0 (CoreCLR) | ForgeTypeId / UnitTypeId | long (64 bit - ElementId.Value) | Obbligatorio |
| Revit 2026 (fino a 2026.4) | .NET 8.0 (CoreCLR) | ForgeTypeId / UnitTypeId | long (64 bit - ElementId.Value) | Obbligatorio |
| Revit 2025.5 / 2026.5 | .NET 10 (CoreCLR) | ForgeTypeId / UnitTypeId | long (64 bit - ElementId.Value) | Obbligatorio |
| Revit 2027 | .NET 10 (CoreCLR) | ForgeTypeId / UnitTypeId | long (64 bit - ElementId.Value) | Obbligatorio |
[!IMPORTANT] Migrazione a .NET 8 (Revit 2025+): Da Revit 2025 non è più possibile utilizzare .NET Framework. Il progetto
.csprojdeve essere configurato con:<TargetFramework>net8.0-windows</TargetFramework>e<EnableDynamicLoading>true</EnableDynamicLoading>. Per le API ElementId, la proprietàIntegerValueè deprecata e sostituita daValue(tipolonga 64 bit).
[!IMPORTANT] Migrazione a .NET 10 (Revit 2027 e update .5 del 2025/2026): Il runtime non dipende solo dall'anno: Revit 2025.5 e 2026.5 girano gia su .NET 10 (Revit 2026.5 rilasciato ad agosto 2026), mentre gli update precedenti degli stessi anni restano su .NET 8. Un installer o un loader che sceglie il runtime in base al solo anno di Revit sbaglia bersaglio: leggere il numero di update/build. Gli add-in compilati per .NET 8 in genere continuano a funzionare su .NET 10, ma vanno verificati i casi di rottura: API rimosse in .NET 10, dipendenze NuGet transitive ferme a .NET 8, caricamento assembly, reflection, serializzazione e interop nativa. Per una migrazione piena, ricompilare contro l'SDK .NET 10 (
<TargetFramework>net10.0-windows</TargetFramework>) e fissare la toolchain con unglobal.json:{ "sdk": { "version": "10.0.100", "rollForward": "minor" } }Rimozioni e deprecazioni della release (import AXM di FormIt, membri di
Mechanical.Zone, metodi legacy di creazione dei ferri d'armatura, alcune proprietà diEnergyDataSettings) vanno verificate sulla documentazione SDK della versione prima della migrazione.
Configurazione del Progetto Moderno (.csproj SDK-Style per Revit 2025)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<Platforms>x64</Platforms>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<!-- Necessario per isolare le dipendenze in CoreCLR -->
<EnableDynamicLoading>true</EnableDynamicLoading>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<!-- Riferimenti Revit API (Private=false per non copiare le DLL di sistema) -->
<Reference Include="RevitAPI">
<HintPath>C:\Program Files\Autodesk\Revit 2025\RevitAPI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RevitAPIUI">
<HintPath>C:\Program Files\Autodesk\Revit 2025\RevitAPIUI.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
</Project>Pattern Architetturali Fondamentali
1. IExternalApplication e Ribbon UI Personalizzata
using System;
using System.Reflection;
using Autodesk.Revit.UI;
using System.Windows.Media.Imaging;
namespace BimSkills.RevitDev
{
public class AppMain : IExternalApplication
{
public Result OnStartup(UIControlledApplication application)
{
string tabName = "BIM Skills Italia";
application.CreateRibbonTab(tabName);
RibbonPanel panel = application.CreateRibbonPanel(tabName, "Strumenti QA/QC");
string thisAssemblyPath = Assembly.GetExecutingAssembly().Location;
// Creazione PushButton
PushButtonData buttonData = new PushButtonData(
"cmdValidateLoin",
"Valida\nLOIN",
thisAssemblyPath,
"BimSkills.RevitDev.Commands.ValidateLoinCommand"
)
{
ToolTip = "Esegue l'audit dei parametri informativi e pset rispetto al CI di commessa.",
LargeImage = new BitmapImage(new Uri("pack://application:,,,/BimSkills;component/Resources/Loin32.png"))
};
panel.AddItem(buttonData);
return Result.Succeeded;
}
public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}
}
}2. IExternalCommand con TransactionGroup e Failure Handling
using System;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace BimSkills.RevitDev.Commands
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class BatchUpdateParamsCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIApplication uiApp = commandData.Application;
UIDocument uiDoc = uiApp.ActiveUIDocument;
Document doc = uiDoc.Document;
// TransactionGroup per raggruppare modifiche multiple in un unico "Undo"
using (TransactionGroup tg = new TransactionGroup(doc, "Aggiornamento Parametri WBS e CAM"))
{
tg.Start();
using (Transaction tx = new Transaction(doc, "Popolamento Dati"))
{
// Soppressione warning non bloccanti
FailureHandlingOptions failureOptions = tx.GetFailureHandlingOptions();
failureOptions.SetFailuresPreprocessor(new WarningSwallower());
tx.SetFailureHandlingOptions(failureOptions);
tx.Start();
try
{
// Esecuzione modifiche massive
var walls = new FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_Walls)
.WhereElementIsNotElementType()
.ToElements();
foreach (Element wall in walls)
{
Parameter p = wall.LookupParameter("Codice_WBS");
if (p != null && !p.IsReadOnly)
{
p.Set("WBS.STR.01.P00");
}
}
tx.Commit();
}
catch (Exception ex)
{
if (tx.HasStarted()) tx.RollBack();
tg.RollBack();
message = $"Errore durante l'aggiornamento: {ex.Message}";
return Result.Failed;
}
}
// Unifica le transazioni interne nella cronologia Undo
tg.Assimilate();
}
TaskDialog.Show("Completato", "Parametri di commessa aggiornati con successo.");
return Result.Succeeded;
}
}
/// <summary>
/// Disattiva i popup di warning non critici durante i comandi batch
/// </summary>
public class WarningSwallower : IFailuresPreprocessor
{
public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
{
var failures = failuresAccessor.GetFailureMessages();
foreach (FailureMessageAccessor failure in failures)
{
if (failure.GetSeverity() == FailureSeverity.Warning)
{
failuresAccessor.DeleteWarning(failure);
}
}
return FailureProcessingResult.Continue;
}
}
}3. FilteredElementCollector: Prestazioni Ottimizzate
I filtri Revit API operano in memoria nativa C++ prima di marshallare gli oggetti verso il runtime .NET. L'ordine dei filtri è determinante per le prestazioni:
// Esempio: Recupero muri portanti esterni al Piano Terra (Velocissimo)
Level targetLevel = new FilteredElementCollector(doc)
.OfClass(typeof(Level))
.Cast<Level>()
.FirstOrDefault(l => l.Name == "Piano Terra");
if (targetLevel != null)
{
// 1. Filtro rapido per categoria e istanza
FilteredElementCollector collector = new FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_Walls)
.WhereElementIsNotElementType();
// 2. Filtro rapido per livello di appartenenza
ElementLevelFilter levelFilter = new ElementLevelFilter(targetLevel.Id);
// 3. Filtro parametrico nativo per LoadBearing = True
ParameterValueProvider pvpLoadBearing = new ParameterValueProvider(
new ElementId(BuiltInParameter.WALL_STRUCTURAL_SIGNIFICANT)
);
FilterIntegerRule ruleLoadBearing = new FilterIntegerRule(
pvpLoadBearing, new FilterNumericEquals(), 1
);
ElementParameterFilter structuralFilter = new ElementParameterFilter(ruleLoadBearing);
// Applicazione combinata a livello C++ nativo
var structuralWalls = collector
.WherePasses(levelFilter)
.WherePasses(structuralFilter)
.Cast<Wall>()
.ToList();
}4. Comunicazione Asincrona UI Non Modale (ExternalEvent)
Per comunicare tra finestre WPF esterne / socket di rete e il thread principale di Revit senza generare eccezioni InvalidOperationException: Cannot modify document outside transaction:
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
public class AsyncUpdateHandler : IExternalEventHandler
{
public string NewParamValue { get; set; } = "DEFAULT_VAL";
public void Execute(UIApplication app)
{
UIDocument uidoc = app.ActiveUIDocument;
Document doc = uidoc.Document;
using (Transaction tx = new Transaction(doc, "Async Update from UI"))
{
tx.Start();
// Modifica elementi in sicurezza nel thread UI autorizzato da Revit
var selection = uidoc.Selection.GetElementIds();
foreach (ElementId id in selection)
{
Element el = doc.GetElement(id);
Parameter p = el?.LookupParameter("Stato_Verifica");
p?.Set(NewParamValue);
}
tx.Commit();
}
}
public string GetName() => "AsyncUpdateHandler";
}
// Nel ViewModel o finestra WPF:
// ExternalEvent exEvent = ExternalEvent.Create(new AsyncUpdateHandler());
// exEvent.Raise(); // Accoda l'esecuzione nel loop di Revit5. Manifest .addin Standard
Il file .addin deve essere posizionato in %APPDATA%\Autodesk\Revit\Addins\[Anno]\:
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Application">
<Name>BIM Skills Italia AddIn</Name>
<Assembly>C:\ProgramData\BimSkills\BimSkills.RevitDev.dll</Assembly>
<AddInId>87E4544D-4518-4908-9FE7-99E78F59C721</AddInId>
<FullClassName>BimSkills.RevitDev.AppMain</FullClassName>
<VendorId>VISIONXT</VendorId>
<VendorDescription>VisionXt Tech - BIM Automation</VendorDescription>
</AddIn>
</RevitAddIns>6. Add-In Isolation (Revit 2027)
Revit 2027 introduce l'isolamento degli add-in: ogni add-in dichiara il proprio contesto di caricamento, quali assembly espone agli altri e da quali dipende. Serve a evitare che due add-in che caricano versioni diverse della stessa libreria (Newtonsoft.Json, EPPlus, System.Text.Json) si sovrascrivano a vicenda.
Tag del manifesto .addin:
I tag di isolamento vivono in un blocco <ManifestSettings> dentro <AddIn>:
<AddIn Type="Application">
<!-- ...campi standard: Name, Assembly, AddInId, FullClassName, VendorId... -->
<ManifestSettings>
<UseRevitContext>False</UseRevitContext>
<ContextName>VisionXtBimSkills</ContextName>
<UseAllContextsForDependencyResolution>False</UseAllContextsForDependencyResolution>
<PublicAssemblies>
<Assembly>BimSkills.Shared.dll</Assembly>
</PublicAssemblies>
<Dependencies>
<DependsOnContext ContextName="VisionXtCore" />
</Dependencies>
</ManifestSettings>
</AddIn>Semantica dei tag:
ContextName: add-in installati in cartelle diverse ma con lo stessoContextNamevengono caricati nello stesso contesto.PublicAssemblies: gli assembly che il contesto accetta di condividere con gli altri.DependsOnClientId(attributoClientId) eDependsOnContext(attributoContextName): da chi il proprio contesto risolve le dipendenze. Entrambi ammettono di restringere la risoluzione a specifici assembly (AssemblyName); se non si specifica nulla, vengono usati tutti gli assembly pubblici di quel contesto. Verificare la forma esatta diAssemblyNamesull'esempio di manifesto della documentazione SDK 2027 prima di scriverlo.UseAllContextsForDependencyResolution:Trueriapre la risoluzione a tutti i contesti e annulla gran parte del beneficio dell'isolamento.
Lato API, le dipendenze sono modellate da AddInDependencyBase e dalle sue specializzazioni
ClientIdDependency (dipendenza da un add-in identificato dal suo GUID) e
ContextNameDependency (dipendenza da un contesto di caricamento condiviso).
Regole pratiche:
- Un contesto per prodotto, non per comando: gli add-in della stessa suite condividono il contesto.
- Esporre in
PublicAssembliessolo le librerie che altri add-in devono davvero risolvere. UseAllContextsForDependencyResolutionaTrueva usato solo come rimedio temporaneo in fase di migrazione.
Anti-pattern nello Sviluppo Revit API
| Errore Tipico C# | Conseguenza | Soluzione Corretta |
Usare .ToElements().Where(...) con LINQ | Carica in memoria migliaia di oggetti C# rallentando l'add-in di 10x | Applicare sempre WherePasses(ElementFilter) prima di estrarre la lista. |
Accedere a doc.ActiveView in IExternalDBApplication | NullReferenceException bloccante | ActiveView e ActiveUIDocument esistono solo in contesto UI (IExternalCommand). |
Usare IntegerValue per gli ElementId in Revit 2024+ | Warning di deprecazione e troncamento a 64 bit su modelli enormi | Usare elementId.Value (tipo long). |
Passare valori metrici direttamente a Parameter.Set(val) | Valori scalati in modo errato (es. 3 metri diventano 9.84 piedi) | Convertire sempre con UnitUtils.ConvertToInternalUnits(val, UnitTypeId.Meters). |
Non richiamare symbol.Activate() prima di NewFamilyInstance | Crash del comando con ArgumentException su tipi non attivi | Verificare if (!symbol.IsActive) symbol.Activate(); prima della posa. |
Output Strutturato
Quando invocata, la skill fornisce:
- Soluzioni Complete C# (.NET 8 o .NET 4.8) pronte per la compilazione in Visual Studio / JetBrains Rider.
- File
.csprojSDK-Style Ottimizzato con configurazione dynamic loading per Revit 2024-2026. - File Manifest
.addincon GUID univoci e percorsi assembly. - Pattern di Gestione Eccezioni e Soppressione Warning.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

