_pageRequestManager;
private object PageRequestManager
{
get
{
if (this.m_pageRequestManager == null)
{
this.m_pageRequestManager = s_pageRequestManagerPropertyInfo.GetValue(
ScriptManager.GetCurrent(this.Page), null);
}
return this.m_pageRequestManager;
}
}
}
这段实现并不复杂。如果Request Body中的“__UpdatePanelUploading__”的值为“true”,我们就会使用反射修改ScirptManager控件中的私有变量“_isInAsyncPostBack”。此后,我们使用了自己定义的匿名方法来监听页面的Error事件,当页面的Error事件被触发时,我们定义的新方法就会将能够正确解析的内容发送给客户端。
自然,UpdatePanelFileUpload也需要将程序集中内嵌的脚本文件注册到页面中。我为组件添加了一个开关,可以让用户开发人员使用编程的方式来打开/关闭对于AJAX文件上传的支持。这部分实现更为简单:
public bool Enabled
{
get { }
set { }
}
public string ExecuteMethod
{
get { }
set { }
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
ScriptManager sm = ScriptManager.GetCurrent(this.Page);
if (sm.IsInAsyncPostBack || !sm.EnablePartialRendering ||
this.IsInUploadAsyncPostBack || !this.Enabled)
{
return;
}
if (String.IsNullOrEmpty(this.ExecuteMethod))
{
throw new ArgumentException("Please provide the ExecuteMethod.");
}
ScriptReference script = new ScriptReference(
"AspNetAjaxExtensions.UpdatePanelFileUpload.js",
this.GetType().Assembly.FullName);
ScriptManager.GetCurrent(this.Page).Scripts.Add(script);
if (!String.IsNullOrEmpty(this.ExecuteMethod))
{
this.Page.ClientScript.RegisterStartupScript(
this.GetType(),
"ExecuteMethod",
"AspNetAjaxExtensions.UpdatePanelIFrameExecutor._executeForm = " + this.ExecuteMethod + ";",
true);
}
}
从上面的代码中还可以看到一个ExecuteMethod属性,而这个属性最终会被拼接为一段JavaScript并注册到页面中去。这是新版UpdatePanelFileUpload控件的新特点。这个控件最关键的特性是使用iframe来传递和接受数据,而我将实现这个功能完全交由用户来实现。原因如下:
使用iframe进行通信非常复杂也很难写出真正完美的代码,因此将这部分功能转移到控件外部,这样用户就可以自行修改了。
一些AJAX组件提供了使用iframe进行通信的功能(例如jQuery的Form插件),但是控件无法知道用户的应用中是否已经用了其他客户端框架,因此UpdatePanelFileUpload不会与任何特定的客户端框架进行绑定。
当然,为了方便大家使用,也为了提供一个完整的解决方案,我会提供一个基于jQuery的Form插件的ExecuteMethod。在使用中也可以将其替换为适合您项目的做法,例如swfupload。
客户端组件
UpdatePanelIFrameExecutor继承了WebRequestExecutor,因此需要实现许多方法和属性。但是我们事实上不用完整地实现所有的成员,因为客户端的异步刷信机制只会访问其中的一部分。以下是异步刷信过程中会使用的成员列表,我们必须正确地实现它们:
get_started: 表示一个Executor是否已经开始 了。
get_responseAvailable: 表示一个请求是否成功。
get_timedOut: 表示一个请求是否超时。
get_aborted: 表示一个请求是否被取消了。
get_responseData: 获得文本形式的Response Body。
get_statusCode: 获得Response的状态代码
executeRequest: 执行一个请求。
abort: 停止正在运行的请求。
Upl