在asp.net 2.0中结合母板页使用meta标签(扩展@Page指令)

asp.net

介绍
母板页是asp.net 2.0中的一个非常强大的特性,但是它却不能提供一个实现最基础的针对搜索引擎优化的方法。如果你想你的web页被搜索引擎收录并提高排名,那么你就需要在每一个页都指定一个title和meta标记。本文将说明如何扩展你的asp.net页,以使得在使用母板页的时候你可以直接在你内容页的@Page指令中指定你的meta标签的描述和meta标签的关键字

背景
当你要针对搜索引擎优化你的web页的时候,设置页的title标签和页的meta描述是其中最重要的因素之一。<title>和meta标签实际上是在每个页的HTML的<head>部分,下面出示一个Rhinoback online backup的例子。

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>
   Rhinoback Professional Secure Online Backup Services for Small and Medium Business - SMB
</title>
<meta name="description" content="Professional Online Backup Services. 
      Rhinoback provides robust backup functionality at affordable prices.  
      Premium features, premium services, low prices.  Get the most for 
      your money with Rhinoback!" />
<meta name="keywords" content="backup, online backup, secure backup, cheap backup, 
      free backup, offsite backup,internet backup, secure files, offsite data storage, 
      privacy, security, features, low prices, premium service, remote backup" />
</head>
<body>
     <!-- page content -->
</body>
</html>
<title>标签的文本显示在浏览器的顶端。从下面的例子中可以看到<title>在IE中的显示

当你的页被搜索引擎收录的时候,meta描述的文本则在搜索引擎的列表中显示。下面的例子来自google。带下划线的标题的下面的文本就来自页的meta描述标签。如果没有meta描述标签,那你的页在搜索引擎的列表中将显示为你的页上的某一处的文本。指定你的每一个页的描述文本要比把这些事情交给搜索引擎做好的多。

母板页已经被证明是asp.net 2.0中非常有用的一个特性。本文不是来说明母板页的细节或是如何实现它,因为这样的文章太多了。当我们在母板页中使用了<head>的话,那么母板页下的所有内容页都将自动的包括这个<head>。幸运的是开发人员可以在内容页中直接在@Page指令中修改title属性来修改内容页的title。

<%@ Page Language="C#" MasterPageFile="~/PageTags.master" AutoEventWireup="true" CodeFile="home.aspx.cs" Inherits="home" Title="My home page title" %>
上面的@Page指令说明了这是一个使用了母板页的内容页。如果你要指定meta标签的话,应该在内容页中指定。你可以看到@Page指令中有一个“Description”属性,但是它不能在你的页上创建meta描述标签。事实上,即使你指定了“Description”属性,最后也会被忽略掉而不做任何事的。

我不可能让站点的所有页都使用同一个描述,而且我想给每一页都加一个关键字。我们首先想到的解决办法就是在后置代码中插入我们想要的meta标签到每一个页的<head>里,就像如下的做法
C#

protected void Page_Load(object sender, EventArgs e)
{
    HtmlMeta tag = new HtmlMeta();
    tag.Name = "description";
    tag.Content = "My description for this page";
    Header.Controls.Add(tag);
}
VB

Sub Page_Load()Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    Dim tag As HtmlMeta = New HtmlMeta()
    tag.Name = "description"
    tag.Content = "My description for this page"
    Header.Controls.Add(tag)
End Sub
这种解决方法有一个问题,就是页的标题,meta描述,meta关键字都是相互关联的,所以我们想的是最好让标题和描述在同一个文件中指定。在Page_Load方法里确实可以很简单的在.aspx页中加入一个<script>标签,但是我想要一个更简单的设置和检查每一页标签的解决方案。

在接下来的方案中我们会看到如何通过扩展@Page指令给每一页加上meta标签。

解决方案
我创建了一个继承自System.Web.UI.Page的page基类,并且让我的内容页继承自我的BasePage类。BasePage类包含了在.aspx页中给header控件中增加meta标签的代码,当我们继承了BasePage的之后,这段代码就只需要在一个地方存在,而不用每一页都写一遍。
C#

using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;

/**//// <SUMMARY>
/// 为了给内容页增加meta标签而扩展基类
/// </SUMMARY>
public class BasePage : Page
{
    private string _keywords;
    private string _description;
    // 构造函数
    // 增加一个Init的事件处理
    public BasePage()
    {
        Init += new EventHandler(BasePage_Init);
    }

    // 页将使用这个基类初始化
    // 如果可用则增加meta关键字和meta描述
    void BasePage_Init(object sender, EventArgs e)
    {

        if (!String.IsNullOrEmpty(Meta_Keywords))
        {
            HtmlMeta tag = new HtmlMeta();
            tag.Name = "keywords";
            tag.Content = Meta_Keywords;
            Header.Controls.Add(tag);
        }

        if (!String.IsNullOrEmpty(Meta_Description))
        {
            HtmlMeta tag = new HtmlMeta();
            tag.Name = "description";
            tag.Content = Meta_Description;
            Header.Controls.Add(tag);
        }
    }

    /**//// <SUMMARY>
    /// 获取或设置页的meta关键字
    /// </SUMMARY>
    public string Meta_Keywords
    {
        get 
        
            return _keywords; 
        }
        set 
        
            // 删掉多余的空格
            // 译者注:\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [\f\n\r\t\v]。
            _keywords = Regex.Replace(value, "\\s+", " "); 
        }
    }

    /**//// <SUMMARY>
    /// 获取或设置页的meta描述
    /// </SUMMARY>
    public string Meta_Description
    {
        get 
        
            return _description; 
        }
        set 
        {
            // 删掉多余的空格
            // 译者注:\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [\f\n\r\t\v]。
            _description = Regex.Replace(value, "\\s+", " "); 
        }
    }
}
VB

Imports System
Imports System.Web.UI
Imports System.Web.UI.HtmlControls
Imports System.Text.RegularExpressions


' 为了给内容页增加meta标签而扩展基类

Public Class BasePageClass BasePage
    Inherits Page

    Dim _keywords As String
    Dim _description As String
    ' 页将使用这个基类初始化
    ' 增加一个Init的事件处理
    Public Sub New()Sub New()
        AddHandler Init, New EventHandler(AddressOf BasePage_Init)
    End Sub

    ' 页将使用这个基类初始化
    ' 如果可用则增加meta关键字和meta描述
    Sub BasePage_Init()Sub BasePage_Init(ByVal sender As Object, ByVal e As EventArgs)

        If Not String.IsNullOrEmpty(Meta_Keywords) Then
            Dim tag As HtmlMeta = New HtmlMeta()
            tag.Name = "keywords"
            tag.Content = Meta_Keywords
            Header.Controls.Add(tag)
        End If

        If Not String.IsNullOrEmpty(Meta_Description) Then
            Dim tag As HtmlMeta = New HtmlMeta()
            tag.Name = "description"
            tag.Content = Meta_Description
            Header.Controls.Add(tag)
        End If
    End Sub


    '获取或设置页的meta关键字
    Public Property Meta_Keywords()Property Meta_Keywords() As String
        Get
            Return _keywords
        End Get
        set 
            ' 删掉多余的空格
            ' 译者注:\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [\f\n\r\t\v]。
            _keywords = Regex.Replace(value, "\\s+", " ")
        End Set
    End Property


    ' 获取或设置页的meta描述
    Public Property Meta_Description()Property Meta_Description() As String
        Get
            Return _description
        End Get
        Set(ByVal value As String)
            ' 删掉多余的空格
            ' 译者注:\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [\f\n\r\t\v]。
            _description = Regex.Replace(value, "\\s+", " ")
        End Set
    End Property
End Class
Meta_Keywords属性和Meta_Description属性是公共的,你可以在类实例化后设置它们。当某个类继承自这个类并被初始化后,Base_Init将被调用并在页中增加meta标签

C#

public partial class home : BasePage 
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
}
VB

Partial Class homeClass home
    Inherits BasePage
    Sub Page_Load()Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    
    End Sub
End Class
注意每一个继承自BasePage的页都可以通过属性或代码来插入meta标签。现在我们可以直接在.aspx文件的@Page指令中指定Meta_Keywords属性和Meta_Description属性的值。示例如下

<%@ Page Language="C#" MasterPageFile="~/PageTags.master" AutoEventWireup="true" CodeFile="home.aspx.cs" Inherits="home"  
    CodeFileBaseClass="BasePage" 
    Title="My home page title" 
    Meta_Keywords="page directive, extension, dotnet, asp.net"
    Meta_Description="This is the meta description for my home page."                          
%>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <h3>My home page content<h3>
    <p>
    This is the content on my home page.  This page has an appropriate title tag and
    also has meta tags for keywords and description that are relative to this page.
    The title tag is essential to good search engine optimization and the meta
    description is the text that the search engine will display when your 
    page is listed in search results.  The title and meta description should be
    set specific to each page and should describe the content of the page. 
    </p>
</asp:Content>
注意这里增加了一个CodeFileBaseClass属性,这是必需的,它可以引用BasePage类的公共属性

重点提要
你应该注意到了,在BasePage类里使用了正则表达式。这是因为在你的.aspx里添加描述和关键字的时候可能会是多行,就像下面这个例子似的

<%@ Page Language="C#" MasterPageFile="~/IdeaScope.master" AutoEventWireup="true" 
  CodeFile="is.aspx.cs" Inherits="_is"
  CodeFileBaseClass="BasePage" 
  
  Title="Effective Customer Feedback Management, Improve Customer Commmunication" 
  
  Meta_Keywords="Customer Feedback, Customer Opinion, feedback, opinion,
       idea, ideas, idea management, customer feedback management,         
        product management, product manager, product marketing,         
        product marketing manager"
                              
  Meta_Description="IdeaScope is an on-demand and embedded solution that allows 
       you to capture, prioritize and centrally manage customer feedback. Make your
       customer feedback process more efficient. Save time and involve more 
       stakeholders without significant cost."                          
%>
如果不用正则表达式转换它们的话,这些标记就会包含很多的新行和空格,这会使一些搜索引擎不知所措,所以我们要让这些标记方便搜索引擎的收录。

还有另外一个问题就是,Visual Studio 2005不认识Meta_Keywords属性和Meta_Description属性。你如果在@Page指令中指定了这两个属性的话,将会看到这些属性的下面会出现红色的波浪线,VS2005会认为它们是无效的,但实际上它仍然可以正确的编译和运行。如果你不想看到这些错误的话,你可以在Visual Studio的schema里给@Page指令增加如下代码。

<xsd:attribute name="Meta_Keywords" vs:nonfilterable="true" />
<xsd:attribute name="Meta_Description" vs:nonfilterable="true" />
这些节点应该作为<xsd:complexType name="PageDef">的子节点被插入,如果你把Visual Studio 2005安装在默认路径,那么这个schema文件的路径则是

C:\Program Files\Microsoft Visual Studio 8\Common7\Packages\schemas\html\page_directives.xsd

本文示范了如何通过扩展@Page指令使其支持meta关键字和meta描述。你也可以使用相同的方法增加其他的meta标签。原码文件和示例项目包括了c#和vb两种语言。感谢Scott Guthrie的博客文章,Obsure but cool feature in ASP.NET 2.0一文为本解决方案提供了技术支持。

时间: 2024-11-08 17:43:14

在asp.net 2.0中结合母板页使用meta标签(扩展@Page指令)的相关文章

ASP.NET 2.0 中的异步页功能应用

asp.net|异步 下载本文源代码:WickedCode0510.exe ASP.NET 2.0 提供了大量新功能,其中包括声明性数据绑定和母版页,成员和角色管理服务等.但我认为最棒的功能是异步页,接下来让我告诉您其中的原因. 当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程.一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求.如果一个同步请求成为 I/O 绑定(例如,如果它调用一个远程 Web 服务或查询一个远程数据库,并等待调用

ASP.NET 2.0中的异步页功能应用

ASP.NET 2.0 提供了大量新功能,其中包括声明性数据绑定和母版页,成员 和角色管理服务等.但我认为最棒的功能是异步页,接下来让我告诉您其中的原 因. 当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配 给该线程.一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程 用于处理其他请求.如果一个同步请求成为 I/O 绑定(例如,如果它调用一个 远程 Web 服务或查询一个远程数据库,并等待调用返回),那么分配给该请求 的线程在调用返回之前处于挂起状态.这影响

ASP.NET 2.0 中的异步页[来自MSDN]

ASP.NET 2.0 提供了大量新功能,其中包括声明性数据绑定和母版页,成员和角色管理服务等.但我认为最棒的功能是异步页,接下来让我告诉您其中的原因. 当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程.一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求.如果一个同步请求成为 I/O 绑定(例如,如果它调用一个远程 Web 服务或查询一个远程数据库,并等待调用返回),那么分配给该请求的线程在调用返回之前处于挂起状态.这影响了可伸缩性,

ASP.NET 2.0 中实现跨页提交

在ASP.NET 2.0中,对于跨页提交已经有了非常合理的解决方案下面是一个示例:BeginPage.aspx: 请注意Button1的PostBackUrl属性设置 <%@ Page Language="C#" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitio

体验ASP.NET 2.0 中的异步页功能

asp.net|异步 (一).简单介绍实现原理 下图左为未使用异步页功能执行过程(Asp.net 1.0通常情况), 下图右为使用了异步页执行过程(Asp.net 2.0新增特性). (Asp.net 1.0一般处理过程) (使用Asp.net 2.0新增特性异步页功能处理过程) 从左图中看出,在一个页面整个请求的过程中, 一个线程始终为同一个页面的请求服务. 而从右图可以看出,在一个页面请求的过程中, 可以由不同的线程为本页面请求服务. 显然,采用图中方式在客户端请求数量多时,网站整体效率较高

ASP.NET 2.0中创建内容页

asp.net|创建 在创建一个完整的母版页之后,接下来必然要创建内容页.从用户访问的角度来讲,内容页与最终结果页的访问路径相同,这好像表明二者是同一文件,实际不然.结果页是一个虚拟的页面,没有实际代码,其代码内容是在运行时状态下母版页和内容页合并的结果.在开始介绍内容页之前,还有两个概念需要强调:一是内容页中所有内容必须包含在Content控件中:二是内容页必须绑定母版页.虽然内容页的扩展名与普通ASP.NET页面相同,但是,其代码结构有着很大差别.在创建内容页的过程中,必须时刻牢记以上两个重

asp.net 2.0中页的生存周期(Lifecycle)和动态控件

原文地址:http://www.codeproject.com/KB/aspnet/lifecycle.aspx 作者:Vivek Thakur 介绍 弄懂Page的生存周期(lifecycle)对于开发asp.net应用程序来说是非常重要的.很多.net初学者在处理动态加载控件的时候都出现过回发后丢值,丢状态之类的问题.HTTP协议是无状态的,这就是web程序不同与windows程序的一个天生的问题,如果要学习asp.net的话,Page的生存周期将是你最重要的基础之一.事件的顺序是怎样的,特

ASP.NET 2.0中实现跨页面提交

asp.net|页面 在ASP.NET 1.X 版本中,页面都是提交到自己本身,并不能方便的指定需要提交的目的页面.例如FirstPage.aspx中的button只能提交到FirstPage.aspx,而不能提交到SecondPage.aspx.很多时候,ASP.NET 1.X这样工作方式使我们的开发方式受到不少限制.熟悉ASP/JSP/PHP的朋友大概很不习惯,因为以前经常使用的提交方式突然无法使用,虽然也有解决这个问题的方法(演示Webcast),可是过程太烦琐,不甚方便.令我们高兴的是,

在ASP.NET 2.0中实现跨页面提交

在ASP.NET 1.X 版本中,页面都是提交到自己本身,并不能方便的指定需要 提交的目的页面.例如FirstPage.aspx中的button只能提交到FirstPage.aspx, 而不能提交到SecondPage.aspx.很多时候,ASP.NET 1.X这样工作方式使我们的 开发方式受到不少限制.熟悉ASP/JSP/PHP的朋友大概很不习惯,因为以前经常 使用的提交方式突然无法使用,虽然也有解决这个问题的方法(欲详细了解的读 者可去微软网站收看webcast),可是过程太烦琐,不甚方便.