2011-03-10 46 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