說明:我的環境是vs2010
我們像程序調試的模式一步一步的來看。
1、首先我們來看我的頁面
public partial class index : Optimization_WebPage.BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
base.SEO_PageName = "index";
}
}
2、這裏我們在看母版頁
/// <summary>
/// 頁面基類:這裏做了對頁面的viewstate優化和Seo操作
/// </summary>
public class BasePage : Page
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.SetOptimization();
this.SetSEOParameters(Seo);
}
protected override void OnUnload(EventArgs e)
{
dicCacheKey = null;
seo = null;
sEO_PageName = null;
base.OnUnload(e);
}
#region viewstate壓縮優化
/// <summary>
/// 加載優化後的viewState
/// 作者:shawn
/// TIME :2011.12.19
/// </summary>
/// <returns></returns>
protected override object LoadPageStateFromPersistenceMedium()
{
var viewStateID = (string)((Pair)base.LoadPageStateFromPersistenceMedium()).Second;
var stateStr = (string)Cache[viewStateID];
if (stateStr == null)
{
var fn = Path.Combine(this.Request.PhysicalApplicationPath, @"App_Data/ViewState/" + viewStateID);
stateStr = File.ReadAllText(fn);
}
return new ObjectStateFormatter().Deserialize(stateStr);
}
/// <summary>
/// 將viewState優化並進行保存操作
/// 作者: shawn
/// Time : 2011.12.19
/// </summary>
/// <param name="state"></param>
protected override void SavePageStateToPersistenceMedium(object state)
{
var value = new ObjectStateFormatter().Serialize(state);
var viewStateID = (DateTime.Now.Ticks + (long)this.GetHashCode()).ToString(); //產生離散的id號碼
var fn = Path.Combine(this.Request.PhysicalApplicationPath, @"App_Data/ViewState/" + viewStateID);
File.WriteAllText(fn, value);
Cache.Insert(viewStateID, value);
base.SavePageStateToPersistenceMedium(viewStateID);
}
#endregion
#region seo相關操作
/// <summary>
/// 頁面相關SEO信息設定
/// </summary>
/// <param name="title">頁面標題.不能爲空</param>
/// <param name="seo">seo信息類.keyweords和descrption屬性不能爲空。否則程序異常</param>
public virtual void SetSEOParameters(SEOParameters seo)
{
//其實下面的各個屬性值可以再加上程序動態生成的一些值。例如:*****水果 + seo專員固定寫的的seo信息。
//例title.text = title.text + seo.SEO_title。而且還可以增加配置文件來設置規則。好比規則是好比固定的內容在前面。動態的在後面等等
if (Seo != null)
{
HtmlMeta
keywd = new HtmlMeta(),
desprtion = new HtmlMeta(),
author = new HtmlMeta(), // author
copyright = new HtmlMeta(), // copyright
date = new HtmlMeta(), // date
robots = new HtmlMeta(),// robots
equiv = new HtmlMeta(),
language = new HtmlMeta(),
client_equiv = new HtmlMeta();
HtmlTitle title = new HtmlTitle();
//標題
title.Text = seo.SEO_title;
//關鍵詞
keywd.HttpEquiv = "keywords";
keywd.Content = seo.SEO_keyWords;
//描述信息
desprtion.HttpEquiv = "description";
desprtion.Content = seo.SEO_desprtion;
//編碼
equiv.HttpEquiv = "Content-Type";
equiv.Content = seo.SEO_ecoding;
//渲染器選擇
client_equiv.HttpEquiv = "X-UA-Compatible";
client_equiv.Content = seo.SEO_clientContent;
//語言
language.HttpEquiv = "Content-Language";
language.Content = seo.SEO_languagestr;
//作者
author.Name = "Author";
author.Content = seo.SEO_authorContent;
//版權所有
copyright.Name = "copyright";
copyright.Content = seo.SEO_copyrightContent;
//日期
date.Name = "date";
date.Content = DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString();
//robots針對搜索引擎
robots.Name = "robots";
robots.Content = seo.SEO_urlRoobts;
//將創建的各個SEO標籤添加到header
this.Header.Controls.AddAt(0, title);
this.Header.Controls.AddAt(1, keywd);
this.Header.Controls.AddAt(2, desprtion);
this.Header.Controls.AddAt(3, equiv);
this.Header.Controls.AddAt(4, client_equiv);
this.Header.Controls.AddAt(5, language);
this.Header.Controls.AddAt(6, author);
this.Header.Controls.AddAt(7, copyright);
this.Header.Controls.AddAt(8, date);
this.Header.Controls.AddAt(9, robots);
}
}
Dictionary<string, SEOParameters> dicCacheKey = null;
/// <summary>
/// 供外部調用獲取已加載到緩存中的seo.xml文件.
/// </summary>
Dictionary<string, SEOParameters> DicCacheKey
{
get
{
if (dicCacheKey == null)
{
dicCacheKey = Cache["seoCache_Dic"] as Dictionary<string, SEOParameters>;
}
return dicCacheKey;
}
set { dicCacheKey = value; }
}
SEOParameters seo = null;
/// <summary>
/// seo優化信息實體該值.具體頁面指定.如現優化頁面爲index.那麼使用實例爲:
/// base.Seo = base.DicCacheKey["index"] as SEOParameters;
/// </summary>
SEOParameters Seo
{
get
{
if (seo == null)
{
if (SEO_PageName != null)
{
if (DicCacheKey != null)
{
if (DicCacheKey[SEO_PageName] != null)
{
seo = DicCacheKey[SEO_PageName] as SEOParameters;
}
}
}
}
return seo;
}
set { seo = value; }
}
string sEO_PageName;
/// <summary>
/// 對應VirtualPath.xml需要做優化的頁面名字.實例:index.aspx或index.html寫爲index
/// </summary>
public string SEO_PageName
{
get { return sEO_PageName; }
set { sEO_PageName = value; }
}
#endregion
#region .NET渲染代碼以及空白字符優化處理
/// <summary>
/// 加載優化
/// </summary>
void SetOptimization()
{
if (!NoOptimizationNuLLStr)
{
HttpContext.Current.Cache.Insert("OptimizationNuLLStr", true); //其實這裏還可以進行封裝。慢慢去擴展、吧
}
else
{
HttpContext.Current.Cache.Insert("OptimizationNuLLStr", false);
//其實這裏還可以進行封裝。慢慢去擴展、吧
} if (!NoMovieNetCode) { HttpContext.Current.Cache.Insert("MovieNetCode", true); //其實這裏還可以進行封裝。慢慢去擴展、吧
} else { HttpContext.Current.Cache.Insert("MovieNetCode", false); //其實這裏還可以進行封裝。慢慢去擴展、吧
} } bool noOptimizationNuLLStr;
/// <summary> /// 指示當前頁面是否進行空字符的優化處理.如果不進行相關處理由繼承頁面將該值設爲true /// </summary> public bool NoOptimizationNuLLStr { get { return noOptimizationNuLLStr;} set { noOptimizationNuLLStr = value; } } bool noMovieNetCode; /// <summary> /// 指示當前頁面是否進行.NET渲染出的代碼移動處理.如果不進行相關處理由繼承頁面將該值設爲true
/// </summary> public bool NoMovieNetCode { get { return noMovieNetCode; } set { noMovieNetCode = value; } } #endregion }
很清楚這個頁面主要做的事情1、將需要調用的SEO信息的頁面名稱放入鍵值對2、加載對應Seo的相關信息。3、viewState壓縮保存至服務器端
爲什麼這麼做。很簡單。因爲程序不知道是哪個頁面調用放在緩存中的seo的信息。其實這個basepgae只是取值把值賦予seo的屬性在返回給繼承它的頁面,所以,效率嘛。還是很快的。而且用的是緩存,不存在數據讀取等一系列操作。那麼問題出來了。我們是什麼時候把seo的信息緩存起來的呢?保存在哪呢?seo專員需要修改的時候怎麼辦呢?
ok,我們接下來就解決這個問題。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
using Optimization_WebPage;
using System.Xml;
using System.IO;
namespace Optimization_WebPage.ViewState
{
public class SEOSetXMLCache:IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_UpdateRequestCache);
}
/// <summary>
/// 註冊事件.進行事件執行.將 URL地址重寫xml數據讀入SEOxml。並將SEO xml文檔中的數據緩存
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void context_UpdateRequestCache(object sender, EventArgs e)
{
System.Web.HttpApplication application = (System.Web.HttpApplication)sender;
//將 URL地址重寫xml數據讀入SEOxml
this.SetSeoXmlByVirtualPath(application);
//並將SEO xml文檔中的數據緩存
if (application.Context.Cache["seoCache_Dic"] == null)
{
this.GetSeoCache(application.Context);
}
}
#region 將SEO xml文檔中的數據緩存
/// <summary>
/// 對seo相關數據的 xml文檔的數據加載到cache緩存
/// </summary>
void GetSeoCache(HttpContext Context)
{
XmlDocument xmlDoc = new XmlDocument();
string tmpPath = HttpContext.Current.Server.MapPath("~/Seo.xml");
if(File.Exists(tmpPath))
{
xmlDoc.Load(tmpPath);
XmlNodeList xmlNodelist = xmlDoc.SelectSingleNode("Root").ChildNodes;
Dictionary<string, SEOParameters> dic_seo = new Dictionary<string, SEOParameters>();
for (int i = 0; i < xmlNodelist.Count; i++)
{
if (HttpContext.Current.Cache[xmlNodelist.Item(i).Name] == null)
{
this.SetSEOCache(dic_seo, Context, i, xmlDoc, tmpPath);
}
}
Context.Cache.Insert("seoCache_Dic", dic_seo, new CacheDependency(tmpPath));
}
}
void SetSEOCache(Dictionary<string, SEOParameters> dic_seo, HttpContext Context, int i, XmlDocument xmlDoc, string tmpPath)
{
XmlNodeList xmlNodelist = xmlDoc.SelectSingleNode("Root").ChildNodes;
dic_seo.Add(xmlNodelist.Item(i).Name, LoadXmlGetSeoParameter(xmlNodelist.Item(i).Name, xmlDoc));
//Context.Cache.Insert(xmlNodelist.Item(i).Name, LoadXmlGetSeoParameter(xmlNodelist.Item(i).Name, xmlDoc), new CacheDependency(tmpPath));
}
/// <summary>
/// 通過二級節點名獲取二級節點下得節點
/// </summary>
/// <param name="NodesName"></param>
/// <returns></returns>
SEOParameters LoadXmlGetSeoParameter(string NodesName, XmlDocument xmlDoc)
{
SEOParameters seo = new SEOParameters();
XmlNodeList xmlNodeList = xmlDoc.SelectSingleNode("Root").SelectSingleNode(NodesName).ChildNodes;
foreach (XmlNode xmlNode in xmlNodeList)
{
XmlElement mypara = (XmlElement)xmlNode;
switch (mypara.Name)
{
case "title":
seo.SEO_title = mypara.InnerText;
break;
case "discription":
seo.SEO_desprtion = mypara.InnerText;
break;
case "keywords":
seo.SEO_keyWords = mypara.InnerText;
break;
default:
seo.SEO_title = "";
seo.SEO_desprtion = "";
seo.SEO_keyWords = "";
break;
}
}
return seo;
}
#endregion
#region 將 URL地址重寫xml數據讀入SEOxml
void SetSeoXmlByVirtualPath(HttpApplication app)
{
if (app.Context.Cache["IsSetSeoXmlByVirtualPath"] != null)
{
string Isload = app.Context.Cache["IsSetSeoXmlByVirtualPath"].ToString();
if (Isload == "Yes")
{
string tmpPathSeo = HttpContext.Current.Server.MapPath("~/Seo.xml");
XmlDocument xmlSeo = null;
if (!File.Exists(tmpPathSeo))
{
this.AddNodeByXML(xmlSeo, tmpPathSeo);
}
else
{
File.Delete(tmpPathSeo);
this.AddNodeByXML(xmlSeo, tmpPathSeo);
}
}
}
}
/// <summary>
/// 向SEO xml文檔中插入節點
/// </summary>
/// <param name="xmlSeo">seoxml文檔</param>
/// <param name="tmpPathSeo">文檔地址</param>
void AddNodeByXML(XmlDocument xmlSeo, string tmpPathSeo)
{
XmlText xmltext;
xmlSeo = new XmlDocument();
//加入XML的聲明段落
XmlNode xmlnode = xmlSeo.CreateXmlDeclaration("1.0", "utf-8", null);
xmlSeo.AppendChild(xmlnode);
XmlElement xmlelem = xmlSeo.CreateElement("", "Root", "");
xmltext = xmlSeo.CreateTextNode("");
xmlelem.AppendChild(xmltext);
xmlSeo.AppendChild(xmlelem);
XmlDocument xmlDoc = new XmlDocument();
string tmpPath = HttpContext.Current.Server.MapPath("~/VirtualPath.xml");
xmlDoc.Load(tmpPath);
XmlNodeList xmlNodeList = xmlDoc.SelectSingleNode("RewriterConfig").SelectSingleNode("urls").ChildNodes;
for (int i = 0; i < xmlNodeList.Count; i++)
{
XmlNode node = xmlNodeList[i];
XmlAttribute xmlabuu = null;
try
{
xmlabuu = node.Attributes["virtualUrl"];
}
catch (Exception)
{
continue;
}
string tmp = xmlabuu.Value;
if (!tmp.Contains("(") && !tmp.Contains(")") && !tmp.Contains("\""))
{
tmp = tmp.Replace(".html", "");
tmp = tmp.Replace(".htm", "");
tmp = tmp.Replace(".aspx", "");
tmp = tmp.Replace("/", "");
XmlInsertNode(xmlSeo, tmpPathSeo, "Root", tmp, "title", "");
XmlInsertNode(xmlSeo, tmpPathSeo, "Root", tmp, "discription", "");
XmlInsertNode(xmlSeo, tmpPathSeo, "Root", tmp, "keywords", "");
}
else { continue; }
}
xmlSeo.Save(tmpPathSeo);
}
/// <summary>
/// 插入一個節點和此節點的字節點
/// </summary>
/// <param name="objXmlDoc">xml文檔對象</param>
/// <param name="xmlPath">xml路徑</param>
/// <param name="MailNode">當前節點路徑</param>
/// <param name="ChildNode">新插入節點</param>
/// <param name="Element">插入節點的子節點</param>
/// <param name="Content">子節點的內容</param>
public static void XmlInsertNode(XmlDocument objXmlDoc, string xmlPath, string MailNode, string ChildNode, string Element, string Content)
{
XmlNode objRootNode = objXmlDoc.SelectSingleNode(MailNode);
XmlNode isNode = objXmlDoc.SelectSingleNode(MailNode).SelectSingleNode(ChildNode);
if (isNode == null)
{
XmlElement objChildNode = objXmlDoc.CreateElement(ChildNode);
objRootNode.AppendChild(objChildNode);
XmlElement objElement = objXmlDoc.CreateElement(Element);
objElement.InnerText = Content;
objChildNode.AppendChild(objElement);
}
else
{
XmlElement objElement = objXmlDoc.CreateElement(Element);
objElement.InnerText = Content;
isNode.AppendChild(objElement);
}
}
#endregion
}
}
我這裏做的方式很簡單。繼承了一個httpmodule。爲什麼這樣做。原因很簡單。因爲我要保證數據的及時更新。那麼每次用戶在訪問我的時候我只會做一個簡單的判斷。該seo信息緩存裏存在嗎?我存放在xml數據裏的數據進行了更改嗎?如果數據存在緩存中,我這裏不會做任何操作。我還驗證存放seo的xml文件是否進行了更改,如果更改了,將緩存數據清空,重新加載。加載時候是根據URL重寫地址文件來加載。如果沒更改,那程序就不會進入相關的加載操作。所以,只有當更改seo文件和程序第一次運行時會加載數據,其他的時候都不會。所以,從效率上可以看出還是不錯。ok。不存在的話就不用說了吧。
那我的xml數據格式是怎麼樣的呢?我這先貼出來我的url地址重寫文件,大家看下
<RewriterConfig>
<urls>
<!--一級欄目-->
<add virtualUrl="/index.html" destinationUrl="~/index.aspx"/>
<add virtualUrl="/About.html" destinationUrl="~/Abouttyj/AboutTYJ.aspx"/>
<add virtualUrl="/News.html" destinationUrl="~/News/News.aspx"/>
<add virtualUrl="/Advantage.html" destinationUrl="~/Advantage/Advantage.aspx"/>
<add virtualUrl="/Culture.html" destinationUrl="~/Culture/Culture.aspx"/>
<add virtualUrl="/Performance.html" destinationUrl="~/Performance/Performance.aspx"/>
<add virtualUrl="/Order.html" destinationUrl="~/Order/Order.aspx"/>
<add virtualUrl="/Feedback.html" destinationUrl="~/Feedback/Feedback.aspx"/>
<!--關於我們-->
<add virtualUrl="/About/Honor.html" destinationUrl="~/Abouttyj/Honor.aspx"/>
<add virtualUrl="/About/team.html" destinationUrl="~/Abouttyj/Team.aspx"/>
<add virtualUrl="/About/Customer.html" destinationUrl="~/Abouttyj/Customer.aspx"/>
<add virtualUrl="/About/Recruitment.html" destinationUrl="~/Abouttyj/Recruitment.aspx"/>
<add virtualUrl="/About/Contact.html" destinationUrl="~/Abouttyj/Contact.aspx"/>
<!--新聞動態-->
<add virtualUrl="/Freight.html" destinationUrl="~/News/Freight.aspx"/>
<add virtualUrl="/Industry.html" destinationUrl="~/News/Industry.aspx"/>
<add virtualUrl="/News/(\d+).html" destinationUrl="~/News/Newsdetail.aspx?name=$1"/>
<!--天翼捷優勢-->
<add virtualUrl="/Fleet.html" destinationUrl="~/Advantage/Fleet.aspx"/>
<add virtualUrl="/Warehouse.html" destinationUrl="~/Advantage/Warehouse.aspx"/>
<!--天翼捷文化-->
<add virtualUrl="/Sentiment.html" destinationUrl="~/Culture/Sentiment.aspx"/>
<add virtualUrl="/Train.html" destinationUrl="~/Culture/Train.aspx"/>
<!--業績展示-->
<add virtualUrl="/Logistics.html" destinationUrl="~/Performance/Logistics.aspx"/>
<add virtualUrl="/Logistics/(\d+).html" destinationUrl="~/Performance/LogisticsDetail.aspx?id=$1"/>
<add virtualUrl="/Performance/(\d+).html" destinationUrl="~/Performance/PerformanceDdetail.aspx?id=$1"/>
<!--在線訂單-->
<add virtualUrl="/Order/(\d+).html" destinationUrl="~/Order/OrderDetailed.aspx?id=$1"/>
<add virtualUrl="/SeeOrder.html" destinationUrl="~/Order/SeeOrder.aspx"/>
<!--留言反饋-->
<add virtualUrl="/SeeFeedback.html" destinationUrl="~/Feedback/SeeFeedback.aspx"/>
<!--首頁搜索-->
<add virtualUrl="/Logistics/(\w+)_(\w+)" destinationUrl="~/Performance/Logistics.aspx?city=$1&citys=$2"/>
<!--站點地圖-->
<add virtualUrl="/sitemap.html" destinationUrl="~/siteMap.aspx"/>
</urls>
</RewriterConfig>
上面我的url地址重寫,下面是我根據url重寫生成的seo.xml文件
<?xml version="1.0" encoding="utf-8"?>
<Root>
<index>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</index>
<About>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</About>
<News>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</News>
<Advantage>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Advantage>
<Culture>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Culture>
<Performance>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Performance>
<Order>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Order>
<Feedback>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Feedback>
<AboutHonor>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</AboutHonor>
<Aboutteam>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Aboutteam>
<AboutCustomer>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</AboutCustomer>
<AboutRecruitment>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</AboutRecruitment>
<AboutContact>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</AboutContact>
<Freight>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Freight>
<Industry>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Industry>
<Fleet>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Fleet>
<Warehouse>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Warehouse>
<Sentiment>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Sentiment>
<Train>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Train>
<Logistics>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</Logistics>
<SeeOrder>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</SeeOrder>
<SeeFeedback>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</SeeFeedback>
<sitemap>
<title>
</title>
<discription>
</discription>
<keywords>
</keywords>
</sitemap>
</Root>
這裏是程序第一次運行根據我的源碼規則生成的一個只有節點信息沒有值得xml文件。那麼數據怎麼來。呵呵呵,這裏就需要問你的seo專員了吧。呵呵呵
下面是我的SEOparamertes 類:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Optimization_WebPage
{
public class SEOParameters
{
public SEOParameters()
{
}
public SEOParameters(string _title,string _desprtion,string _keyWords,string _ecoding, string _authorContent, string _copyright,
string _language, string _clientContent, string _urlRoobts)
{
_SEO_title = _title;
_SEO_desprtion = _desprtion;
_SEO_keyWords = _keyWords;
_SEO_authorContent = _authorContent;
_SEO_clientContent = _clientContent;
_SEO_copyrightContent = _copyright;
_SEO_urlRoobts = _urlRoobts;
_SEO_languagestr = _language;
_SEO_ecoding = _ecoding;
}
public SEOParameters(string _title,string _desprtion,string _keyWords)
{
_SEO_title = _title;
_SEO_desprtion = _desprtion;
_SEO_keyWords = _keyWords;
}
string _SEO_title = "";
/// <summary>
/// 標題信息.該值不能爲空.否則程序異常.且最多隻能接受80個字符
/// </summary>
public string SEO_title
{
get { return _SEO_title.Length > 80 ? _SEO_title.Substring(0, 79) : _SEO_title; }
set { _SEO_title = value; }
}
string _SEO_desprtion = "";
/// <summary>
/// 頁面描述信息.該值不能爲空.否則程序異常.且最多隻能接受200個字符
/// </summary>
public string SEO_desprtion
{
get { return _SEO_desprtion.Length > 200 ? _SEO_desprtion.Substring(0, 199) : _SEO_desprtion; }
set { _SEO_desprtion = value; }
}
string _SEO_keyWords = "";
/// <summary>
/// 頁面關鍵詞.該值不能爲空.否則程序異常.且最多隻能接受100個字符
/// </summary>
public string SEO_keyWords
{
get { return _SEO_keyWords.Length > 100 ? _SEO_keyWords.Substring(0, 99) : _SEO_keyWords; }
set { _SEO_keyWords = value; }
}
string _SEO_ecoding = "";
/// <summary>
/// 編碼方式.如果值爲"".系統默認會設置值爲:text/html;charset=utf-8
/// </summary>
public string SEO_ecoding
{
get { return _SEO_ecoding == "" ? "text/html;charset=utf-8" : _SEO_ecoding; }
set { _SEO_ecoding = value;}
}
string _SEO_authorContent = "";
/// <summary>
/// 著作者:如果值爲""。系統默認會設置值爲:www.ay56.cn
/// </summary>
public string SEO_authorContent
{
get { return _SEO_authorContent == "" ? "http://www.ay56.cn" : _SEO_authorContent; }
set { _SEO_authorContent = value; }
}
string _SEO_copyrightContent = "";
/// <summary>
/// 版權所有.如果值爲""。系統默認會設置值爲:www.ay56.cn
/// </summary>
public string SEO_copyrightContent
{
get { return _SEO_copyrightContent == "" ? "http://www.ay56.cn" : _SEO_copyrightContent; }
set { _SEO_copyrightContent = value;}
}
string _SEO_languagestr = "";
/// <summary>
/// 網頁語言:如果值爲"",系統默認會設置值爲:utf-8
/// </summary>
public string SEO_languagestr
{
get { return _SEO_languagestr == "" ? "utf-8" : _SEO_languagestr; }
set { _SEO_languagestr = value; }
}
string _SEO_clientContent = "";
/// <summary>
/// 客戶端HTML文件渲染器.如果值爲"",系統默認會設置值爲:IE=EmulateIE7
/// </summary>
public string SEO_clientContent
{
get { return _SEO_clientContent == "" ? "IE=EmulateIE7" : _SEO_clientContent; }
set { _SEO_clientContent = value; }
}
string _SEO_urlRoobts = "";
/// <summary>
/// 搜蘇引擎索引目錄地址:如果存在該文件,給於文件路徑.如果值爲"",系統默認會設置值爲:"all"
/// </summary>
public string SEO_urlRoobts
{
get { return _SEO_urlRoobts == "" ? "all" : _SEO_urlRoobts; }
set { _SEO_urlRoobts = value; }
}
}
}
下面代碼是對viewstate的移動和是否需要對空字符進行出來。就是對渲染出來的html結果排成類似於百度、google的源碼那裏。最大化限度減少文件的空白字符,增加傳輸速度。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;
namespace Optimization_WebPage.ViewState
{
/// <summary>
/// 移動隱藏字段 __VIEWSTATE 到 /Form 之前.
/// 作者:shawn
/// </summary>
public class MoveViewStateFilter : System.IO.MemoryStream {
System.IO.Stream _filter;
bool _filtered = false;
/// <param name="filter">A reference to the downstream HttpResponse.Filter.</param>
public MoveViewStateFilter( System.IO.Stream filter )
{
_filter = filter;
}
/// <summary>Closes this filter stream.</summary>
/// <remarks>
/// The contents of this filter are written to the downstream filter after the hidden
/// __VIEWSTATE form field is moved.
/// </remarks>
public override void Close()
{
//獲取針對該頁面是否進行空字符優化處理操作
bool OptimizationNuLLStr = HttpContext.Current.Cache["OptimizationNuLLStr"] != null ? (bool)HttpContext.Current.Cache["OptimizationNuLLStr"] : false;
//獲取針對該頁面是否進行.NET代碼移動操作
bool MovieNetCode = HttpContext.Current.Cache["MovieNetCode"] != null ? (bool)HttpContext.Current.Cache["MovieNetCode"] : false;
if (_filtered)
{
if (this.Length > 0)
{
byte[] bytes = null; ;
string content = System.Text.Encoding.UTF8.GetString(this.ToArray());
string tmp = "http://" + HttpContext.Current.Request.Url.Host + "/";
if (MovieNetCode) //是否進行移動處理
{
if (content.Contains("<div class=\"aspNetHidden\""))
{
content = this.STRINGMOVE(content, "<div class=\"aspNetHidden\"", "</div>", "</form>");
}
else
{
content = this.STRINGMOVE(content, "<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\"", "/>", "</form>");
content = this.STRINGMOVE(content, "<input type=\"hidden\" name=\"__EVENTVALIDATION\" id=\"__EVENTVALIDATION\"", "/>", "</form>");
}
content = this.STRINGMOVE(content, "<script src=\"/WebResource.axd?", "</script>", "</form>");
if (content.Contains("<script src=\"/ScriptResource.axd?"))
{
for (int i = 0; i < 3; i++)
{
content = this.STRINGMOVE(content, "<script src=\"/ScriptResource.axd?", "</script>", "</form>");
}
}
if (content.Contains("<script type=\"text/javascript\">\r\n//<![CDATA["))
{
for (int i = 0; i < 3; i++)
{
content = this.STRINGMOVE(content, "<script type=\"text/javascript\">\r\n//<![CDATA[", "//]]>\r\n</script>", "</form>");
}
}
content = this.STRINGMOVE(content, "<script type=\'text/javascript\'>new Sys.WebForms.Menu", "</script>", "</form>");
}
if (OptimizationNuLLStr) //是否進行空字符優化
{
////多餘字符替換爲""
System.Text.RegularExpressions.Regex regex = new Regex(@" ", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regextwo = new Regex(@"\r\n", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regexthree = new Regex(@"\r\n\t", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
content = regexthree.Replace(content, "");
content = regextwo.Replace(content, "");
content = regex.Replace(content, "");
}
bytes = System.Text.Encoding.UTF8.GetBytes(content);
_filter.Write(bytes, 0, bytes.Length);
tmp = null;
content = null;
}
_filter.Close();
}
base.Close();
}
/// <summary>
/// 移動字符串
/// </summary>
/// <param name="content">渲染出來的內容</param>
/// <param name="MoveString_start">要移動字符串的開始字符</param>
/// <param name="MoveString_End">要移動字符串的結束字符</param>
/// <param name="Insert_string">需要在哪個字符前插入你需要移動的字</param>
/// <param name="tmpCount">要移動字符串的結束字符串的長度</param>
string STRINGMOVE(string content, string MoveString_start, string MoveString_End, string Insert_string)
{
int MoveStringIndex_start = content.IndexOf(MoveString_start);
if (MoveStringIndex_start > 0)
{
int MoveStringIndex_End = content.IndexOf(MoveString_End, MoveStringIndex_start) + MoveString_End.Length;
string MoviString = content.Substring(MoveStringIndex_start, MoveStringIndex_End - MoveStringIndex_start) + "\n";
content = content.Remove(MoveStringIndex_start, MoveStringIndex_End - MoveStringIndex_start);
int Insert_stringIndex = content.IndexOf(Insert_string);
if (Insert_stringIndex >= 0)
{
content = content.Insert(Insert_stringIndex, MoviString);
MoviString = null;
return content;
}
}
return content;
}
public override void Write( byte[] buffer, int offset, int count )
{
if ( ( System.Web.HttpContext.Current != null )
&& ( "text/html" == System.Web.HttpContext.Current.Response.ContentType ) ) {
base.Write( buffer, offset, count );
_filtered = true;
}
else {
_filter.Write( buffer, offset, count );
_filtered = false;
}
}
/// <summary>
/// 便利渲染後的字符串。對其中的a標籤和link標籤的href進行重賦值
/// </summary>
/// 作者:shawn
/// <param name="content">渲染出來的結果</param>
/// <param name="tmp">標頭字符串</param>
string insertHostName(string content,string tmp)
{
//該正則需優化
//string reg = @"<a[^>]*href=(""(?<href>[^""]*)""|'(?<href>[^']*)'|(?<href>[^\s>]*))[^>]*>(?<text>[\s\S]*?)</a>";
//逍遙
//string reg = @"<\s*a\b(?![^<>]*?(javascript|__doPostBack))[^<>]+?href=(['""]?)(?<url>[^*#<>()]*?)\2[^>]*>";
//string reg = @"(?i)<(a|link)\s[^>]*?href=(['""]?)(?!javascript|__doPostBack|alert)(?<url>[^'""\s*#<>()]+)[^>]*>";
//string reg = @"(?i)<a\s[^>]*?href=(['""]?)(?!javascript|__doPostBack)(?<url>[^'""\s*#<>]+)[^>]*>";
string reg = @"(?i)<(?:img\s[^>]*?(?<url>src=(['""]?)[^'""\s*#<>()]+\1)|(?:a|link)\s[^>]*?(?<url>href=(['""]?)(?!javascript|__doPostBack|alert)[^'""\s*#<>()]+\2))[^>]*>";
MatchCollection mc1 = Regex.Matches(content, reg, RegexOptions.IgnoreCase | RegexOptions.Compiled);
for (int i = 0; i < mc1.Count; i++)
{
string href_url = mc1[i].Groups["url"].Value;// 這裏取到了href屬性值
//拼接後的url1
//string href = "href=\"" + href_url + "\"";
//string hreftwo = "href=" + href_url;
if (!href_url.Contains(tmp) && !href_url.Contains("javascript") && !href_url.Contains("#") && !href_url.Contains("(")
&& !href_url.Contains("__doPostBack") && !href_url.Contains("*") && !href_url.Contains("<") && href_url != "" &&
!href_url.Contains(")") && !href_url.Contains(">") && !href_url.Contains("http://"))
{
content = this.Movie(href_url, content, tmp);
}
}
return content;
}
/// <summary>
/// 刪除插入替換法
/// </summary>
/// 作者:shawn
/// <param name="href">鏈接</param>
/// <param name="content">渲染的結果</param>
/// <param name="tmp">標頭</param>
/// <param name="tmpInt">截取的index</param>
/// <returns></returns>
string Movie(string href,string content,string tmp)
{
int StarIndex = content.IndexOf(href);
if (StarIndex != -1)
{
int EndIndex = content.IndexOf(">", StarIndex);
href = href.Replace("href","");
href = href.Replace("=","");
href = href.Replace("\"", "");
if (href.IndexOf("../") == 0)
{
href = href.Remove(0, 3);
}
else if (href.IndexOf("~/") == 0)
{
href = href.Remove(0, 2);
}
else if (href.IndexOf("/") == 0 || href.IndexOf("~") == 0)
{
href = href.Remove(0, 1);
}
content = content.Remove(StarIndex, EndIndex - StarIndex);
content = content.Insert(StarIndex, "href=\"" + tmp + href + "\"");
return content;
}
return content;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
namespace Optimization_WebPage.ViewState
{
/// <summary>
/// 註冊移動事件.開始進行viewstate移動
/// 作者:shawn
/// </summary>
public class MoveViewStateModule : System.Web.IHttpModule {
public MoveViewStateModule()
{
}
void System.Web.IHttpModule.Dispose() {
}
void System.Web.IHttpModule.Init( System.Web.HttpApplication context )
{
context.BeginRequest += new EventHandler( this.BeginRequestHandler );
}
void BeginRequestHandler( object sender, EventArgs e ) {
System.Web.HttpApplication application = ( System.Web.HttpApplication )sender;
application.Response.Filter = new MoveViewStateFilter( application.Response.Filter );
}
}
}
//如需使用BasePage.請再web應用的Global文件中對應的事件替換一下代碼並導入命名空間using System.IO;
protected void Application_Start(object sender, EventArgs e)
{
DirectoryInfo dir = new DirectoryInfo(this.Server.MapPath("~/App_Data/ViewState/"));
if (!dir.Exists)
dir.Create();
else
{
DateTime nt = DateTime.Now.AddHours(-1);
foreach (FileInfo f in dir.GetFiles())
{
if (f.CreationTime < nt)
f.Delete();
}
}
}
有朋友問我你爲什麼不寫在Application_Start事件來加載數據。還是那個回答,數據的及時性。我的緩存數據是根據xml做的緩存、如果xml一旦修改。數據會重新加載。
別忘了、這個是配合url地址重寫用的。所以我們還需要做一件事情:
using System;
using System.Web;
using System.Configuration;
using System.Xml.Serialization;
using System.Web.Caching;
namespace Module.config
{
[Serializable()]
[XmlRoot("RewriterConfig")]
public class UrlConfiguration
{
public UrlConfiguration() { }
/// <summary>
/// 返回配置文件中的RewriterConfig配置節.提示信息.該數據緩存依賴於文件
/// </summary>
/// <returns></returns>
public static UrlConfigurationSection GetConfig()
{
if (HttpContext.Current.Cache["RewriterConfig"] == null)
{
HttpContext.Current.Cache.Insert("RewriterConfig", ConfigurationManager.GetSection("RewriterConfig"), new CacheDependency(HttpContext.Current.Server.MapPath("~/VirtualPath.xml")));
HttpContext.Current.Cache.Insert("IsSetSeoXmlByVirtualPath", "Yes");
}
else
{
if (HttpContext.Current.Cache["IsSetSeoXmlByVirtualPath"] != null)
{
HttpContext.Current.Cache["IsSetSeoXmlByVirtualPath"] = "No";
}
else
{
HttpContext.Current.Cache.Insert("IsSetSeoXmlByVirtualPath", "No");
}
}
return (UrlConfigurationSection)HttpContext.Current.Cache["RewriterConfig"];
}
}
}
至此。已經寫完了。其實這個東西很早了,已經很多站在使用。最後你還可以開發一個管理的一個頁面對xml進行管理。很方面。呵呵呵。很多還不完善,需要大家一起來完善。