Server tags cannot contain constructs

I am trying to use CDN for my images on the website.
Problem is, sometimes I have server controls such as ImageButton, and I would like to use a class in order to fully extract the path of the CDN. for that purpose I tried doing:

<asp:ImageButton runat="server" OnClick="Agree" ImageUrl="<%=ResourceManager.GetImageCDN("iagree.png")%>" />

and I get the title as error.

Only if I’m using <%# it will work (and only if I an databinding).
How can I do this easily? how can I place CDN code on my markup code?

Thanks!

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

There are four options (in addition to “<%# %>” style databinding, which I don’t recommend):

  1. Set the value in code behind. This inflates ViewState, and of course requires code changes for every instance of the control.
  2. Use a custom ExpressionBuilder. This doesn’t inflate ViewState, but it does require changing all of your markup.
  3. Use a Control Adapter to change the behavior of the control everywhere in your app; for example, by modifying the ImageUrl property before the control is rendered. Can be done with no ViewState impact.
  4. Use a class that inherits from the ImageButton class, combined with tag mapping to use that class instead of the original everywhere in your app, and eliminate the need for changes to your markup. Can be done with no ViewState impact.

The best option depends on your app’s requirements, but I usually prefer a control adapter if you want to make the changes site-wide.

Here’s an example, in case it helps:

using System;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.Adapters;

namespace Sample
{
    public class ImageButtonControlAdapter : WebControlAdapter
    {
        protected override void BeginRender(HtmlTextWriter writer)
        {
            ImageButton image = this.Control as ImageButton;
            if ((image != null) && !String.IsNullOrEmpty(image.ImageUrl))
            {
                //
                // Decide here which objects you want to change
                //
                if (!image.ImageUrl.StartsWith("http") && 
                    !image.ImageUrl.StartsWith("data:"))
                {
                    image.ImageUrl = ResourceManager.GetImageCDN(image.ImageUrl);
                }
            }
            base.BeginRender(writer);
        }
    }
}

Configure it into your app with the following entry in App_Browers/adapter.browser:

<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter controlType="System.Web.UI.WebControls.ImageButton"
               adapterType="Sample.ImageButtonControlAdapter" />
    </controlAdapters>
  </browser>
</browsers>

Your markup would be:

<asp:ImageButton runat="server" OnClick="Agree" ImageUrl="iagree.png" />

Cool, right??

Method 2

In case someone else comes across this thread in the future, you can get the required outcome by surrounding the server tag with single quotes, rather than double quotes.

The original:

<asp:ImageButton runat="server" OnClick="Agree" ImageUrl="<%=ResourceManager.GetImageCDN("iagree.png")%>" />

The new version:

<asp:ImageButton runat="server" OnClick="Agree" ImageUrl='<%=ResourceManager.GetImageCDN("iagree.png")%>' />

This works in .Net 4.0, but I would presume that it would work in the other versions too.

Method 3

You can evaluate code in a server tag by creating your own Code Expression Builder. It’s quite simple.

[ExpressionPrefix( "Code" )]
public class CodeExpressionBuilder : ExpressionBuilder
{
    public override CodeExpression GetCodeExpression( BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context )
    {
        return new CodeSnippetExpression( entry.Expression );
    }
}

And an entry in your web.config:

<compilation debug="true" targetFramework="4.0">
    <expressionBuilders>
        <add expressionPrefix="Code" type="[YourNamespace].CodeExpressionBuilder"/>
    </expressionBuilders>
</compilation>

This allows you to use a syntax such as:

<asp:ImageButton runat="server" ImageUrl='<%$ Code:ResourceManager.GetImageCDN("iagree.png") %>'>

Here’s a full explanation: http://weblogs.asp.net/infinitiesloop/archive/2006/08/09/The-CodeExpressionBuilder.aspx

Method 4

Of course, your best bet is to give the imagebutton an id, eg:

<asp:ImageButton id="IAgreeImageButton" runat="server" Onclick="Agree" />

And then within your page load assign the imageurl:

void Page_Load(...)
{
     if (!Page.IsPostback)
     {
          IAgreeImageButton.ImageUrl = ResourceManager.GetImageCDN("iagree.png");
     }
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x