Bookmark and Share

Thursday, May 20, 2010

Migrating external assemblies used in RDLC from VS2005 to VS2010

If you are using ReportViewer and RDLC reports in visual studio 2005 you may use externals assemblies for additional rules and formulas, in order to enable external assemblies you need to call the AddTrustedCodeModuleInCurrentAppDomain function.
rv.LocalReport.AddTrustedCodeModuleInCurrentAppDomain("MyLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");

Porting this code  to VS2010 without changes will generate the exception:

Exception of type 'System.Web.HttpException' was thrown.
Exception of type 'System.Web.HttpUnhandledException' was thrown.
Report execution in the current AppDomain requires Code Access Security policy,
which is off by default in .NET 4.0 and later.
Enable legacy CAS policy or execute the report in the sandbox AppDomain.

With the exception detail:

Exception of type 'System.Web.HttpException' was thrown.
Exception of type 'System.Web.HttpUnhandledException' was thrown.
at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.Util.AspCompatApplicationStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Exception of type 'System.Web.HttpException' was thrown.
Exception of type 'System.Web.HttpUnhandledException' was thrown.
Report execution in the current AppDomain requires Code Access Security policy, which is off by default in .NET 4.0 and later. Enable legacy CAS policy or execute the report in the sandbox AppDomain.
at Microsoft.Reporting.WebForms.LocalReport.ReportRuntimeSetupHandler.AddTrustedCodeModuleInCurrentAppDomain(String assemblyName)
at Microsoft.Reporting.WebForms.LocalReport.AddTrustedCodeModuleInCurrentAppDomain(String assemblyName)
at Web.Report.OnInit(EventArgs e) in C:\inetpub\wwwroot\Web\Report.aspx.cs:line 500
at System.Web.UI.Control.InitRecursive(Control namingContainer)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)


The solution is to use the new AddFullTrustModuleInSandboxAppDomain function, using the SetBasePermissionsForSandboxAppDomain function, here is an example:



using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
//...
//... 
PermissionSet permissions = new PermissionSet(PermissionState.None);
permissions.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
rv.LocalReport.SetBasePermissionsForSandboxAppDomain(permissions);
Assembly asm = Assembly.Load("MyLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
AssemblyName asm_name = asm.GetName();
rv.LocalReport.AddFullTrustModuleInSandboxAppDomain(new StrongName(new StrongNamePublicKeyBlob(asm_name.GetPublicKeyToken()), asm_name.Name, asm_name.Version));

Hope it helps!, and happy coding!