Migrate Building Coder Samples to Revit 2013

I migrated The Building Coder samples to Revit 2013.

Revit Onebox

Before diving into that, however, a short note on Revit Onebox. Here is a comparison matrix of the features provided by the different flavours, all of which are available in the Onebox version. There is even a short 1.5 minute youtube video on the topic.

Question: I would like to install the Revit 2013 Onebox product which contains Revit Architecture, Structure and MEP as one product. Where can I find it?

Answer: Revit Onebox is included in Autodesk Building Design Suite 2013 Premium and Ultimate, and not in Standard. For ADN members, the Autodesk Building Design Suites are now available for download from the ADN extranet at Software & Support > Autodesk Building Design Suite > Downloads.

The Building Coder Samples Migration to Revit 2013

Back to the API related topics.

Migrating from one release of Revit to the next is an exercise we have gone through several times in the past, of course.

This time I was especially well prepared, since I recently intentionally eliminated the Revit 2012 API compiler warnings and deprecated calls.

Look at that post for links back to the previous migration efforts.

Here are the main issues I had to tackle:

.NET Framework Update

The first thing that strikes one this time around when migrating an add-in from the previous version is the message displayed by Visual Studio on changing the Revit API assemblies, telling us that the add-in project now needs to reference the .NET framework version 4:

.NET Framework version update message

Trying to rebuild now without updating the framework version causes 1545 errors and 94 warnings:

The primary reference "RevitAPI" could not be resolved because it has an indirect dependency on the .NET Framework assembly "mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" which has a higher version "" than the version "" in the current target framework.

Go to Solution Explorer > BuildingCoder > [right click] > Properties > Application > Target Framework and change it to version 4.0 to remove them all again:

Set .NET Framework version

Materials Collection Update

After that, recompiling causes one single error:

The type or namespace name 'Materials' could not be found (are you missing a using directive or an assembly reference?) in CmdGetMaterials.cs, line 460.

The Materials collection class, derived from the MaterialSet class, was defined in the Revit 2012 API to provide access to the materials used in the Revit project. Instances of this class were returned by the Settings.Materials property.

This class no longer exists in the Revit 2013 API, a fact not mentioned in the What's New section of the Revit API help file RevitAPI.chm, to my surprise. It does however mention that its creation members have been replaced by the new static Material.Create method:

Just seeing one single error reported was of course too good to be true. There are actually many more than one errors relating to materials. They are caused in various places in the module CmdGetMaterials, which we used to compare different ways to retrieve materials using either the obsolete Materials collection property or directly via filtered element collectors.

Commenting out the initial offending usage of the Materials class in the GetMaterialByName extension class caused lots of other errors and warnings to be listed, 13 errors and 52 warnings, to be precise.

New Document GetElement method

Most of the warnings refer to the obsolete Document.Element property taking an element id argument, which has now been converted to a method named GetElement, as I recently explained.

I globally replaced ".get_Element(" by ".GetElement(" to fix that, reducing the count to 13 errors and 33 warnings.

Most of the errors are still related to the removal of the Materials collection class in the CmdGetMaterials.cs module, so I fixed that next by simply encapsulating all the offending the code in an '#if BEFORE_REVIT_2013' pragma, effectively removing it, reducing the count to 5 errors and 33 warnings.

Remaining Errors

The five remaining errors look pretty trivial:

One single error remains:

The type 'System.Windows.Markup.IUriContext' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Xaml, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089' in line 73 of CmdPreviewImage.cs.

So I did what the man says and added the required reference, resulting in zero errors and 33 warnings.

Rebuild all now succeeds, so I could in fact load and test my little baby at this point.

Enumerable GeometryElement

However, since most of the warnings are caused by the obsolete GeometryElement Objects property returning a GeometryObjectArray, I decided to address that as well first.

The Obsolete attribute on this property actually states that "This property will be obsolete from 2013; Call GetEnumerator() instead." Strictly taken, this is only true if I interpret "from" as "after", as far as I can tell.

The fix is very simple and reduces the number of lines of code, since the GeometryElement class is now in itself enumerable. Here is a code snippet from CmdSlabBoundary.cs using the obsolete Objects property:

  GeometryElement geo = floor.get_Geometry( opt );

  GeometryObjectArray objects = geo.Objects;

  foreach( GeometryObject obj in objects )
    Solid solid = obj as Solid;
    if( solid != null )
      GetBoundary( polygons, solid );

This can now be replaced by a shorter version iterating over the geometry element itself directly, like this:

  GeometryElement geo = floor.get_Geometry( opt );
  foreach( GeometryObject obj in geo )
    Solid solid = obj as Solid;
    if( solid != null )
      GetBoundary( polygons, solid );

Put differently, we used to access a GeometryObjectArray containing the geometry objects from the geometry element using its Objects property:

  GeometryObjectArray objs = ge.Objects; // 2012

Nowadays, the geometry element itself is an enumeration of the contained objects, and derived from the appropriate interface to access them:

  IEnumerable<GeometryObject> objs = ge; // 2013

I did not replace the use of the Objects property in those places that query the number of elements contained, since the new enumerator interface does not return that information directly, whereas the GeometryObjectArray provides a Size property returning the total count of collection members.

After this cleanup, I am left with zero errors and 13 warnings, which I am happy to live with for the moment, since I have other things to do besides this.

Updated Group and Ungroup Methods

Well, actually, since its return value is not used anywhere, it costs me little effort to replace the two calls to the obsolete Group.Ungroup method by calls to the replacement method UngroupMembers in CmdDuplicateElement.cs.

Oh, and in the same module, it is also easy to fix the call to the obsolete overload of NewGroup taking an ElementSet argument:

  Group group = doc.Create.NewGroup(
    uidoc.Selection.Elements );

The Selection class already provides a method GetElementIds returning a collection of element ids, so we can simply plug that in instead to invoke the other overload:

  Group group = doc.Create.NewGroup(
    uidoc.Selection.GetElementIds() );

Now we are down to zero errors and ten warnings.


Pre-Release Revit 2013 Version for Revit 2012 Comparison

Here is version 2013.0.98.0, the pre-release version of The Building Coder samples for Revit 2013. To compare it with the last Revit 2012 release, please refer to the version 2012.0.98.0, which introduced the command CmdRemoveDwfLinks.

Final Initial Revit 2013 Version

At long last, to wrap this up, here is the final version 2013.0.98.1 of The Building Coder samples for Revit 2013. The difference to the previous one is a global update of all the copyright comments from 2011 to 2012, which makes just about every single file different from the Revit 2012 version. I postponed this to allow for easier comparison between the last Revit 2012 version 2012.0.98.0 and the pre-release Revit 2013 version 2013.0.98.0.

Phew again, and enjoy.