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

C# 服务器控件生成意外的标记,c#,asp.net,.net,htmltextwriter,C#,Asp.net,.net,Htmltextwriter,我正在使用.NET 4.0和IIS 7为客户机构建一个数据库编辑器/业务线工具。我想根据会话中存储的值,在页面中有条件地包含一些HTML。我在服务器端执行此操作,为了封装代码,我创建了一个ASP服务器控件 正如您将看到的,服务器控件生成的标记不是我所期望的。我希望有人以前见过这一点,并能帮助我理解如何控制标记生成输出 下面是一个名为MyList的控件的新RenderContent。它应该使用标记生成新的列表条目 protected override void RenderContents(Htm

我正在使用.NET 4.0和IIS 7为客户机构建一个数据库编辑器/业务线工具。我想根据会话中存储的值,在页面中有条件地包含一些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>
    
    现在,标记开始分解。注意“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>
    

    现在你知道我做的一切了

    避免
    System.Web.UI.WebControls
    。我建议您直接子类化
    System.Web.UI.Control


    由您派生的类插入(您没有提到)。请注意,您正在覆盖
    RenderContents
    ,而不是
    Render
    ,这意味着控件超类可以随意包装
    RenderContents
    的输出,在这种情况下

    避免
    System.Web.UI.WebControls
    。我建议您直接子类化
    System.Web.UI.Control


    由您派生的类插入(您没有提到)。请注意,您正在重写
    RenderContents
    ,而不是
    Render
    ,这意味着控件超类可以随意将
    RenderContents
    的输出包装为任何内容,在这种情况下

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

    protected override HtmlTextWriterTag TagKey
    {
        get { return HtmlTextWriterTag.Li; }
    }
    
    默认值为
    Span
    ,这解释了您看到的内容。当然,如果这样做,就不会在
    RenderContents
    override中渲染Li标记

    另一种方法是重写
    渲染
    ,完全控制渲染,或者从
    控件
    派生。但您将失去
    WebControl
    的一些功能,尤其是外部标签的样式

    关于第二个问题,您正在拨打:

    output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);
    
    它添加了一个要应用于下一次调用
    RenderBeginTag
    的样式属性。您不调用
    RenderBeginTag
    ,因此这将应用于树中下一个控件中的标记

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

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

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

    protected override HtmlTextWriterTag TagKey
    {
        get { return HtmlTextWriterTag.Li; }
    }
    
    默认值为
    Span
    ,这解释了您看到的内容。当然,如果这样做,就不会在
    RenderContents
    override中渲染Li标记

    另一种方法是重写
    渲染
    ,完全控制渲染,或者从
    控件
    派生。但您将失去
    WebControl
    的一些功能,尤其是外部标签的样式

    关于第二个问题,您正在拨打:

    output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);
    
    它添加了一个要应用于下一次调用
    RenderBeginTag
    的样式属性。您不调用
    RenderBeginTag
    ,因此这将应用于树中下一个控件中的标记

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

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

    非常好,彻底的回答,我很感激。非常好,彻底的回答,我很感激。