1

我正在使用 .NET 4.0 和 IIS 7 为客户端构建数据库编辑器/业务线工具。我想根据存储在 Session 中的值有条件地在我的页面中包含一些 HTML。我在服务器端执行此操作,为了封装代码,我创建了一个 ASP 服务器控件。

正如您将看到的,服务器控件生成的标记不是我所期望的。我希望有人以前见过这个并且可以帮助我了解如何控制标记生成输出。

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

protected override void RenderContents(HtmlTextWriter output) {
    output.RenderBeginTag(HtmlTextWriterTag.Li);
    output.WriteEncodedText(this.Text);
    output.RenderEndTag();
}

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

<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>

它生成以下内容:

<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>

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

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”中的不一致:

<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”指的是我的“真实”控件,我对其进行了简化以隔离问题并使这篇文章更短):

<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>

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

4

2 回答 2

1

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

protected override HtmlTextWriterTag TagKey
{
    get { return HtmlTextWriterTag.Li; }
}

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

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

关于您的第二个问题,您正在致电:

output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);

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

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

if ((Site != null) && (Site.DesignMode))
{
    ... running in design mode, Session won't be available
}
于 2012-09-22T17:50:06.263 回答
0

避免System.Web.UI.WebControls。我建议你System.Web.UI.Control直接继承。

正在由您派生的<span>类插入(您没有提到)。请注意,您正在覆盖RenderContents而不是Render,这意味着控件超类可以随意包装 的输出RenderContents,在本例中为<span>

于 2012-09-22T14:31:26.340 回答