2012-09-22 44 views
1

我正在爲使用.NET 4.0和IIS 7的客戶端構建數據庫編輯器/業務線工具。我想根據存儲的值有條件地在頁面中包含一些HTML會話。我在服務器端做這件事,爲了封裝代碼,我創建了一個ASP服務器控件。如你所見,Server Control生成的標記並不是我所期望的。我希望以前有人看到過,並能幫助我理解如何控制標記生成輸出。服務器控件生成意外標記

下面是一個名爲MyList的控件的新RenderContents。它應該使用<li>標籤生成新的列表條目。

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

編制主體工程,並增加MYLIST的引用之後,我用MYLIST下面的HTML:

<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的頁屬性提供我控件容器的引用,並由此進入我的會議:

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(); 
} 

現在標記開始顯現出來了。注意,在「×1」的矛盾:

<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()中設置斷點時,只有當我連續放置5個標籤時纔會調用一次斷點。

其他信息: 帶有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> 

現在你知道我做的一切!

回答

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將爲空。您應該檢查空值,或者檢查您是否在設計模式下運行:

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

優秀,徹底的答案,我很感激。 –

0

避免System.Web.UI.WebControls。我建議你直接子類System.Web.UI.Control

<span>正在由您從中衍生的類插入(您未提及)。請注意,您優先於RenderContents而不是Render,這意味着控制超類可以自由地將RenderContents的輸出與其所希望的任何內容包裝在一起,在此情況下爲<span>

+0

謝謝!你給了我一些很好的選擇。 –