2011-03-10 83 views
8

當我生成我控制在ASP.net他們出來是這樣的:ASP.net渲染HTML很好(美化)

<div id="ctl00_mainContent_ApprovalSelectPanel" class="discussWrapper"> 

     <span class="cbox highlighted"><input id="ctl00_mainContent_ctl00" type="checkbox" name="ctl00$mainContent$ctl00" checked="checked" value="70" /><label for="ctl00_mainContent_ctl00">Buyer1</label></span><span class="cbox"><input id="ctl00_mainContent_ctl01" type="checkbox" name="ctl00$mainContent$ctl01" value="75" /><label for="ctl00_mainContent_ctl01">Buyer2</label></span><span class="cbox"><input id="ctl00_mainContent_ctl02" type="checkbox" name="ctl00$mainContent$ctl02" value="280" /><label for="ctl00_mainContent_ctl02">Client3</label></span><span class="cbox"><input id="ctl00_mainContent_ctl03" type="checkbox" name="ctl00$mainContent$ctl03" value="281" /><label for="ctl00_mainContent_ctl03">Client4</label></span><span class="cbox"><input id="ctl00_mainContent_ctl04" type="checkbox" name="ctl00$mainContent$ctl04" value="283" /><label for="ctl00_mainContent_ctl04">Client2</label></span><span class="cbox"><input id="ctl00_mainContent_ctl05" type="checkbox" name="ctl00$mainContent$ctl05" value="289" /><label for="ctl00_mainContent_ctl05">Client1</label></span><span class="cbox"><input id="ctl00_mainContent_ctl06" type="checkbox" name="ctl00$mainContent$ctl06" value="346" /><label for="ctl00_mainContent_ctl06">artworker1</label></span><span class="cbox"><input id="ctl00_mainContent_ctl07" type="checkbox" name="ctl00$mainContent$ctl07" value="362" /><label for="ctl00_mainContent_ctl07">buyer3</label></span><span class="cbox"><input id="ctl00_mainContent_ctl08" type="checkbox" name="ctl00$mainContent$ctl08" value="367" /><label for="ctl00_mainContent_ctl08">meeeee</label></span><span class="cbox"><input id="ctl00_mainContent_ctl09" type="checkbox" name="ctl00$mainContent$ctl09" value="368" /><label for="ctl00_mainContent_ctl09">stake</label></span> 

    </div> 

漂亮的醜陋不堪,當您查看源理解。這通常不是問題,但我的網站提供訪問者資源和教程,其中查看源是體驗的一部分。

有什麼辦法可以很好地渲染這些控件嗎?正確縮進,更好的ID和名稱等?

+4

你不會用webforms獲得漂亮的源代碼。如果你想使用ASP.NET MVC是一個更好的主張。 – UpTheCreek 2011-03-10 12:10:08

+0

我個人發現,這些名字(儘可能長和「醜」)是一種非常明智的方式,特別是涉及中繼器,嵌套控件,模板和幾乎「一切都不重要」的場景。只需使用更好的CSS類/選擇器(避免用於ASP.NET控件的基於ID的選擇器)和數據綁定(以避免對客戶端ID進行硬編碼),並*不會*將生成的名稱視爲靜態資源。 – 2012-11-08 19:53:44

回答

14

在.NET 4.0中,您可以將ClientIDMode設置爲4個選項AutoID,Static,Predictable和Inherit之一。您可能正在尋找Static,因爲這將確保您的控件使用您分配給它們的ID呈現給頁面。

您可以通過添加應用程序級別設置:

<pages clientIDMode="Static"> 

到Web.config

有這些變化在這裏更多的細節:http://beyondrelational.com/blogs/hima/archive/2010/07/16/all-about-client-id-mode-in-asp-net-4.aspx

+0

這對於ID感謝,對於縮進和換行符有什麼想法? – 2011-03-10 11:39:12

+0

這太棒了。這是否適用於名稱以及ID或ID?這將使腳本和CSS比以前更容易。非常感謝:) – 2011-03-10 12:19:43

+0

男人,希望我在編寫ASP.NET 2.0應用程序時有這種感覺。 – 2011-04-04 17:16:49

2

獲得相當輸出是怎麼回事幾乎是不可能的,因爲解析器在呈現控件時沒有任何上下文的概念。許多控件呈現多個HTML元素,並且他們需要知道他們的上下文來做到這一點...以及能夠知道需要什麼樣的格式(例如,對於列表控件,何時開始新行,何時再次縮進)。

此外,並非標記中的所有元素都實際呈現,並且標記的佈局並不總是與輸出的佈局直接相關。例如:

<asp:PlaceHolder runat="server" /> 
    <asp:Panel runat="server" /> 
     <asp:DropDownList runat="server" /> 
    </asp:Panel /> 
</asp:PlaceHolder /> 

Placeholder不呈現,所以會造成在輸出或不縮進? DropDownList呈現多個HTML控件,並且無法確定所需的呈現方式:是否縮進與第一個控件相同的級別?它應該渲染時沒有元素間間隔?從實際的角度來看,無間隔地渲染效率更高(這是大多數控件所做的),以最大限度地減少需要發送到客戶端的數據量。

最後,即使在簡單的情況下,當您從瀏覽器「查看源代碼」的實際表示形式在瀏覽器之間可能會有所不同。它們都可以選擇以任何方式處理間距,換行符和縮進,因爲元素間間距不會以任何方式影響渲染。

如果您呈現「前/後」您的網站的例子,你真的沒有太多的選擇,除了手動格式顯示輸出,如果這是你想要的。如果人們也想看看源代碼,那很好,但要使源代碼看起來像標記一樣好,這將是非常具有挑戰性的。

如果這是對你很重要,你可以攔截輸出流發送到客戶端之前重新它,但它不會從asp.net的渲染引擎直接發生。對於如何做到這一點,谷歌「asp.net響應濾波器」的一個例子 - here's one.我敢肯定,它不是很難找到格式,你可以應用這個概念的HTML代碼。

6

ASP.NET WebForms在.NET 4中,HTML渲染和控件標記得到了改進。0,這將有助於HTML元素本身的控件ID和結構(如針對您的問題在Rob Stone's answer中所述)。但是,縮進和換行符可能仍然不足以滿足您的需求。

如果HTML源真正是爲您的應用程序的用戶體驗的一部分,你可能考慮寫附着在ReleaseRequestState事件一個HttpModule。這種方法將解決HTML源代碼的實際換行符和縮進問題。至avoid re-inventing the wheel您可以使用.NET port of HTML Tidy.NET Wrapper for HTML Tidy作爲響應中自定義過濾器的一部分。

有一個很好的例子可以在this blog的HttpModule中編寫自定義過濾器。我發現最有用的代碼段如下(略有修改,但你可以從博客本身的充分理解):

public class CustomModule : IHttpModule 
{ 
    public void Init(HttpApplication context) 
    { 
    context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState); 
    } 

    private void context_ReleaseRequestState(object sender, EventArgs e) 
    { 
    HttpResponse response = HttpContext.Current.Response; 
    if (string.Compare(response.ContentType,"text/html",true) == 0) 
    { 
     response.Filter = new CustomFilter(response.Filter,response.ContentEncoding); 
    } 
    } 
} 

和你CustomFilter類中...

public override void Write(byte[] buffer, int offset, int count) 
{ 
    sb = new StringBuilder(count + 1024); 
    sb.Append(enc.GetString(buffer,offset,count)); 

    // <---- Run the sb content through HTML Tidy here ----> 

    byte[] buff = enc.GetBytes(sb.ToString()); 
    s.Write(buff,0,buff.Length); 
    } 
} 
+0

有趣的命題;然而,如果只有開發人員關心源代碼的外觀,只要HTML是有效的(對於瀏覽器),那麼這只是浪費資源..所以這種方法最好只在「開發」模式下執行。 – 2012-11-08 19:50:20

+0

@pst - 我同意你對大多數網站的評論。在這種情況下,雖然OP聲明瞭「我的網站提供訪問者資源和教程,其中查看源代碼是體驗的一部分。」因此,從這個角度來看,這可能值得額外的資源。有意義嗎? – 2012-11-08 20:29:01

+1

那麼,爲什麼要說*關於ASP.NET體驗? ;-) – 2012-11-08 21:57:44

1

這裏的派對遲到了,但我遇到了類似的問題。我們正在生成一些非常複雜的JavaScript,它的方式太過破壞,無法進行合理的調試,所有這些都與其他標記混淆在一起。所以我想出了這門課。

public class HtmlPrettyControl : HtmlGenericControl 
{ 
    public bool Indent { get; set; } 

    public HtmlPrettyControl(string tag) : this(tag, true) { } 

    public HtmlPrettyControl(string tag, bool indent) : base(tag) 
    { 
     Indent = indent; 
    } 

    protected override void Render(HtmlTextWriter writer) 
    { 
     // Here you can check if you are running against a production environment 
     // and just do base.Render to prevent extra code execution and space in 
     // your response to the client 

     if (Indent) 
     { 
      RenderBeginTag(writer); 
      writer.WriteLine(); 
      writer.Indent++; 
      base.RenderChildren(writer); 
      writer.WriteLine(); 
      writer.Indent--; 
      RenderEndTag(writer); 
     } 
     else 
     { 
      base.Render(writer); 
     } 
     writer.WriteLine(); 
    } 
} 

用例:

var myDiv = new HtmlPrettyControl("div"); 
var myLabel = new HtmlPrettyControl("label", false); 
myLabel.InnerText = "I'm sorry, Dave."; 
myDiv.Controls.Add(myLabel) 

生成markup:

<div> 
    <label>I'm sorry, Dave.</label> 
<div> 

我們使用了類似的渲染方法重寫爲不是簡單的HTML標籤的控件(在不同的基類/繼承鏈)。唯一的缺點是傳遞給Render方法的writer似乎沒有被通知您控件所在的ascx的當前縮進級別(如果有的話)。因此,雖然控件及其子級的層次結構很好地縮進並分解,但它們將重置爲0的縮進級別,從而打破了ascx或aspx佈局文件中環繞標記的整體流程。

+0

我會在這裏討論基本問題,用簡單的標記推薦JavaScript ;-)我有一個控件(實際上是兩個,取決於上下文),只是爲了便於JavaScript渲染以包含標記和代碼隱藏也照顧其他細節;內聯事件也以類似的方式與「託管」JavaScript託管功能庫進行分離。 – 2012-11-08 19:46:48

+0

哦,是的,我永遠不會說我們目前的方法(我試圖用這個類來解決的問題)是理想的,甚至是優雅的。但是,我認爲這裏的這個特別的解決方案是針對原始問題的。 – 2012-11-08 21:25:25