Working around "Cannot create an object of type 'System.Boolean' from its string representation"

by Sander Gerz April 18, 2009 21:05
In ASP.NET Web Forms most times there’s a need to set ASP.NET Server Control properties at runtime. This, for instance:
<asp:Button runat="server" id="Button1" visible="true" />

It is pretty straightforward to set the value of the visible-property in a code-behind page, like so:

protected void Page_Load(object sender, EventArgs e)
{
Button1.Visible = false;
}

However, it would be nice if you could to things like this

<asp:Button runat="server" id="Button1" visible='<% =User.IsInRole("Editor")%>' />

One might expect that that the expression above is evaluated such that the visible-property is true when the current User has the role of Editor and false if not. Unfortunately, executing this bit results in an exception:
Cannot create an object of type 'System.Boolean' from its string representation
'<%= User.IsInRole("Editor") %>' for the 'Visible' property. 
These problems are discussed also here and here. The reason is that the string-value of each property on a server-control is evaluated and parsed to its desired type. So you could set the property to "True" or "true", but not to an expression that needs to be evaluated.
The solution is to use a databinding syntax, which is pretty easy to do
<asp:Button runat="server" id="Button1" visible='<%# User.IsInRole("Editor") %>' />

As you can see, we simply add the pound/hash sign and remove the equals from the expression. This databind-expression is interpretered quite differently at runtime.

  • <%= %> is in reality the same thing as Response.Write().

  • <%# %> is more in related to assigning a value to an object. In the ASP.NET lifecycle, the <%# %> operators are evaluated before the page writes the first byte to the response buffer.

The problem with using a databinding expression is that you need to execute a DataBind() method either on the control itself or on the entire page. Executing DataBind() at page level can have negative side effects when you have multiple controls on the page with associated databinding logic. DataBind() at pagelevel triggers events, perhaps at times when you don’t want them. Using DataBind() in the codebehind for relevant controls defeats the idea a bit that we want to set a property with some simple rules and preferably in one place only.

A solution for this is to add another property (or attribute if you will), that just executes DataBind() on the current control. Something like this:

<asp:Button runat="server" id="Button1" visible='<%# User.IsInRole("Editor")%>'
code='<% DataBind(); %>' />

 

Unfortunately, that doesn’t work, because at runtime, the ASP.NET rendering engine will complain that a Button-control doesn’t have a property “code” so it doesn’t know what to do with it. However, we can trick it to ignore the property for rendering, but still execute the code, like so:

<asp:Button runat="server" id="Button1" visible='<%# User.IsInRole("Editor")%>' meta:code='<% DataBind(); %>' />


Prefixing the attribute with the text meta: with make the renderer ignore the value, but the code will still execute. Please note that the example uses meta:code, but it doesn’t really matter what name you give the attribute. It could be meta:execute or meta:whateveryouwant, as long as it’s not meta:resourceKey, because that property has special meaning.

It may not be the most elegant solution, but hey, if it works, I’m ok with it. With the rise of ASP.NET MVC we’ll probably see more of this type of coding anyway.

Currently rated 2.9 by 76 people

  • Currently 2.881579/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Comments

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen | Modified by Mooglegiant