• 当head遇上runat=server之后发生的纠结之事


    关于这个问题网上很少有说到,本早想写一篇文章来记录,搁浅了挺久,其实在第一天写asp.net程序时问题就诞生了,但是在上次项目之前做项目都没有在意,甚至是注意它,其实也算是可以忽略掉的,碰巧上次项目正与它纠结上了,为了不影响项目导致大面积的修改尝试了很多方法,请教了很多人,google了n遍,最后在项目上线之后一段时间才得以解决,心中大快,跟大家分享...

    或许很多人也一样没有在意甚至注意这个问题吧,我们在Visual Studio中新建一个.aspx或者.master页面时,html中的title标签默认是加上runat="server"的,为什么会加?当然是aspx页面模版文件本身就有这个属性的,也正是因为加了才能享受到asp.net特性带来的便利(在服务器端进行处理,比如asp.net4.0下MetaDescription,MetaKeywords的特性等),但便利的同时也出现了一些小小的瑕疵。

    下图为页面head标签不加runat="server"运行之后的效果,很整洁的按照我想要的格式输出了:

    但是给它加上runat="server"运行之后,却变成了如下图的效果:

    head加了runat="server"的效果

    也许你会说这也没什么啊,完全没啥影响,我喜欢紧凑的感觉...

    起初我也是这样认为,但是每次查看页面源代码的时候越看越觉得它不顺眼,觉得它丑陋不堪,违背了我的意愿,为什么好好的代码,格式不受我控制,加之领导说"你这个title换行是会影响SEO的啊,这个你注意下啊",这里暂时先不讨论它是否真会影响SEO,既然领导也提出来了,可想而知,越来越纠结,必须得解决它,cnblogs提问,未解,google了n遍,未解,但是在园子里玉开这篇文章中找到了些线索,在这里非常感谢他的指引,虽然当时给了建议,但是出于本人对asp.net也只是浅尝辄止的程度所以当时没能解决问题,于是搁浅了段时间.有天在优化网站的时候,查看网页的源代码又发现了它,真是冤家路窄的感觉,于是又开始google,带着玉开给我的ControlAdapter终于还是发现一个跟我同样纠结的哥们,当然问题也得到了解决...下面给出解决方案以及demo下载:

    示例解决方案图如下:

    WithoutRunatServer.aspx页面是正常页面只做对比用,详细代码请下载demo查看

    WithRunatServer.aspx代码如下:

    WithRunatServer.aspx

    注意head标签是runat="server"的,不加处理运行页面得到源代码如下图效果:

    格式非常混乱,看起来头皮非常发麻,有时调试页面的时候看到乱七八糟的代码会非常没心情,接下来讲关键部分,BaseControlAdapter.cs文件代码如下

    BaseControlAdapter.cs

    复制代码

    using System;
    using System.Globalization;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;

    namespace Adapter
    {
    public class HtmlHeadAdapter : System.Web.UI.Adapters.ControlAdapter
    {
    protected override void Render(HtmlTextWriter writer)
    {
    writer.WriteLine("<head>");
    RenderChildren(writer);
    writer.Write("</head>");
    }

    protected override void OnPreRender(EventArgs e)
    {
    bool hasTitle = false;
    foreach (Control cntrl in this.Control.Controls)
    {
    if (cntrl is HtmlTitle)
    {
    hasTitle = true;
    break;
    }
    }
    if (!hasTitle)
    {
    HtmlTitle ht = new HtmlTitle();
    ht.Text = Page.Title;
    Control.Controls.Add(ht);
    }
    base.OnPreRender(e);
    }
    }

    public class HtmlTitleAdapter : System.Web.UI.Adapters.ControlAdapter
    {
    protected override void Render(HtmlTextWriter writer)
    {
    HtmlTitle htmlTitle = (HtmlTitle)this.Control;
    //writer.Indent = 1;//控制标签开始处缩进
    writer.Write("<title>");
    writer.Write(htmlTitle.Text);
    writer.WriteLine("</title>");
    }
    }

    public class HtmlLinkAdapter : System.Web.UI.Adapters.ControlAdapter
    {
    protected override void Render(HtmlTextWriter writer)
    {
    AttributeCollection attributes = ((HtmlLink)this.Control).Attributes;
    if (null != attributes && attributes.Count > 0)
    {
    writer.Write("<link");
    foreach (string key in attributes.Keys)
    {
    writer.Write(" ");
    writer.Write(key);
    writer.Write("=\"");
    if (0 == String.Compare("href", key, true, CultureInfo.InvariantCulture))
    writer.Write(this.Control.ResolveUrl(attributes[key]));
    else
    writer.Write(attributes[key]);
    writer.Write("\"");
    }
    writer.WriteLine(" />");
    }
    }
    }

    public class HtmlMetaAdapter : System.Web.UI.Adapters.ControlAdapter
    {
    protected override void Render(HtmlTextWriter writer)
    {
    HtmlMeta metaTag = (HtmlMeta)this.Control;
    writer.Write("<meta");
    if (!String.IsNullOrEmpty(metaTag.HttpEquiv))
    {
    writer.Write(" http-equiv=\"");
    writer.Write(metaTag.HttpEquiv);
    }

    if (!String.IsNullOrEmpty(metaTag.Name))
    {
    writer.Write(" name=\"");
    writer.Write(metaTag.Name);
    }
    writer.Write("\" content=\"");
    writer.Write(metaTag.Content);
    writer.WriteLine("\" />");
    }
    }
    }

    复制代码

    BaseControlAdapter文件包括了4个分别类是HtmlHeadAdapter,HtmlTitleAdapter,HtmlLinkAdapter,HtmlMetaAdapter用来处理<head>,<title>,<link>,<meta>标签(如果有其他标签要进行处理可以添加相应的类)

    可以看到基本上是处理了标签的换行的问题,代码中注释了缩进是因为得到的效果并没有想象中的好,之后再进行尝试

    Adapter类库准备好了当然得引入到Web项目中去,然后是如何指定上面的类去处理相应的标签呢,这时就要用上App_Browsers这个文件夹,新建一个Default.browser代码如下:

    Default.browser

    复制代码

    <browsers>
    <browser refID="Default">
    <controlAdapters>
    <adapter
    controlType="System.Web.UI.HtmlControls.HtmlHead"
    adapterType="Adapter.HtmlHeadAdapter"/>
    <adapter
    controlType="System.Web.UI.HtmlControls.HtmlTitle"
    adapterType="Adapter.HtmlTitleAdapter" />
    <adapter
    controlType="System.Web.UI.HtmlControls.HtmlLink"
    adapterType="Adapter.HtmlLinkAdapter"/>
    <adapter
    controlType="System.Web.UI.HtmlControls.HtmlMeta"
    adapterType="Adapter.HtmlMetaAdapter"/>
    </controlAdapters>
    </browser>
    </browsers>

    复制代码

    关于App_Browsers特殊文件夹以及.browser文件的作用可以参考下面连接:

    ASP.NET Web Project Folder Structure

    http://msdn.microsoft.com/en-us/library/ex526337.aspx

    Browser Definition File Schema (browsers Element)

    http://msdn.microsoft.com/en-us/library/ms228122.aspx

    这样编译整个解决方案并运行WithRunatServer.aspx页面发现代码已经整洁很多了

    问题是得到了解决,不过还是发现有一些瑕疵,比如缩进,script等文中没有提到过的标签的处理等,我在实际项目中用了些不优雅的方式进行了处理,由于项目特殊性就不详谈了,希望给同样纠结的童靴一个思路,觉得还行的话给个推荐,存在不对之处请指出,谢谢:)

    附上一些参考连接:

    http://www.cnblogs.com/yukaizhao/archive/2010/05/18/asp_net_40_seo_enhancement_new_feature.html

    http://blogs.x2line.com/al/archive/2007/01/10/2773.aspx
    http://blogs.x2line.com/al/archive/2007/01/31/2814.aspx
    http://blogs.x2line.com/al/archive/2007/01/31/2816.aspx
    http://codebetter.com/blogs/jeff.lynch/archive/2008/05/02/asp-net-quot-head-quot-rendering-issues.aspx

    附上本文的demo下载:https://files.cnblogs.com/aNd1coder/ControlAdapterExample.rar

    引用: http://www.cnblogs.com/aNd1coder/archive/2011/02/10/head-runat-server-result-html-format-disorder.html

  • 相关阅读:
    [USACO06FEB] Stall Reservations 贪心
    [USACO14MAR] Sabotage 二分答案 分数规划
    【机房史】笑面与学弟们的日常正文17最近一次更新20200802
    8.22返校前记
    2020年7月1日
    我TM怎么这么垃圾
    平安夜
    2018 12 21
    新blog
    写在搬家之后.
  • 原文地址:https://www.cnblogs.com/chencidi/p/2540142.html
Copyright © 2020-2023  润新知