ViewState 与SEO优化

8 篇文章 0 订阅
这里记录两种优化方案:压缩和后置, 判断是否需要viewstate压缩准则是,内网系统不必考虑压缩(网速够快还闲着没事消耗服务器CPU资源干啥啊。。。),对外系统根据viewstate长度选择性进行压缩

一,viewstate压缩:

  页面的生存周期里保存viewstate的方法为SavePageStateToPersistenceMedium方法,所以重写这个方法就ok了。

protected override void SavePageStateToPersistenceMedium(object state)
    {
        StringBuilder sb = new StringBuilder();
        TextWriter tw = new StringWriter(sb);
        LosFormatter lf = new LosFormatter();
        lf.Serialize(tw, state);
        tw.Flush();
        tw.Close();
        tw.Dispose();
        bool useZip = false;
        string finalStr = sb.ToString();
        if (sb.Length >= 1096)
        {
            useZip = true;
            byte[] bytes = Compress(Convert.FromBase64String(finalStr));
            finalStr = Convert.ToBase64String(bytes);
        }

        ClientScript.RegisterHiddenField("_MyViewState", finalStr);
        ClientScript.RegisterHiddenField("_UseZip", (useZip?"T":"F"));
    }

   private byte[] Compress(byte[] data)
    {
        MemoryStream ms = new MemoryStream();
        GZipStream gzip = new GZipStream(ms, CompressionMode.Compress);
        gzip.Write(data, 0, data.Length);
        gzip.Flush();
        gzip.Close();
        gzip.Dispose();

        byte[] bytes = ms.ToArray();
        ms.Close();
        ms.Dispose();

        return bytes;
    }

1.传入的参数state就是页面所有的viewstate集合对象,默认时该对象是经过序列化后保存到__ViewState的隐藏控件中的。所以要用LosFormatter对象将将state对象序列化,此时得到的序列化字符串是68位的数为基来编码的。

2.1096表示当viewstate长度大于1096时就压缩,否则就原封不动。

3..net有的System.IO.Compression中有两种压缩方式,这里选用GZip,也可以用其他更好的压缩算法的方法,压出效果就好^_^!

4.压缩完后恢复成以68位的数为基的编码字符串保存到__MyViewState的隐藏控件中,注意不能用回默认的__ViewState保存,否则会出错。

 

搞定压缩部分,当然都解压部分啦,回传时通过LoadPageStateFromPersistenceMedium方法获取viewstate,所以继续重写吧

protected override object LoadPageStateFromPersistenceMedium()
    {
        string myViewState = Request.Form["_MyViewState"];
        bool useZip = (Request.Form["_UseZip"].Equals("T")?true:false);
        LosFormatter lf = new LosFormatter();
        if (useZip)
        {
            byte[] bytes = Convert.FromBase64String(myViewState);
            bytes = Decompress(bytes);

            return lf.Deserialize(Convert.ToBase64String(bytes));
        }
        else
        {
            return lf.Deserialize(myViewState);
        }
    }
  private byte[] Decompress(byte[] data)
    {
        MemoryStream ms = new MemoryStream(data);
        GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress);
        byte[] resultByte = null;
        int count = 1;
        MemoryStream resultMs = new MemoryStream();
        while (count >= 1)
        {
            resultByte = new byte[1024];
            count = gzip.Read(resultByte, 0, 1024);
            resultMs.Write(resultByte, 0, count);
        }
        resultByte = resultMs.ToArray();
        resultMs.Close();
        resultMs.Dispose();
        gzip.Close();
        gzip.Dispose();
        ms.Close();
        ms.Dispose();

        return resultByte;
    }

1.从__MyViewState中获取viewstate字符串,然后是解压、反序列,得到之前保存的ViewState对象。

 

这样ViewState的压缩就KO了。当然Asp.net还可以将ViewState保存到Session里面,设置一下就好了,非常方便,也免得自己来处理多页面出现的ViewState覆盖问题。

 

  二,后置ViewState(2011.12.12校正)

viewstate默认是保存到页面的开头部分,如果长度过大会对搜索引擎爬该网站有一定的影响,可以通过把ViewState放置到页面最后的方式优化,后置viewstate还有一个好处就是页面会出来快一点哦。

protected override void Render(HtmlTextWriter writer)
    {
        StringWriter sw = new StringWriter();
        HtmlTextWriter htw = new HtmlTextWriter(sw);
        base.Render(htw);
        htw.Flush();
        htw.Close();
        htw.Dispose();
        StringBuilder resulteHtml = new StringBuilder(sw.ToString());
        sw.Close();
        sw.Dispose();

        Regex reg = new Regex("<input type=\"hidden\" name=\"_MyViewState\" id=\"_MyViewState\" .* />");
        string myViewState = reg.Match(resulteHtml.ToString()).Value;
       if(!string.IsNullOrEmpty(myViewState))
      {
          resulteHtml.Replace(myViewState, string.Empty);
        resulteHtml.Append(myViewState);//不能把自定义隐藏控件放在页面的最后
         int formEndTag_index=resulteHtml.ToString().IndexOf("</form>");
             resulteHtml.Insert(forEndTag_index,myViewState);
          reg = new Regex("<input type=\"hidden\" name=\"_UseZip\" id=\"_UseZip\" .* />");
          myViewState = reg.Match(resulteHtml.ToString()).Value;
          resulteHtml.Replace(myViewState, string.Empty);
        resulteHtml.Append(myViewState);//不能把自定义隐藏控件放在页面的最后

         formEndTag_index=resulteHtml.ToString().IndexOf("</form>");

             resulteHtml.Insert(forEndTag_index,myViewState);
       }
        Response.Write(resulteHtml.ToString());
    }

Render是页面发送给用户前最后留给我们发挥的地方了(除了自定义HttpModule啦),base.Render()会将页面控件所生成的html代码输入到HtmlTextWriter
对象中,通过它就可以得到页面最终的html代码了,接着就用正则表达式获取viewstate部分,并移动到html代码的最后,然后直接输出到响应流中,至于重写方
法中的参数,就当作路人甲乙丙吧。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值