浅析UpdatePanel的partial render原理

      在我接触ajax.net前,update panel的大名已经是如雷贯耳了。update panel到底如何实现partial render的呢,半年来一直塞在我的思绪中。
      一个星期前,终于开始了我的ajax.net之旅,美妙绝伦的js 扩展令人陶醉。但不幸的是在我以updatepanel machinism,inside updatepanel ajax等等等为关键字 google,baidu后依然没有任何斩获,大多数搜到的条目都是告诉你如何往updatepanel里面拖控件的。我也知道博客园众多高人,其中老赵同志最为显目,我翻了他的很多文章,都没能打开我的心结。(可能他写过相关文章,我没找到。)
     没办法,只好用reflector打开程序集,我努力的寻找,寻找那个方法,那个能改变呈现流程的方法。终于我找到了你  ----------- SetRenderMethodDelegate。
      以下代码模拟了update panel的partial render行为。
  ParialRender.aspx.cs
ContractedBlock.gif ExpandedBlockStart.gif
None.gifusing System;
None.gif
using System.Data;
None.gif
using System.Configuration;
None.gif
using System.Collections;
None.gif
using System.Web;
None.gif
using System.Web.Security;
None.gif
using System.Web.UI;
None.gif
using System.Web.UI.WebControls;
None.gif
using System.Web.UI.WebControls.WebParts;
None.gif
using System.Web.UI.HtmlControls;
None.gif
using System.Collections.Specialized;
None.gif
None.gif
public partial class PartialRender : System.Web.UI.Page
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
private static Random random = new Random();
InBlock.gif
InBlock.gif    
protected void Page_Load(object sender, EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        NameValueCollection headers 
= this.Request.Headers;
InBlock.gif        
// 识别异步回调
InBlock.gif
        if(headers["x-myajax"!= null)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.SetRenderMethodDelegate(this.MyAjaxPageRender);
InBlock.gif            
this.form1.SetRenderMethodDelegate(this.MyAjaxFormRender);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
// 改变页面的呈现流程
InBlock.gif
    private void MyAjaxPageRender(HtmlTextWriter writer, Control page)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.form1.RenderControl(writer);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
// 改变form的呈现流程
InBlock.gif
    private void MyAjaxFormRender(HtmlTextWriter writer, Control page)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.UpdatePanel.RenderControl(writer);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
protected void btnSubmit_Click(object sender, EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.txtRandomNumber.Text = random.Next(1000).ToString();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

PartialRender.aspx
ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif<%dot.gif@ Page Language="C#" AutoEventWireup="true" CodeFile="PartialRender.aspx.cs" Inherits="PartialRender" %>
None.gif
None.gif
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
None.gif
None.gif
<html xmlns="http://www.w3.org/1999/xhtml" >
None.gif
<head runat="server">
None.gif    
<title>浅析update panel 之 partial render 原理</title>
ExpandedBlockStart.gifContractedBlock.gif    
<script>dot.gif
InBlock.gif    
var xmlHttp;
InBlock.gif    
InBlock.gif    
// 创建xmlhttprequest对象
ExpandedSubBlockStart.gifContractedSubBlock.gif
    function createXMLHttpRequest() dot.gif{
InBlock.gif        
if (window.ActiveXObject)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return new ActiveXObject("Microsoft.XMLHTTP");
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
else if (window.XMLHttpRequest) dot.gif{
InBlock.gif            
return new XMLHttpRequest();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
else dot.gif{
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
// 状态改变handle
ExpandedSubBlockStart.gifContractedSubBlock.gif
    function handleStateChange() dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (xmlHttp.readyState == 4dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
if (xmlHttp.status == 200dot.gif{
InBlock.gif                processCallback();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
// 处理异步回调
ExpandedSubBlockStart.gifContractedSubBlock.gif
    function processCallback() dot.gif{
InBlock.gif        parseDom(xmlHttp.responseText);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
// 发出异步请求
ExpandedSubBlockStart.gifContractedSubBlock.gif
    function doRequest() dot.gif{
InBlock.gif        xmlHttp 
= createXMLHttpRequest();
InBlock.gif        
var url = window.location.href;
InBlock.gif        xmlHttp.open(
"POST", url, true);
InBlock.gif        xmlHttp.onreadystatechange 
= handleStateChange;
InBlock.gif        
// 标记异步回调
InBlock.gif
        xmlHttp.setRequestHeader("x-myajax""nothing");
InBlock.gif        xmlHttp.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded;"); 
InBlock.gif        
var queryString = createQueryString();
InBlock.gif        xmlHttp.send(queryString);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
// 创建 querystring ,也就是模拟表单里面的name-value对。
ExpandedSubBlockStart.gifContractedSubBlock.gif
    function createQueryString() dot.gif{
InBlock.gif        
var result = "btnSubmit=";
InBlock.gif        result 
+= "&txtRandomNumber=" + document.getElementById("txtRandomNumber").value;
InBlock.gif        parseDom(document.forms[
0].outerHTML);
InBlock.gif        
for (var i = 0; i < hiddenFields.length / 2; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
var hiddenField = document.getElementById(hiddenFields[i * 2]);
InBlock.gif            result 
+= "&" + encodeURIComponent(hiddenField.name) + "=" + encodeURIComponent(hiddenField.value);
ExpandedSubBlockEnd.gif        }

InBlock.gif        
return result;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
// 这里存放隐藏字段的id 和 value,隐藏字段就是__VIEWSTATE之类的东西
InBlock.gif
    var hiddenFields = null;
InBlock.gif    
// updatePanel 内部的html
InBlock.gif
    var updatePanelContent = null;
InBlock.gif    
InBlock.gif    
// 分析一段html,求出它里面 <input type=hidden> 和 update panel
ExpandedSubBlockStart.gifContractedSubBlock.gif
    function parseDom(text) dot.gif{
InBlock.gif        hiddenFields 
= [];
InBlock.gif        updatePanelContent 
= "";
InBlock.gif        
var root = document.createElement("span");
InBlock.gif        root.innerHTML 
= text;
InBlock.gif        parseNode(root);
ExpandedSubBlockStart.gifContractedSubBlock.gif        
for (var i = 0; i < hiddenFields.length / 2; i++dot.gif{
InBlock.gif            document.getElementById(hiddenFields[i 
* 2]).value = hiddenFields[i * 2 + 1];
ExpandedSubBlockEnd.gif        }
 
InBlock.gif        document.getElementById(
"UpdatePanel").innerHTML = updatePanelContent;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
// 递归分析节点
ExpandedSubBlockStart.gifContractedSubBlock.gif
    function parseNode(node) dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (node.nodeType == 3)dot.gif{
InBlock.gif            
return;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (node.tagName.toLowerCase() == "input" && node.type.toLowerCase()  == "hidden"dot.gif{
InBlock.gif            hiddenFields.push(node.id);
InBlock.gif            hiddenFields.push(node.value);
InBlock.gif            
return;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (node.id == "UpdatePanel"dot.gif{
InBlock.gif            updatePanelContent 
= node.innerHTML;
InBlock.gif            
return;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
for (var i = 0; i < node.childNodes.length; i++dot.gif{
InBlock.gif            parseNode(node.childNodes[i]);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
ExpandedBlockEnd.gif    
</script>
None.gif
</head>
None.gif
<body>
None.gif    
<form id="form1" runat="server">
None.gif     
<asp:Panel ID="UpdatePanel" runat="server" >
None.gif            
<asp:Button ID="btnSubmit" runat="server" Text="生成随机数" OnClick="btnSubmit_Click" OnClientClick="doRequest();return false;"  />
None.gif            
<asp:TextBox ID="txtRandomNumber" runat="server"></asp:TextBox>
None.gif     
</asp:Panel>
None.gif    
</form>
None.gif
</body>
None.gif
</html>
None.gif
代码在普通的panel中放了一个button,一个textbox,按button就能无刷新的产生随机数。
1.要改变submit的行为,原来的表单不能提交了,而是交给xmlhttprequest提交。
2.服务器端要知道是xmlhttprequest做的请求还是普通的请求,这个通过设置一个自定义的http头实现 x-myajax.
3.要改变服务器端的呈现流程,原来呈现整个页面,但异步请求的时候只能
呈现updatepanel和一些系统级别的东西(__VIEWSTATE之类).我们通过Control的SetRenderMethodDelegate方法来实现。
4.要能解析response text, 根据解析的结果设置__VIEWSTATE 的值,设置updatepanel内部的html。
这只是一个简单的模拟,实际中updatepanel,scriptmanager的行为复杂得多,比如说trigger,focus等等。

转载于:https://www.cnblogs.com/lordych/archive/2007/08/19/861371.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值