Implicit casting in DataRepeater not working in certain scenarios after SP1

Problem

Using the following VB-syntax in a DataRepeater will no longer work after applying .NET Framework 2.0 Service Pack 1 in a medium-trust environment.

<asp:Repeater ID="Repeater1" runat="server">
        <ItemTemplate>
               <%#Container.DataItem("data")%><br />
        </ItemTemplate>
</asp:Repeater>

 

Resolution

Use Eval-method, as recommended in all Microsoft documentation. Using explicit casting would work as well, but you'd have to re-write every page if you decide to change your data layer.


 

Repro

Create an ASP.NET page with a repeater using a simple OleDb database as it's DataSource.

If you run this application in full trust, you should encounter no problems.

Now, set the trust level to medium. (You'll have to modify the settings and give it access to OleDbConnections.) When you run it you'll get a Security Exception:

Security Exception
Description: The application attempted to perform an operation not allowed by the security policy.  To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file.

Exception Details: System.Security.SecurityException: Request failed.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. 

Stack Trace:

[SecurityException: Request failed.]
   System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Assembly asm, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed) +150
   System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Object assemblyOrString, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed) +100
   System.Security.CodeAccessSecurityEngine.CheckSetHelper(PermissionSet grants, PermissionSet refused, PermissionSet demands, RuntimeMethodHandle rmh, Object assemblyOrString, SecurityAction action, Boolean throwException) +281
   System.Security.PermissionSetTriple.CheckSetDemand(PermissionSet demandSet, PermissionSet& alteredDemandset, RuntimeMethodHandle rmh) +67
   System.Security.PermissionListSet.CheckSetDemand(PermissionSet pset, RuntimeMethodHandle rmh) +145
   System.Security.PermissionListSet.DemandFlagsOrGrantSet(Int32 flags, PermissionSet grantSet) +43
   System.Threading.CompressedStack.DemandFlagsOrGrantSet(Int32 flags, PermissionSet grantSet) +41
   System.Security.CodeAccessSecurityEngine.ReflectionTargetDemandHelper(Int32 permission, PermissionSet targetGrant, CompressedStack securityContext) +139
   System.Security.CodeAccessSecurityEngine.ReflectionTargetDemandHelper(Int32 permission, PermissionSet targetGrant) +51

 

Cause and resolution

Visual Basic has always been strong on implicit casting. For example, this code is completely valid:

Dim myString As String = 10

So, in the sample at the top, Container.DataItem is merely an Object. VB then casts this to a System.Data.Common.DbDataRecord object and we're able to retrieve the "data"-property. This is no longer working after Service Pack 1.

C, in all its variations wouldn't be caught dead accepting a syntax like String = Integer, so the code at the top would never work. Instead you'd have to explicitly cast the object to the appropriate type:

<asp:Repeater ID="Repeater1" runat="server">
        <ItemTemplate>
               <%#((System.Data.Common.DbDataRecord)Container.DataItem)["data"]%><br />
        </ItemTemplate>
</asp:Repeater>

If you change the VB code so that it uses the VB equivalent: CType you will resolve the problem.

So, is the resolution to use explicit casting? Well, not really. If you look at the C# example above you might notice a potential problem. If we change our data layer we would have to go through every single page and change the explicit casting. This is one of the reasons why we've always recommended using the Databinder.Eval method for VB and C# alike, so if you've followed the design guidelines your code should look like this:

<asp:Repeater ID="Repeater1" runat="server">
        <ItemTemplate>
               <%#DataBinder.Eval(Container.DataItem, "data")%><br />
        </ItemTemplate>
</asp:Repeater>

Actually, as of Framework 2.0 it's enough to write Eval("data").

So, if you review the documentation on msdn for Framework 1.1, Framework 2.0, knowledge base articles, etc. you'll see that we consistently recommend using the Eval method.

/ Johan