| name | c3d-data-shortcuts |
| description | Data shortcut references, cross-drawing objects, broken reference repair |
Civil 3D Data Shortcuts and Cross-Drawing References
Use this skill when working with data shortcuts, creating or managing cross-drawing references, synchronizing imported references, repairing broken references, or configuring data shortcut working and project folders.
Overview
Data shortcuts allow Civil 3D objects in one drawing (the source) to be referenced read-only into other drawings (the host). The .NET API exposes this through the DataShortcuts static class and the DataShortcutManager class in Autodesk.Civil.DataShortcuts. The assembly is AeccDataShortcutMgd.dll.
Working Folder
└── Project Folder (_Shortcuts/ subfolder)
├── Alignments.xml
├── Surfaces.xml
├── Pipe Networks.xml
├── Pressure Pipe Networks.xml
├── Corridors.xml
└── View Frame Groups.xml
Supported Reference Types (RefType Enum)
The DataShortcuts.RefType enumeration defines the publishable entity types:
using Autodesk.Civil.DataShortcuts;
Managing Working and Project Folders
Get and Set Working Folder
using Autodesk.Civil.DataShortcuts;
string workingFolder = DataShortcuts.GetWorkingFolderPath();
ed.WriteMessage("Working folder: {0}\n", workingFolder);
DataShortcuts.SetWorkingFolderPath(@"C:\Civil3D Projects");
Get and Set Project Folder
string projectFolder = DataShortcuts.GetProjectFolderPath();
ed.WriteMessage("Project folder: {0}\n", projectFolder);
DataShortcuts.SetProjectFolderPath("MyProject");
int projectId = DataShortcuts.GetDSProjectId(@"C:\Civil3D Projects\MyProject");
DataShortcuts.AssociateDSProject(projectId);
Listing Published Items
DataShortcutManager dsMgr = DataShortcuts.CreateDataShortcutManager(ref projectId);
int count = dsMgr.GetPublishedItemsCount();
for (int i = 0; i < count; i++)
{
DSEntityInfo info = dsMgr.GetPublishedItemAt(i);
ed.WriteMessage("Name: {0}, Type: {1}, Source: {2}\n",
info.Name, info.RefType, info.SourceDrawing);
}
dsMgr.Dispose();
Creating Data References (Importing Shortcuts)
Using DataShortcuts.CreateReference
using Autodesk.Civil.DataShortcuts;
using Autodesk.Civil.ApplicationServices;
DataShortcuts.CreateReference(
doc.Database,
"EG Surface",
RefType.Surface
);
Using DataShortcutManager.CreateReference
int projectId = 0;
DataShortcutManager dsMgr = DataShortcuts.CreateDataShortcutManager(ref projectId);
int itemIndex = -1;
int count = dsMgr.GetPublishedItemsCount();
for (int i = 0; i < count; i++)
{
DSEntityInfo info = dsMgr.GetPublishedItemAt(i);
if (info.Name == "Main Road CL" && info.RefType == RefType.Alignment)
{
itemIndex = i;
break;
}
}
if (itemIndex >= 0)
{
dsMgr.CreateReference(itemIndex, doc.Database);
ed.WriteMessage("Reference created for alignment 'Main Road CL'.\n");
}
dsMgr.Dispose();
Batch Import Multiple References
int projectId = 0;
DataShortcutManager dsMgr = DataShortcuts.CreateDataShortcutManager(ref projectId);
RefType[] typesToImport = {
RefType.Surface,
RefType.Alignment,
RefType.PipeNetwork
};
int imported = 0;
int count = dsMgr.GetPublishedItemsCount();
for (int i = 0; i < count; i++)
{
DSEntityInfo info = dsMgr.GetPublishedItemAt(i);
if (Array.IndexOf(typesToImport, info.RefType) >= 0)
{
try
{
dsMgr.CreateReference(i, doc.Database);
imported++;
ed.WriteMessage("Imported: {0} ({1})\n", info.Name, info.RefType);
}
catch (System.Exception ex)
{
ed.WriteMessage("Failed to import {0}: {1}\n", info.Name, ex.Message);
}
}
}
ed.WriteMessage("Total imported: {0}\n", imported);
dsMgr.Dispose();
Identifying Reference Objects
Checking If an Entity Is a Reference
using (Transaction ts = db.TransactionManager.StartTransaction())
{
Alignment align = ts.GetObject(alignId, OpenMode.ForRead) as Alignment;
if (align.IsReferenceObject)
{
ed.WriteMessage("'{0}' is a data reference.\n", align.Name);
DataShortcutKey dsKey = align.GetReferenceInfo();
ed.WriteMessage(" Source drawing: {0}\n", dsKey.SourceDrawing);
ed.WriteMessage(" Source entity: {0}\n", dsKey.SourceEntityName);
ed.WriteMessage(" Ref type: {0}\n", dsKey.RefType);
}
if (align.IsReferenceSubObject)
{
ed.WriteMessage("'{0}' is a reference sub-object.\n", align.Name);
}
ts.Commit();
}
Iterating All Reference Entities in a Drawing
CivilDocument doc = CivilApplication.ActiveDocument;
using (Transaction ts = db.TransactionManager.StartTransaction())
{
foreach (ObjectId surfId in doc.GetSurfaceIds())
{
var surf = ts.GetObject(surfId, OpenMode.ForRead) as Autodesk.Civil.DatabaseServices.Surface;
if (surf.IsReferenceObject)
ed.WriteMessage("DREF Surface: {0}\n", surf.Name);
}
foreach (ObjectId alignId in doc.GetAlignmentIds())
{
var align = ts.GetObject(alignId, OpenMode.ForRead) as Alignment;
if (align.IsReferenceObject)
ed.WriteMessage("DREF Alignment: {0}\n", align.Name);
}
foreach (ObjectId netId in doc.GetPipeNetworkIds())
{
var network = ts.GetObject(netId, OpenMode.ForRead) as Network;
if (network.IsReferenceObject)
ed.WriteMessage("DREF Network: {0}\n", network.Name);
}
ts.Commit();
}
Synchronizing References (SynchronizeImport)
When the source drawing changes, data references in host drawings must be synchronized. References auto-synchronize on drawing open, but can also be forced programmatically.
Synchronize All References
using Autodesk.Civil.DataShortcuts;
DataShortcuts.SynchronizeImport(doc.Database);
ed.WriteMessage("All data references synchronized.\n");
Synchronize a Specific Reference
using (Transaction ts = db.TransactionManager.StartTransaction())
{
Alignment align = ts.GetObject(alignId, OpenMode.ForRead) as Alignment;
if (align.IsReferenceObject)
{
DataShortcuts.SynchronizeImport(db, alignId);
ed.WriteMessage("Synchronized reference: {0}\n", align.Name);
}
ts.Commit();
}
Repairing Broken References
References break when the source drawing is moved, renamed, or deleted. The API provides repair methods.
Detect Broken References
int projectId = 0;
DataShortcutManager dsMgr = DataShortcuts.CreateDataShortcutManager(ref projectId);
int brokenCount = dsMgr.GetBrokenDRefCount(doc.Database);
ed.WriteMessage("Broken references: {0}\n", brokenCount);
for (int i = 0; i < brokenCount; i++)
{
ObjectId brokenId = dsMgr.GetBrokenDRefEntityId(doc.Database, i);
Entity ent = ts.GetObject(brokenId, OpenMode.ForRead) as Entity;
ed.WriteMessage(" Broken: {0} (ObjectId: {1})\n", ent.Name, brokenId);
}
dsMgr.Dispose();
Repair a Broken Data Reference in the Drawing
DataShortcuts.RepairBrokenDRef(
brokenEntityId,
@"C:\Projects\Source\Design.dwg",
true
);
Repair a Broken Data Shortcut in the Project
int projectId = 0;
DataShortcutManager dsMgr = DataShortcuts.CreateDataShortcutManager(ref projectId);
bool repaired = DataShortcuts.RepairBrokenDataShortcut(
shortcutIndex,
@"C:\Projects\Source\Design.dwg",
true
);
if (repaired)
ed.WriteMessage("Data shortcut repaired.\n");
else
ed.WriteMessage("Repair failed.\n");
dsMgr.Dispose();
Batch Repair All Broken References
int projectId = 0;
DataShortcutManager dsMgr = DataShortcuts.CreateDataShortcutManager(ref projectId);
int brokenCount = dsMgr.GetBrokenDRefCount(doc.Database);
if (brokenCount > 0)
{
ObjectId firstBrokenId = dsMgr.GetBrokenDRefEntityId(doc.Database, 0);
DataShortcuts.RepairBrokenDRef(firstBrokenId, newSourceDrawingPath, true);
ed.WriteMessage("Attempted repair of {0} broken reference(s).\n", brokenCount);
}
dsMgr.Dispose();
Gotchas
- Data reference entities are read-only in the host drawing; opening ForWrite on referenced properties throws an exception
DataShortcutManager holds unmanaged resources; always call Dispose() or use a using block
SynchronizeImport requires the source drawing to be accessible at the stored path; if moved, repair first
SetWorkingFolderPath and SetProjectFolderPath do not validate the path; invalid paths cause failures on next shortcut operation
RepairBrokenDRef with autoRepairOther = true only repairs entities referencing the same source drawing; entities from other sources need separate repair calls
- Reference sub-objects (e.g., profiles imported with an alignment) cannot be individually removed; removing the parent reference removes all children
- Creating a reference to an entity that already exists as a DREF in the drawing throws an exception; check
IsReferenceObject first
- The
_Shortcuts subfolder is created automatically by Civil 3D in the project folder; do not manually create or modify its XML files
- The
AECCFORCESYNCHRONIZEREFERENCES built-in command can synchronize all references interactively, but the API method SynchronizeImport is the programmatic equivalent
- Pressure network references require Civil 3D 2020+ API; earlier versions only support gravity
PipeNetwork
Related Skills
c3d-root-objects — CivilDocument, transactions, and collection access patterns used with reference entities
c3d-alignments — Alignment creation and queries; alignment DREFs are the most common reference type
c3d-surfaces — Surface objects that can be published and referenced across drawings
c3d-profiles — Profiles that accompany alignment references as sub-objects
c3d-pipe-networks — Gravity and pressure pipe networks publishable via data shortcuts