ASP.net很好地呈现HTML(Beautify)

时间:2011-03-10 11:17:03

标签: c# html asp.net webforms

当我在ASP.net中生成控件时,他们会这样出来:

<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 个答案:

答案 0 :(得分:14)

在.NET 4.0中,您可以将ClientIDMode设置为4个选项之一AutoID,Static,Predictable和Inherit。您可能正在寻找静态,因为这将确保您的控件呈现给包含您已分配给它们的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

答案 1 :(得分:6)

ASP.NET WebForms HTML呈现和控制标记在.NET 4.0中得到了改进,这将有助于控制ID和HTML元素本身的结构(如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);
  }
}

答案 2 :(得分:2)

获得漂亮的输出几乎是不可能的,因为解析器在渲染控件时没有任何上下文概念。许多控件呈现多个HTML元素,并且需要知道它们的上下文才能执行此操作...以及能够知道所需的格式(例如,对于列表控件,何时开始新行,何时再次缩进)。

此外,并非标记中的所有元素都实际呈现,并且标记的布局并不总是与输出的布局直接相关。例如:

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

Placeholder未呈现,那么会导致输出中的缩进吗? DropDownList呈现多个HTML控件,并且无法确定所需的呈现方式:它是否应缩进到与第一个控件相同的级别?它应该渲染没有元素间距?从实际的角度来看,渲染效率更高(没有大多数控件所做的),以最大限度地减少需要发送到客户端的数据量。

最后,即使在简单的情况下,当您从浏览器“查看源代码”时的实际表示在浏览器之间可能会有所不同。他们都可以选择以任何方式处理间距,换行符,缩进,因为元素间距不会以任何方式影响渲染。

如果您在网站上显示“之前/之后”示例,除了手动格式化输出以进行演示之外,您实际上没有太多选择,如果这是您想要的。如果人们也想查看源代码,那很好,但是让源代码始终看起来与标记一样好是非常具有挑战性的。

如果这对您来说非常重要,您可以拦截输出流并在发送到客户端之前重新格式化,但不会直接从asp.net的渲染引擎发生。有关如何执行此操作的示例,请参阅Google“asp.net响应过滤器” - here's one.我确信找到可以应用于此概念的HTML格式的代码并不难。

答案 3 :(得分:1)

来到这里的晚会,但我遇到了类似的问题。我们正在生成一些高度复杂的javascript,这些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)

生成标记:

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

对于不是简单Html标记的控件(在不同的基类/继承链中),我们使用类似的Render方法覆盖。唯一的缺点是传递给writer方法的Render似乎没有被告知您的控件所存在的ascx的当前缩进级别(如果有的话)。因此,虽然控件及其子代的层次结构很好地缩进和分解,但它们将重置为0的缩进级别,从而打破了ascx或aspx布局文件中环绕标记的整体流程。