External Resource Server can't load linked IFC

External Resource Server can't load linked IFC

svein.horve
Contributor Contributor
644 Views
2 Replies
Message 1 of 3

External Resource Server can't load linked IFC

svein.horve
Contributor
Contributor

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:

 

sveinhorve_0-1648371125286.png

 

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:

sveinhorve_1-1648371910870.png

 

Linked ifc model:

sveinhorve_2-1648371970146.png

 

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;
    }
}

 

 

 

 

 

 

 

 

0 Likes
645 Views
2 Replies
Replies (2)
Message 2 of 3

jeremy_tammik
Alumni
Alumni

Thank you for reporting this and your clear description. I am checking with the development team for you.

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 3

jeremy_tammik
Alumni
Alumni

Dear Svein,

 

Thank you for your report, sample material and patience.

 

The development team reply: I am hoping that this is possible to do and we only need to provide code sample.

 

Consequently, I submitted an internal development ticket REVIT-190078 [External Resource Server can't load linked IFC] for their further exploration. Please make a note of this number for future reference.

 

You are welcome to request an update on the status of this issue or to provide additional information on it at any time quoting this change request number.

 

This issue is important to me. What can I do to help?

 

This issue needs to be assessed by our engineering team and prioritised against all other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:

 

  • Impact on your application and/or your development.
  • The number of users affected.
  • The potential revenue impact to you.
  • The potential revenue impact to Autodesk.
  • Realistic timescale over which a fix would help you.
  • In the case of a request for a new feature or a feature enhancement, please also provide detailed Use cases for the workflows that this change would address.

 

This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.

 

Best regards,

 

Jeremy

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes