External Resource Server can't load linked IFC
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi, I'm trying to implement an ExternalResourceServer to link files from a users Onedrive folder.
We use sharepoint to store project documents, including some IFC and DWG files and access these documents via Onedrive in windows. This means every user has their own unique path to the files, ie c:\Users\username\Onedrive - CompanyName\Project\...
For testing purposes I just replace "c:\Users\username\Onedrive - CompanyName\" with the environment variable %onedrive% which points to the correct folder and so far I'm able to link DWG and Revit files without any problems, but it fails when I try to link IFC files. For the user that links the IFC, it works just fine, but for any other users trying to load the link, I get this error message:
I'm using Revit 2022.1 and the revit ifc importer from github version 22.4.1.0.
When I compare the RevitLinkType for a normal revit file and the ifc link, I see some differences in "GetExternalResourceReferences".
For the normal revit file:
Linked ifc model:
The linked ifc has full path in the InSessionPath, is this why it fails?
Do I have to treat IFC files different, or is this a bug, or not related?
Code:
public class OneDriveExternalResourceServer : IExternalResourceServer
{
// Implementation
public OneDriveExternalResourceServer() { } // Constructor
public Guid GetServerId() => new Guid("4B386D14-5D9E-4611-BCDA-56091BE3AEBF");
public ExternalServiceId GetServiceId() => ExternalServices.BuiltInExternalServices.ExternalResourceService;
public String GetName() => "Onedrive";
public String GetVendorId() => "Vendor";
public String GetDescription() => "Map path to users onedrive folder";
public String GetShortName() => "Onedrive";
public virtual String GetInformationLink() => "";
public string GetIconPath() => string.Empty;
public bool SupportsExternalResourceType(ExternalResourceType resourceType) => (
resourceType == ExternalResourceTypes.BuiltInExternalResourceTypes.CADLink ||
resourceType == ExternalResourceTypes.BuiltInExternalResourceTypes.RevitLink ||
resourceType == ExternalResourceTypes.BuiltInExternalResourceTypes.Image ||
resourceType == ExternalResourceTypes.BuiltInExternalResourceTypes.PointCloud ||
resourceType == ExternalResourceTypes.BuiltInExternalResourceTypes.IFCLink
);
private static string RefMapLinkPathEntry => "Path";
public void LoadResource(Guid loadRequestId, ExternalResourceType resourceType, ExternalResourceReference desiredResource,
ExternalResourceLoadContext loadContext, ExternalResourceLoadContent loadContent)
{
if (loadContent is LinkLoadContent linkLoadContent)
{
string serverLinkPath = GetFullServerLinkFilePath(desiredResource);
ModelPath linksPath = ModelPathUtils.ConvertUserVisiblePathToModelPath(serverLinkPath);
linkLoadContent.SetLinkDataPath(linksPath);
loadContent.LoadStatus = ExternalResourceLoadStatus.Success;
}
else
{
throw new ArgumentException("Wrong type of ExternalResourceLoadContent (expecting a LinkLoadContent) for Revit links.", "loadContent");
}
}
public bool IsResourceWellFormed(ExternalResourceReference extRef)
{
if (extRef.ServerId != GetServerId())
return false;
if (!extRef.HasValidDisplayPath())
return false;
return true;
}
public string GetInSessionPath(ExternalResourceReference reference, string originalDisplayPath)
{
return originalDisplayPath;
}
public ResourceVersionStatus GetResourceVersionStatus(ExternalResourceReference reference)
{
return ResourceVersionStatus.Unknown;
}
public bool AreSameResources(IDictionary<string, string> reference1, IDictionary<string, string> reference2)
{
if (reference1.Count != reference2.Count)
{
return false;
}
else
{
foreach (string key in reference1.Keys)
{
if (!reference2.ContainsKey(key) || reference1[key] != reference2[key])
{
return false;
}
}
}
return true;
}
public void SetupBrowserData(ExternalResourceBrowserData browserData)
{
ExternalResourceMatchOptions matchOptions = browserData.GetMatchOptions();
ExternalResourceType resourceType = matchOptions.ResourceType;
string OneDrivePath = Environment.GetEnvironmentVariable("onedrive");
if (!Directory.Exists(OneDrivePath))
throw new Exception("Onedrive path is invalid");
string filterPattern = "*";
string folderPath = browserData.FolderPath.Replace('/', '\\');
string path = OneDrivePath.TrimEnd('\\') + folderPath;
if (Directory.Exists(path))
{
DirectoryInfo dir = new DirectoryInfo(path);
DirectoryInfo[] subDirs = dir.GetDirectories();
foreach (DirectoryInfo subDir in subDirs)
{
browserData.AddSubFolder(subDir.Name);
}
FileInfo[] subFiles = dir.GetFiles(filterPattern, SearchOption.TopDirectoryOnly);
foreach (FileInfo file in subFiles)
{
var refMap = new Dictionary<string, string>();
refMap[RefMapLinkPathEntry] = folderPath.TrimStart('\\').TrimEnd('/') + '/' + file.Name;
browserData.AddResource(file.Name, GetFileVersion(file.FullName), refMap);
}
}
else
{
throw new ArgumentException("Path is invalid");
}
}
public void GetTypeSpecificServerOperations(ExternalResourceServerExtensions extensions)
{
//RevitLinkOperations revitLinkOps = extensions.GetRevitLinkOperations();
//revitLinkOps.SetGetLocalPathForOpenCallback(new GetLinkPathForOpen());
}
//
private string GetFileVersion(String filePath)
{
FileInfo fileInfo = new FileInfo(filePath);
DateTime lastModifiedTime = fileInfo.LastWriteTimeUtc;
return lastModifiedTime.ToString();
}
private string GetFullServerLinkFilePath(ExternalResourceReference resource)
{
if (resource == null)
throw new Exception("Invalid ExternalResourceReference");
IDictionary<string, string> refMap = resource.GetReferenceInformation();
if (!refMap.ContainsKey(RefMapLinkPathEntry))
throw new Exception("ExternalResourceReference missing Path key");
string refLink = resource.GetReferenceInformation()[RefMapLinkPathEntry].Replace("/", "\\").Replace(@"\\", @"\");
string OneDrivePath = Environment.GetEnvironmentVariable("onedrive");
string fullPath = Path.Combine(OneDrivePath, refLink);
if (!File.Exists(fullPath))
throw new Exception($"File: {fullPath} not found");
return fullPath;
}
}