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



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

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

以下是名为MyList的控件的新RenderContent。它应该使用<李>标签

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属性为我提供了对控件容器的引用,从而访问我的会话:

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'指的是我的'real'控件,我简化了它以隔离问题并缩短这篇文章):

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

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

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

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

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

另一种选择是覆盖Render,完全控制渲染,或者从Control派生。但您将失去WebControl的一些功能,尤其是外部标签的样式。

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

output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);

其向CCD_ 9添加要应用于下一次调用的样式属性。您不调用RenderBeginTag,因此这将应用于树中下一个控件中的标记。

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

if ((Site != null) && (Site.DesignMode))
{
... running in design mode, Session won't be available
}

避免System.Web.UI.WebControls。我建议您直接将System.Web.UI.Control划分为子类。

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

相关内容

  • 没有找到相关文章

最新更新