首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >服务器控件生成意外的标记

服务器控件生成意外的标记
EN

Stack Overflow用户
提问于 2012-09-22 12:17:31
回答 2查看 226关注 0票数 1

我正在为使用HTML4.0和IIS7的客户端构建一个数据库编辑器/业务流程工具。我希望根据存储在会话中的值,有条件地在我的页面中包含一些.NET。我在服务器端这样做,为了封装代码,我创建了一个ASP服务器控件。

正如您将看到的,由服务器控件生成的标记并不是我所期望的。我希望有人之前已经看到了这一点,可以帮助我理解如何控制标记生成输出。

这是一个名为MyList的控件的新RenderContents。它应该使用标签生成新的列表条目。

代码语言:javascript
复制
protected override void RenderContents(HtmlTextWriter output) {
    output.RenderBeginTag(HtmlTextWriterTag.Li);
    output.WriteEncodedText(this.Text);
    output.RenderEndTag();
}

在编译了主项目并添加了对MyList的引用后,我在下面的HTML中使用了MyList:

代码语言:javascript
复制
<h1>Favorite Things</h1>
<ul>
    <cc1:MyList ID="mL1" runat="server" Text="Code that works!" />
    <cc1:MyList ID="mL2" runat="server" Text="Going home before 8" />
    <cc1:MyList ID="mL3" runat="server" Text="Cold drinks in fridge" />
</ul>

它会生成以下代码:

代码语言:javascript
复制
<h1>Favorite Things</h1>
<ul>
    <span id="MainContent_mL1"><li>Code that works!</li></span>
    <span id="MainContent_mL2"><li>Going home before 8</li></span>
    <span id="MainContent_mL3"><li>Cold drinks in fridge</li></span>
</ul>

现在,我添加一个基于会话值的测试。WebControl的Page属性为我提供了对控件容器的引用,从而访问我的会话:

代码语言:javascript
复制
protected override void RenderContents(HtmlTextWriter output) {
    string backcolor = "Yellow";
    if (this.Page.Session["access"] == null) {
        backcolor = "Red";
    }
    output.RenderBeginTag(HtmlTextWriterTag.Li);
    output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);
    output.WriteEncodedText(this.Text);
    output.RenderEndTag();
}

现在标记开始解开了。注意‘ml1’中的不一致:

代码语言:javascript
复制
<h1>Favorite Things</h1>
<ul>
    <span id="MainContent_mL1"><li>Code that works!</li></span>
    <span id="MainContent_mL2" style="background-color:Red;"><li>Going home before 8</li></span>
    <span id="MainContent_mL3" style="background-color:Red;"><li>Cold drinks in fridge</li></span>
</ul>

在我的实际代码中,它更复杂,标记只变成了span标记。而且,当我在RenderContents()中设置断点时,当我有五个连续的标签时,它只被调用一次。

其他信息:带有cc1:MyList控件的页面有EnableSession=true。我的web.config指定了正常的会话管理器('rml','RoleBasedList‘指的是我的’真正‘控制,我简化了这个控制,以隔离问题并使本文更简短):

代码语言:javascript
复制
<system.web>
    <trace enabled="true" localOnly="false" pageOutput="true" requestLimit="20" />
    <compilation debug="true" targetFramework="4.0" />
    <pages>
        <controls>
            <add tagPrefix="rml" assembly="RoleBasedList" namespace="SOTS.ServerControls"/>
        </controls>
    </pages>
    <httpModules>
      <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
    </httpModules>

    <sessionState mode="InProc" cookieless="false" timeout="60"/>
    ...
</system.web>

现在你知道我做的一切了!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-09-23 01:50:06

您只需覆盖自定义服务器控件中的WebControl.TagKey属性:

代码语言:javascript
复制
protected override HtmlTextWriterTag TagKey
{
    get { return HtmlTextWriterTag.Li; }
}

默认值为Span,它解释了您所看到的内容。当然,如果这样做,就不会在RenderContents覆盖中呈现Li标记。

另一种方法是覆盖Render,完全控制渲染,或者从Control派生。但是您将失去WebControl的一些特性,特别是外部标记的样式。

关于您的第二个问题,您正在调用:

代码语言:javascript
复制
output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);

这将添加一个样式属性,该属性将应用于下一次对RenderBeginTag的调用。您不会调用RenderBeginTag,因此这将应用于树中下一个控件中的标记。

另一点是,当您的控件在Visual Studio designer中呈现时,Session将为空。您应该检查是否为null,或者检查您是否在设计模式下运行:

代码语言:javascript
复制
if ((Site != null) && (Site.DesignMode))
{
    ... running in design mode, Session won't be available
}
票数 1
EN

Stack Overflow用户

发布于 2012-09-22 22:31:26

避免使用System.Web.UI.WebControls。我建议你直接继承System.Web.UI.Control的子类。

<span>是由您从中派生的类插入的(您还没有提到)。注意,您覆盖的是RenderContents而不是Render,这意味着控件超类可以自由地用它想要的任何东西包装RenderContents的输出,在本例中是<span>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12540658

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档