Managing External Files

Managing External Files

ExternalFileUtils

As its name implies, this utility class provides information about external file references. TheExternalFileUtils.GetAllExternalFileReferences() method returns a collection of ElementIds of all elements that are external file references in the document. (Note that it will not return the ids of nested Revit links; it only returns top-level references.) This utility class has two other methods, IsExternalFileReference() and GetExternalFileReference() which perform the same function as the similarly named methods of the Element class, but can be used when you have an ElementId rather than first obtaining the Element.

TransmissionData

TransmissionData stores information on both the previous state and requested state of an external file reference. This means that it stores the load state and path of the reference from the most recent time this TransmissionData's document was opened. It also stores load state and path information for what Revit should do the next time the document is opened.

As such, TransmissionData can be used to perform operations on external file references without having to open the entire associated Revit document. The methods ReadTransmissionData and WriteTransmissionData can be used to obtain information about external references, or to change that information. For example, calling WriteTransmissionData with a TransmissionData object which has had all references set to LinkedFileStatus.Unloaded would cause no references to be loaded upon next opening the document.

TransmissionData cannot add or remove references to external files. If AddExternalFileReference is called using an ElementId which does not correspond to an element which is an external file reference, the information will be ignored on file load.

The following example reads the TransmissionData for a file at the given location and sets all Revit links to be unloaded the next time the document is opened.

Code Region: Unload Revit Links

void UnloadRevitLinks(ModelPath location)
/// This method will set all Revit links to be unloaded the next time the document at the given location is opened. 
/// The TransmissionData for a given document only contains top-level Revit links, not nested links.
/// However, nested links will be unloaded if their parent links are unloaded, so this function only needs to look at the document's immediate links. 
{
    // access transmission data in the given Revit file
    TransmissionData transData = TransmissionData.ReadTransmissionData(location);
    if (transData != null)
    {
        // collect all (immediate) external references in the model
        ICollection<ElementId> externalReferences = transData.GetAllExternalFileReferenceIds();
        // find every reference that is a link
        foreach (ElementId refId in externalReferences)
        {
            ExternalFileReference extRef = transData.GetLastSavedReferenceData(refId);
            if (extRef.ExternalFileReferenceType == ExternalFileReferenceType.RevitLink)
            {
                // we do not want to change neither the path nor the path-type
                // we only want the links to be unloaded (shouldLoad = false)
                transData.SetDesiredReferenceData(refId, extRef.GetPath(), extRef.PathType, false);
            }
        }

        // make sure the IsTransmitted property is set 
        transData.IsTransmitted = true;
        // modified transmission data must be saved back to the model
        TransmissionData.WriteTransmissionData(location, transData);
    }
    else
    {
        Autodesk.Revit.UI.TaskDialog.Show("Unload Links", "The document does not have any transmission data");
    }
}

Construct ModelPath for location on server

To read the TransmissionData object, you need to call the static method TransmissionData.ReadTransmissionData. It requires a ModelPath object.

There are two ways to construct a ModelPath object that refers to a central file. The first way involves using ModelPathUtils and the base ModelPath class. The steps are as follows:

  1. Compose the user-visible path string of the central file: ModelPathUtils.GetRevitServerPrefix() + “relative path”.
    Note: The folder separator used in the "relative path" is a forward slash(/). The correct separator is a forward slash.
  2. Create a ModelPath object via the ModelPathUtils.ConvertUserVisiblePathToModelPath() method. Pass in the string composed in the previous step.
  3. Read the transmission data via the TransmissionData::ReadTransmissionData() method. Pass in the ModelPath obtained in the previous step.

The following example demonstrates this method assuming a central file testmodel.rvt is stored in the root folder of Revit Server, SHACNG035WQRP.

Code Region: Constructing path to central file using ModelPath

[TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class RevitCommand : IExternalCommand
{
  public Result Execute(ExternalCommandData commandData,        
         ref string messages, ElementSet elements)
{
    UIApplication app = commandData.Application;
    Document doc = app.ActiveUIDocument.Document;
    Transaction trans = new Transaction(doc, "ExComm");
    trans.Start();
    string visiblePath = ModelPathUtils.GetRevitServerPrefix() + "/testmodel.rvt";
    ModelPath serverPath = ModelPathUtils.ConvertUserVisiblePathToModelPath(visiblePath);
    TransmissionData transData = TransmissionData.ReadTransmissionData(serverPath);
    string mymessage = null;
    if (transData != null)
    {
         //access the data in the transData here.
    }
    else
    {
      Autodesk.Revit.UI.TaskDialog.Show("Unload Links",
      "The document does not have any transmission data");
    }
    trans.Commit();
    return Result.Succeeded;
  }
}

The second way to construct the ModelPath object that that refers to a central file is to use the child class ServerPath. This way can be used if the program knows the local server name, however, it is not recommended as the server name may be changed by the Revit user from the Revit UI. The steps are as follows:

  1. Create a ServerPath object using ServerPath constructor.
new ServerPath(“ServerNameOrServerIp”, “relative path without the initial forward slash”).
Note: The first parameter is the server name, not the string returned by the ModelPathUtils.GetRevitServerPrefix() and the second parameter does not include the initial forward slash. See the following sample code. The folder separator is a forward slash(/) too.
  1. Read the TransmissionData object via the TransmissionData.ReadTransmissionData() method.Pass in the ServerPath obtained in the previous step

The following code demonstrates this method.

Code Region: Constructing path to central file using ServerPath

[TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class RevitCommand : IExternalCommand
{
  public Result Execute(ExternalCommandData commandData,
         ref string messages, ElementSet elements)
  {
    UIApplication app = commandData.Application;
    Document doc = app.ActiveUIDocument.Document;
    Transaction trans = new Transaction(doc, "ExComm");
    trans.Start();
    ServerPath serverPath = new ServerPath("SHACNG035WQRP", "testmodel.rvt");
    TransmissionData transData = TransmissionData.ReadTransmissionData(serverPath);
    string mymessage = null;
    if (transData != null)
    {
       //access the data in the transData here.
    }
    else
    {
      Autodesk.Revit.UI.TaskDialog.Show("Unload Links",
         "The document does not have any transmission data");
    }
    trans.Commit();
    return Result.Succeeded;
  }
}