Custom DotNet and Open XML SDK

SOLVED

Hello,

Using the .Net API, I hat developped a custom DotNet module that was creating a MsWord DOCX using the Microsoft.Interop.Word for a complex Merge situation, creating a documents with many tables.
It was working for small documents, but it was very slow (3 min for a 3 page document).
Timed out after 20 minutes for an expected 19 pages document.

I read many posts on-line recommending to use the "Open XML SDK" which is supposed to be much much faster (6 seconds instead of 5 minutes for example), but I can't get it to work with SageCRM .Net API.

1) I used NuGet in VS 2019 to install the latest version of "Open XML SDK" (DocumentFormat.OpenXml - v2.18 dated 2022-09-06)
2) Added the reference to my project and set "Copy Local = True"
3) Created a simple Test project
4) When deploying, the files DocumentFormat.OpenXml.dll and DocumentFormat.OpenXml.xml are copied to the "Sage\CRM\CRM\CustomDotNet" folder with the Project's DLL


I get this error at runtime:

Sep 12 2022 16:52:58.063 6884 1148 1 Class: CRMWrapper - Method: ExecWebPageNew - Error: An error has occurred on PreBuildContents or BuildContents
Sep 12 2022 16:52:58.070 6884 1148 5 StackTrace:
Error: Could not load file or assembly 'DocumentFormat.OpenXml, Version=2.18.0.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17' or one of its dependencies. The system cannot find the file specified.
at ExportDOCX.MyCustomPage.BuildContents()
at Sage.CRM.Wrapper.CRMWrapper.ExecWebPageNew(String fullFileName, String callFunction)

There is no dependencies for OpenXml with .Net 3.5.

I lost a lot of time this week trying to make this work.
Has anyone been able to work with the "Open XML SDK" in SageCRM ?

Thanks.

Parents
  • +1
    verified answer

    You're getting the problem because your custom CRM .Net assembly is only able to resolve dependencies from the GAC. This is why you didn't have an issue using the Word Interop - because that's installed into the GAC. Dependencies that you add via NuGet won't be GAC-ed.

    This is all because your custom CRM pages are loaded into their own AppDomain. It's possible to set the ApplicationPath and PrivateBinPath when creating a new ApDomain, and this tells the runtime where to start probing for private assemblies, but unfortunately these don't get set by SageCRMBase - so it'll only probe the GAC.

    Fortunately there's a simple fix : you just create a type initialiser for your AppFactory class and add a handler for the AppDomain's AssemblyResolve event in there. Then in the handler you can tell the runtime exactly where to find the dependency. There's a variety of ways to implement this, but see the post here for one way to do it :

    https://www.sagecity.com/sage-global-solutions/sage-crm/b/sage-crm-hints-tips-and-tricks/posts/accessing-other-assemblies-from-crm-net-dlls

  • 0 in reply to Chris Burke


    Thank you very much for the Hint !

    All I had to do is run the following command to put the OpenXML SDK 2.18 in the GAC and it's working.
    "c:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\gacutil.exe" /I DocumentFormat.OpenXml.dll

    I'll read more in detail the link you sent me, but your explanation was very clear to help me understand.

Reply
  • 0 in reply to Chris Burke


    Thank you very much for the Hint !

    All I had to do is run the following command to put the OpenXML SDK 2.18 in the GAC and it's working.
    "c:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\gacutil.exe" /I DocumentFormat.OpenXml.dll

    I'll read more in detail the link you sent me, but your explanation was very clear to help me understand.

Children
No Data