【问题标题】:ASP.net render HTML nicely (Beautify)ASP.net 很好地呈现 HTML(美化)
【发布时间】:2011-07-12 15:35:05
【问题描述】:

当我在 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 和名称等?

【问题讨论】:

  • 您不会通过网络表单获得漂亮的源代码。如果你想使用 ASP.NET MVC 是一个更好的提议。
  • 我个人认为名称(只要它们看起来很长而且“难看”)是一种非常明智的方式,尤其是在涉及中继器、嵌套控件、模板和几乎“所有不平凡的东西”的场景中";只需使用更好的 CSS 类/选择器(避免 ASP.NET 控件的基于 ID 的选择器)和数据绑定(以避免硬编码客户端 ID)并且不要将生成的名称视为静态名称资源。

标签: c# html asp.net webforms


【解决方案1】:

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

【讨论】:

  • 这看起来很适合 ID 的感谢,关于缩进和换行的任何想法?
  • 这太棒了。这适用于名称以及 id 还是仅适用于 id?这将使脚本和 css 比以前容易得多。非常感谢:)
  • 伙计,希望我在编写 ASP.NET 2.0 应用程序时拥有它。
  • 这只是“美化”的一小部分。我更喜欢使用“长控件名称”,因为它可以避免名称冲突。总是;对于复杂的页面和 [许多] 嵌套控件,这将成为更大的问题。它还允许对控件名称执行一些 [unsanctioned] 启发式。
【解决方案2】:

ASP.NET WebForms HTML 渲染和控件标记在 .NET 4.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 中有一个很好的示例,说明了如何在 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);
  }
}

【讨论】:

  • 有趣的提议;但是,如果除了开发人员之外没有人关心源代码的外观,只要 HTML 是有效的(对于浏览器)......那么它只是浪费资源......所以这种方法可能最好只在“开发”模式下使用。
  • @pst - 我同意您对大多数网站的评论。在这种情况下,尽管 OP 已声明 “我的网站正在为访问者提供资源和教程,其中查看源代码是体验的一部分。” 所以从这个角度来看,额外的资源可能是值得的。有道理吗?
  • 那么为什么要对 ASP.NET 体验撒谎呢? ;-)
【解决方案3】:

获得漂亮的输出 几乎是不可能的,因为解析器在渲染控件时没有任何上下文概念。许多控件呈现多个 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 的代码。

【讨论】:

    【解决方案4】:

    在这里聚会迟到了,但我遇到了类似的问题。我们正在生成一些高度复杂的 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 方法覆盖。唯一的缺点是传递给Render 方法的writer 似乎没有被告知您的控件所在的ascx 的当前缩进级别(如果有的话)。因此,虽然控件的层次结构及其子控件被很好地缩进和分解,但它们将重置为缩进级别 0,从而破坏了 ascx 或 aspx 布局文件上环绕标记的整体流程。

    【讨论】:

    • 我认为这里的根本问题是在 JavaScript 中使用普通标记 ;-) 我有一个控件(实际上是两个,取决于上下文)只是为了方便 JavaScript 渲染以包含标记和代码隐藏,也处理其他细节;内联事件也以类似的方式通过“绑定”到托管 JavaScript 函数存储来解耦。
    • 哦,是的,我绝不会争辩说我们当前的方法(我试图用这个类解决的问题)是理想的,甚至是优雅的。但我认为,这里的这个特殊解决方案对原始问题很重要。
    猜你喜欢
    • 2015-08-04
    • 1970-01-01
    • 2015-05-14
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 2019-02-01
    相关资源
    最近更新 更多