I'm trying to write a MS Dynamics CRM 2011 plugin to run in sandbox mode but utilizes classes from a GAC'd assembly. I'm running into an issue where creating a List of a type from the GAC'd assembly is generating an error and I don't understand why. The exception being generated is of type System.MethodAccessException
and has this message:
Attempt by method 'IsolatedModeExceptionsTestingPlugin.Plugin.Execute(System.IServiceProvider)' to access method 'System.Collections.Generic.List`1<System.__Canon>..ctor()' failed.
Can someone explain why this is failing so that I can modify my code/environment to address the failure?
I've recreated the scenario in a simple set of classes below.
I ran my tests on a Win2008 R2 server running Dynamics 2011 Rollup 7, then again on Rollup 11. Both my assemblies are built against .Net 4.0 and the Dynamics IIS AppPool is configured for .Net 4. Both assemblies are signed (using the same key pair).
Note that if I change the plugin's isolation mode from "sandbox" to "none", the plugin works fine -- it's only in sandbox mode that this occurs, which implies some sort of security violation when generating a List<>. Note also that creating a List (or other .Net types) works fine, as does creating a List<> of classes within my own assembly. It seems to be specific to GAC'd assemblies.
The assembly I'm placing in the GAC is named "ClassLibrary1" and contains only one class:
namespace ClassLibrary1
{
public class MyCustomAssemblyClass
{
public string GetAString()
{
return "The current time is " + System.DateTime.Now.ToString();
}
}
}
I placed it in the GAC by running the following on the server (which has the Windows SDK v7.1 installed): "c:\program files\Windows SDKs\Windows\v7.1\bin\NETFX 4.0 Tools\gacutil.exe" -i classlibrary1.dll
My plugin code then looks like this:
using System.Collections.Generic;
using System.Text;
using System;
using ClassLibrary1;
using Microsoft.Xrm.Sdk;
namespace IsolatedModeExceptionsTestingPlugin
{
public class Plugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var pluginExecutionContext = (IPluginExecutionContext) serviceProvider.GetService(typeof (IPluginExecutionContext));
var tracingService = (ITracingService) serviceProvider.GetService(typeof (ITracingService));
try
{
tracingService.Trace("Entered Plugin.Execute()");
tracingService.Trace(string.Format("Isolation Mode: {0}, Mode: {1}\n\n",
pluginExecutionContext.IsolationMode,
pluginExecutionContext.Mode));
try
{
tracingService.Trace(string.Format("*** Creating List<{0}>", typeof (MyCustomAssemblyClass)));
var list = new List<MyCustomAssemblyClass>(); //XXX Exception thrown here!!
tracingService.Trace(" Success");
}
catch (Exception ex)
{
tracingService.Trace(GetExpectionTraceMessage(ex));
throw new Exception("An error occurred in one of the tests", ex);
}
finally
{
tracingService.Trace("*** Finished TestListOfGACClassCxtr\n\n");
}
//This will force a failure to allow viewing of the trace file
// throw new Exception("TEST SUCCESSFULL");
}
finally
{
tracingService.Trace("Exiting Plugin.Execute()");
}
}
private string GetExpectionTraceMessage(Exception ex)
{
var message = new StringBuilder();
message.AppendFormat("EXCEPTION: {0}\n", ex.GetType());
message.AppendFormat("\tMessage: {0}\n", ex.Message);
message.AppendFormat("\tStack: {0}\n", ex.StackTrace);
if (ex.InnerException != null)
{
message.AppendLine("---- INNER EXCEPTION ----");
message.AppendLine(GetExpectionTraceMessage(ex.InnerException));
}
return message.ToString();
}
}
}
I registered the plugin to run in sandbox mode from the database when an entity is updated. Upon execution of the plugin, I get the following output via the Business Process Error dialog's "Download Log File":
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Unexpected exception from plug-in (Execute): IsolatedModeExceptionsTestingPlugin.Plugin: System.Exception: An error occurred in one of the testsDetail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
<ErrorCode>-2147220956</ErrorCode>
<ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<Message>Unexpected exception from plug-in (Execute): IsolatedModeExceptionsTestingPlugin.Plugin: System.Exception: An error occurred in one of the tests</Message>
<Timestamp>2012-11-29T18:09:26.5671559Z</Timestamp>
<InnerFault i:nil="true" />
<TraceText>
[IsolatedModeExceptionsTestingPlugin: IsolatedModeExceptionsTestingPlugin.Plugin]
[6d245108-b638-e211-bae5-000c29d5e4ba: IsolatedModeExceptionsTestingPlugin.Plugin: Update of new_insurancequote]
Entered Plugin.Execute()
Isolation Mode: 2, Mode: 0
*** Creating List<ClassLibrary1.MyCustomAssemblyClass>
EXCEPTION: System.MethodAccessException
Message: Attempt by method 'IsolatedModeExceptionsTestingPlugin.Plugin.Execute(System.IServiceProvider)' to access method 'System.Collections.Generic.List`1<System.__Canon>..ctor()' failed.
Stack: at IsolatedModeExceptionsTestingPlugin.Plugin.Execute(IServiceProvider serviceProvider)
*** Finished TestListOfGACClassCxtr
Exiting Plugin.Execute()
</TraceText>
</OrganizationServiceFault>
For reference, the System.__Canon type seems to be used by the .Net framework to create reusable code at JIT for all generics. See: http://www.marklio.com/marklio/PermaLink,guid,1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9.aspx