浅析UpdatePanel的partial render原理

本文深入探讨了ASP.NET AJAX中UpdatePanel组件实现局部刷新的机制,包括客户端与服务器端的交互过程,以及如何通过SetRenderMethodDelegate方法改变页面的渲染流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在我接触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.gifExpandedBlockStart.gif
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->None.gifusingSystem;
None.gif
usingSystem.Data;
None.gif
usingSystem.Configuration;
None.gif
usingSystem.Collections;
None.gif
usingSystem.Web;
None.gif
usingSystem.Web.Security;
None.gif
usingSystem.Web.UI;
None.gif
usingSystem.Web.UI.WebControls;
None.gif
usingSystem.Web.UI.WebControls.WebParts;
None.gif
usingSystem.Web.UI.HtmlControls;
None.gif
usingSystem.Collections.Specialized;
None.gif
None.gif
publicpartialclassPartialRender:System.Web.UI.Page
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
privatestaticRandomrandom=newRandom();
InBlock.gif
InBlock.gif
protectedvoidPage_Load(objectsender,EventArgse)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifNameValueCollectionheaders
=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
privatevoidMyAjaxPageRender(HtmlTextWriterwriter,Controlpage)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.form1.RenderControl(writer);
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
//改变form的呈现流程
InBlock.gif
privatevoidMyAjaxFormRender(HtmlTextWriterwriter,Controlpage)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.UpdatePanel.RenderControl(writer);
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
protectedvoidbtnSubmit_Click(objectsender,EventArgse)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
this.txtRandomNumber.Text=random.Next(1000).ToString();
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif

PartialRender.aspx
ContractedBlock.gifExpandedBlockStart.gif
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->ExpandedBlockStart.gifContractedBlock.gif<%dot.gif@PageLanguage="C#"AutoEventWireup="true"CodeFile="PartialRender.aspx.cs"Inherits="PartialRender"%>
None.gif
None.gif
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
None.gif
None.gif
<htmlxmlns="http://www.w3.org/1999/xhtml">
None.gif
<headrunat="server">
None.gif
<title>浅析updatepanel之partialrender原理</title>
ExpandedBlockStart.gifContractedBlock.gif
<script>dot.gif
InBlock.gif
varxmlHttp;
InBlock.gif
InBlock.gif
//创建xmlhttprequest对象
ExpandedSubBlockStart.gifContractedSubBlock.gif
functioncreateXMLHttpRequest()dot.gif{
InBlock.gif
if(window.ActiveXObject)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returnnewActiveXObject("Microsoft.XMLHTTP");
ExpandedSubBlockEnd.gif}

ExpandedSubBlockStart.gifContractedSubBlock.gif
elseif(window.XMLHttpRequest)dot.gif{
InBlock.gif
returnnewXMLHttpRequest();
ExpandedSubBlockEnd.gif}

ExpandedSubBlockStart.gifContractedSubBlock.gif
elsedot.gif{
InBlock.gif
returnnull;
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

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

ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

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

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

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

InBlock.gif
returnresult;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
//这里存放隐藏字段的id和value,隐藏字段就是__VIEWSTATE之类的东西
InBlock.gif
varhiddenFields=null;
InBlock.gif
//updatePanel内部的html
InBlock.gif
varupdatePanelContent=null;
InBlock.gif
InBlock.gif
//分析一段html,求出它里面<inputtype=hidden>和updatepanel
ExpandedSubBlockStart.gifContractedSubBlock.gif
functionparseDom(text)dot.gif{
InBlock.gifhiddenFields
=[];
InBlock.gifupdatePanelContent
="";
InBlock.gif
varroot=document.createElement("span");
InBlock.gifroot.innerHTML
=text;
InBlock.gifparseNode(root);
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(vari=0;i<hiddenFields.length/2;i++)dot.gif{
InBlock.gifdocument.getElementById(hiddenFields[i
*2]).value=hiddenFields[i*2+1];
ExpandedSubBlockEnd.gif}

InBlock.gifdocument.getElementById(
"UpdatePanel").innerHTML=updatePanelContent;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
//递归分析节点
ExpandedSubBlockStart.gifContractedSubBlock.gif
functionparseNode(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.gifhiddenFields.push(node.id);
InBlock.gifhiddenFields.push(node.value);
InBlock.gif
return;
ExpandedSubBlockEnd.gif}

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

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

ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedBlockEnd.gif
</script>
None.gif
</head>
None.gif
<body>
None.gif
<formid="form1"runat="server">
None.gif
<asp:PanelID="UpdatePanel"runat="server">
None.gif
<asp:ButtonID="btnSubmit"runat="server"Text="生成随机数"OnClick="btnSubmit_Click"OnClientClick="doRequest();returnfalse;"/>
None.gif
<asp:TextBoxID="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等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值