I'm using the Microsoft Reporting Services in a .NET Framework 4.8 application, using the LocalReport class to rendere a .rdlc report.
In my report, I'm using some custom code from some additional assemblies, that I added to the report via de Report Properties -> References menu.
In my code, when I render the report, I add the assemblies do the LocalReport domain to make them available in the report, with some code like this:
var assemblyName = myCustomAssembly.GetName();
var strongAssemblyName = new StrongName(new StrongNamePublicKeyBlob(assemblyName.GetPublicKeyToken()), assemblyName.Name, assemblyName.Version)
localReport.AddFullTrustModuleInSandboxAppDomain(strongAssemblyName);
Now, this works perfectly... but only if the .DLL that contains the assembly I'm trying to add is in the same folder as my executable. If it is somewhere else (for example, in my case, in a subfolder) the report generation fails, with an exception telling me assembly could not be loaded because the dll file could not be found.
Is there a way to solve this? Can I tell the LocalReport to load the assemblies from a specific folder, or add a search path in some way? Or is the only solution to have the assemblies in the root folder of my app?
So, a lot of answers to other posts here on SO suggested to make it work by adding the subfolder(s) I needed to the domain's
SetupInformation.PrivateBinPathproperty. This, however, didn't seem to have any effect at all. In fact, if I read theSetupInformation.PrivateBinPathproperty immediately after setting it, I gotnullin return.So, I've dug deeper and decompiled part of the .NET Framework source code to get to the bottom of it.
First of all: it should be noted that the report processing happens in a sandboxed
AppDomainthat is created specifically for generating the report, it doesn't run directly on the app's main domain. However, by decompiling theReportViewerassemblies, I've found that the sandboxed domain is constructed with the setup information taken from the baseAppDomain.CurrentDomain.SetupInformation, so any paths set there should also be available to the report generation.From what I can see, the root problem is this: the
SetupInformationproperty of theAppDomainclass seems to return a copy of theSetupInformation. So, setting anything in there is absolutely useless, because you're operating on a copy that is then discarded.What ended up working, was setting this property in the
App.configfile, like this:and that solved the issue!
I'm still curious if there is a way to actually set the probing path dynamically in code rather than having it hardcoded in the .config file, any comment in that direction is welcome.