我正在为使用.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>
现在我根据会话值添加测试。 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>
现在你知道我所做的一切!
答案 0 :(得分:1)
您只需覆盖自定义服务器控件中的WebControl.TagKey
属性:
protected override HtmlTextWriterTag TagKey
{
get { return HtmlTextWriterTag.Li; }
}
默认值为Span
,它解释了您所看到的内容。当然,如果您这样做,则不会在RenderContents
覆盖中呈现Li标记。
另一种方法是覆盖Render
,完全控制渲染,或者从Control
派生。但是你会丢失WebControl
的一些功能,特别是外部标签的样式。
关于你的第二个问题,你打电话:
output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);
添加一个样式属性,以应用于RenderBeginTag
的下一次调用。您无法调用RenderBeginTag
,因此这将应用于树中下一个控件中的标记。
在Visual Studio设计器中呈现控件时,另一点是Session
将为null。您应该检查null,或者检查您是否在设计模式下运行:
if ((Site != null) && (Site.DesignMode))
{
... running in design mode, Session won't be available
}
答案 1 :(得分:0)
避免使用System.Web.UI.WebControls
。我建议你直接子类System.Web.UI.Control
。
<span>
正由您派生的类插入(您未提及)。请注意,您将覆盖RenderContents
而不是Render
,这意味着控件超类可以随意包装RenderContents
的输出,在这种情况下<span>