Node with Revit API - how get access to current document?

Hi, I continue researching creation nodes based C# to Dynamo and wanted try nodes that used Revit API - f.e. below simple node that take parameters of Revit’s base point and return them


Main problem- how I can determine current document?! I tried use Dynamo’s “Document.Current”, but that Dynamo’s command (non Revit API) and smb on forum adviced me use libraries that conver Dynamo commands/API to Revit API and on that step I stucked.
Have anybody ideas how it must working?
If I use classic operations as in Revit’s plugin:

public Autodesk.Revit.UI.Result Execute(ExternalCommandData revit, ref string message, ElementSet elements)
{ UIApplication app = revit.Application;
Document doc = app.ActiveUIDocument.Document;
....}

Dynamo will wait for me values for variables in (…)
I will be glad any help!


All code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Autodesk.Revit.DB;
using Autodesk.DesignScript.Runtime;

namespace BasePoint_coord1
{

    public class RevitAPI
    {
        [MultiReturn(new[] { "BasePoint_X", "BasePoint_Y", "BasePoint_Z", "BasePoint_Angle" })]
        public static Dictionary<string, object> GetCoordOfRevitBasePoint(Autodesk.Revit.DB.Document doc)
        {
            var basePoint = new FilteredElementCollector(doc).OfClass(typeof(BasePoint)).Cast<BasePoint>().Where(p => !p.IsShared).ToList().FirstOrDefault();
            //Инициация параметров
            double BasePoint_X = 0;
            double BasePoint_Y = 0;
            double BasePoint_Z = 0;
            double BasePoint_Angle = 0;

            //Присвоение переменным значений
            BasePoint_Y = basePoint.get_Parameter(BuiltInParameter.BASEPOINT_NORTHSOUTH_PARAM).AsDouble();
            BasePoint_X = basePoint.get_Parameter(BuiltInParameter.BASEPOINT_EASTWEST_PARAM).AsDouble();
            BasePoint_Z = basePoint.get_Parameter(BuiltInParameter.BASEPOINT_ELEVATION_PARAM).AsDouble();
            BasePoint_Angle = basePoint.get_Parameter(BuiltInParameter.BASEPOINT_ANGLETON_PARAM).AsDouble();

            //string result = BasePoint_Y + "," + BasePoint_X + "," + BasePoint_Z + "," + BasePoint_Angle;
            return new Dictionary<string, object>
            {
                {"BasePoint_X", BasePoint_X},
                {"BasePoint_Y", BasePoint_Y},
                {"BasePoint_Z",  BasePoint_Z},
                {"Angle of rotation",  BasePoint_Angle},
            };
        }
    }
}

Hi @georg.grebenyuk,

You can generate a Revit.DB.Document with a simple python script :

import clr
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager

OUT = DocumentManager.Instance.CurrentDBDocument

Hi, @Alban_de_Chasteigner
If I done as you said - I will get an error:

Your dictionary keys - specifically your “Angle of rotation” key - doesn’t match the keys you’ve declared in your MultiReturn attribute. Change it to “BasePoint_Angle” and you wont get the exception.

Yeah, it working!
But how I can get access to current document from C# without that temp-decision with Python?

This could help:

I’m glad for that link, but I can’t understand how it can help me.
I tried some variants with that function and other and main result that I get - nothing methods are not visiable in Dynamo!
I’m amazing why there are no any info on https://developer.dynamobim.org how get access to Revit from Custom Node?

It all depends on what you want to do. @JacobSmall suggestion cant be used with zero touch nodes and is only avialable if you are writing Revit addins which implement IExternalCommand.

So you need to establish the following: does your node even need the document as an input? Some custom nodes do have the document as an input in case where they support links for example, but this is a nuisance since these packages also need to add extra nodes to return the RevitAPI document like what @Alban_de_Chasteigner demonstrated as there is no way for developers to create an instance of Dynamo’s Revit.Application.Document document wrapper as its a singleton (uses the singleton pattern) and therefore has no public constructor.

The problem with returning RevitAPI entities in Dynamo is they are not compatible with any OOTB node or most other packages which means any OOTB node requiring a document will fail in the same way your node is failing if the RevitAPI document from a custom node is used with an OOTB node…which is extremely confusing to most users who are not going to be concerned with these nuances.

If you don’t need the input, then you can access the document via Dynamos singleton stored in its DocumentManager class. This is the most common method zero touch and python nodes use to access the active document, and you can simply add this line inside your method and therefore avoid the need to provide an input:

var document = DocumentManager.Instance.CurrentDBDocument;

Alternatively, if you do want to provide the document input then you need to qualify the class or use an alias using directive which specifies Dynamo’s document wrapper as shown below, but its kind of pointless given the above basically does the same thing but avoids the need for an input:
public static Dictionary<string, object> GetCoordOfRevitBasePoint(Revit.Application.Document doc)

6 Likes

Thank you very much!
After I added link to “C:\Program Files\Autodesk\Revit 2020\AddIns\DynamoForRevit\Revit\RevitServices.dll” and added “using RevitServices.Persistence” all realy starting working
Also I start research your guide - there are a lot of interestind data for me :grinning: