服务器标签不能包含<%...%>结构体

时间:2012-01-05 05:34:05

标签: c# asp.net

我正在尝试将CDN用于网站上的图像。 问题是,有时我有服务器控件,如ImageButton,我想使用一个类,以完全提取CDN的路径。为此我试着做了:

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

我将标题视为错误。

只有当我使用&lt;%#时它才会起作用(并且只有在我进行数据绑定时)。 我怎么能这么容易做到?如何将CDN代码放在我的标记代码上?

谢谢!

4 个答案:

答案 0 :(得分:23)

有四个选项(除了“<%# %>”样式数据绑定,我不推荐):

  1. 在代码后面设置值。这会使ViewState膨胀,当然也需要对控件的每个实例进行代码更改。
  2. 使用自定义ExpressionBuilder。这不会使ViewState膨胀,但它确实需要更改所有标记。
  3. 使用控制适配器在应用中的任何位置更改控件的行为;例如,通过在呈现控件之前修改ImageUrl属性。可以在没有ViewState影响的情况下完成。
  4. 使用继承自ImageButton类的类,结合标记映射,在应用程序的任何位置使用该类而不是原始类,并且无需更改标记。可以在没有ViewState影响的情况下完成。
  5. 最佳选择取决于您应用的要求,但如果您想在网站范围内进行更改,我通常更喜欢控制适配器。

    以下是一个示例,如果它有帮助:

    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);
            }
        }
    }
    

    使用App_Browers / adapter.browser中的以下条目将其配置到您的应用中:

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

    您的标记将是:

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

    很酷,对吧?

答案 1 :(得分:23)

如果将来其他人遇到此线程,您可以通过使用单引号而不是双引号来包含服务器标记来获得所需的结果。

原文:

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

新版本:

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

这适用于.Net 4.0,但我认为它也适用于其他版本。

答案 2 :(得分:12)

您可以通过创建自己的代码表达式生成器来评估服务器标记中的代码。这很简单。

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

你的web.config中的一个条目:

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

这允许您使用如下语法:

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

以下是完整的解释:http://weblogs.asp.net/infinitiesloop/archive/2006/08/09/The-CodeExpressionBuilder.aspx

答案 3 :(得分:2)

当然,最好的办法是给imagebutton一个id,例如:

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

然后在您的页面加载中分配imageurl:

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