How many times you’ve run in to the issue where you see #error for any build in Reporting service fields (or even for some expressions for that matter) with role manager enabled for the ASP.NET site running on and above .NET framework 4.0? Whatever you do, nothing changes until you disable the Role manager? If that is the scenario, then you’re in the right place.

The web.config for a ASP.NET site on .NET Framework 4.0 and above with role manager enabled would look similar to this:

<roleManager defaultProvider="AspNetSqlRoleProvider" enabled="true">
      <providers>
        <clear/>
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="app1"/>
        <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="app1"/>
      </providers>
    </roleManager>

Please note that the above entries will differ according to the provider that you use for role manager.

Now, in the RDLC report, you have an expression like: =Globals!ExecutionTime within a text box. With these things in place, viewing the ASP.NET page that has the Report viewer control will show the page like:

Error

Alright, how would you fix this issue now? It’s that simple. On your page load event of the ASP.NET page that hosts the report viewer control, add the following line of code.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

ReportViewer1.LocalReport.SetBasePermissionsForSandboxAppDomain(AppDomain.CurrentDomain.PermissionSet.Copy())

End Sub

Though the above code is in VB.NET, it should be a straight forward conversion to C#. Hence I’m not pasting that here Smile

Once you add the piece of code, the magic will happen and the report will look like below:

Error

Want to know the reason behind the issue and why the code fixes it?

With RoleManager enabled, the thread identity is set to an instance of System.Security.Principal.GenericIdentity.  This object uses marshal by value across the app domain boundary.  During deserialization, it attempts to access the WindowsIdentity.Name property, which internally performs a security demand for ControlPrincipal permission.  In our sandbox appdomain, the appdomain has execute only permission and fails this check.  It looks like the identity should either be marshaled by reference or assert the necessary permissions to deserialize itself in a low privilege environment.

What the above piece of code will do is, it will force the sandbox app domains to assert the necessary permission and this ensures even during the deserialization process the correct set of credentials are preserved to get us the right output.

Happy learning!

HTH!

Selva.

[All the posts are AS-IS with no warranty]