探讨微软ASP.NET AJAX控件开发技术(服务器端)

简介:
一、简介
到目前为止,我们已经讨论了开发Ajax控件所涉及的客户端相关技术。现在,让我们来讨论此过程中与服务器端相关的一些技术。
需要说明的是,在【客户端】篇中我们的举例本质上仅是使用ASP.NET AJAX框架提供的面向对象JavaScript技术来增强了一个客户端图像组件,而没有明显涉及到AJAX技术(除了ScriptManager在后台 以AJAX方式下载并管理客户端脚本代码外)。所以,这个例子是简单的,仅凭客户端相关知识就可以使用这个增强控件。
但是,在实际开发中,当要增强的客户端控件涉及到AJAX技术时,或者干脆是想增强服务器端组件(如UpdatePanel控件)时,我们必须进行 相关的服务器端编程,而这要求我们必须对Ajax控件开发中所涉及的服务器端相关联的类有所了解。而且,还要以ASP.NET 2.0服务器控件开发相关知识为基本前提,特别是在开发复杂的Ajax控件时。
在本篇中,我们要重新构造一个增强的图像按钮控件MySrvImageButton,此控件将以ASP.NET 2.0服务器控件ImageButton为基础。
二、AJAX控件开发服务器端相关技术
首先,让我们来看一下AJAX控件开发服务器端相关组件及其关系,这些类之间的继承关系图如下图1所示。
图1:控件开发涉及的主要服务器端类之间层次结构图
上图展示了组件、控件和扩展器之间的继承关系。如你所见,为了开发一个控件(注意,Component和Extender不在本文讨论范围之内), 我们有两个选择:其一,创建一个派生自ScriptControl的类;其二,创建一个实现IScriptControl接口的类。但是,如果你想使你的 控件从WebControl派生,那么,ScriptControl应该是一个更好的选择—因为它正是派生自WebControl控件本身。但是,如果你 想从头开发创建你的控件,并且不要求实现WebControl所具备的任何内在特征,那么,实现IScriptControl则更为恰当。此外,当你想在 一个现有控件(例如本文中的MySrvImageButton)中添加Ajax特征时选择使用接口IScriptControl也会是你的选择。但是这两 种方法都要求重载下列两个方法:①、GetScriptDescriptors;②、GetScriptReferences。
三、GetScriptDescriptors
这个方法负责在客户端以自动方式生成$create语句(而在上篇中是使用手工方式)。它使用了一个特殊类ScriptDescriptor来生成它。在继续往下讨论前,首先让我们来浏览一下ScriptDescriptor类中的继承层次图(如图2所示):
图2:ScriptDescriptor类中的继承层次图
显然,每一种具体类型的组件都存在其单独的描述符。如果你在开发一个常规组件,那么,这个方法会返回一个 ScriptComponentDescriptor的实例。对于扩展器而言,该方法返回的是一个ScriptBehaviorDescriptor实 例;而对于一个控件,则返回ScriptControlDescriptor类的实例。该描述符中提供了一些特定的方法用于创建服务器端与客户端的“连 接”。下面,还是让我们来分析一个有关$Create语句是如何在服务器端“注入”的简短示例:

     
     
//上篇中从客户端以手工方式使用$create
$create(AjaxImageButtonNamespace.MyCliImageButton,
{'hoverImageUrl':'Images/updateh.gif'},
{'click':buttonClicked}, null, $get('cliBtn'));
在本文中,我们在服务器端以下列几个语句共同自动生成$Create语句:
ScriptControlDescriptor desc =
new ScriptControlDescriptor("AjaxImageButtonLib.MySrvImageButton",
ClientID);
if (!string.IsNullOrEmpty(HoverImageUrl))
{
desc.AddProperty("hoverImageUrl", HoverImageUrl);
}
if (!string.IsNullOrEmpty(ClientClickFunction))
{
desc.AddEvent("click", ClientClickFunction);
}
return desc;
在上面的代码中,我们在构造器中传递客户端类型(尽管客户端和服务器端具有相同的类型名)和DOM元素ID。这一步将填充$Create语句的第一 个和最后一个参数。此后,我们设置hoverImageUrl属性,它对应于$Create语句的属性部分。最后,通过设置Click事件处理器,我们填 充$Create语句的事件部分。下面是脚本描述符中暴露的几个重要的方法:
1)AddProperty()
这个方法能够在客户端添加一个属性。第一个参数相应于属性名,第二个参数对应该参数的取值。
2)AddEvent()
这个方法在客户端添加一个事件。第一个参数相应于事件名,第二个参数对应你想绑定的函数的名称。
3)AddScriptProperty()
这个方法能够把JavaScript代码指定为属性的一个值。对于复杂的属性赋值通常都要求这样的操作。
4)AddElementProperty()
这个方法在客户端添加一个属性,但是其与AddProperty方法间的区别在于,该值作为一个参数传递给$get方法。
5)AddComponentProperty()
这个方法负责在$Create语句的Component部分添加一个组件引用。该值将被用于$find语句中实现属性的赋值。这个方法的第一个参数相应于属性名,第二个参数对应该组件的id。
四、GetScriptReferences
这个方法负责在ScriptManager中注册JavaScript文件。在这个方法中,针对每一个要求的JavaScript文件,我们都需要创建一个相应的ScriptReference实例。例如,在图像按钮例子中,我们按如下方式注册JavaScript文件:
IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
return new ScriptReference(Page.ResolveUrl("~/SrvImageButton.js"));
}
此外,我们还可以以嵌入式资源方式注册JavaScript文件。为此,我们必须首先在Visual Studio的解决方案资源管理器中把一个JavaScript文件标记为一种嵌入式资源。然后,我们必须添加上WebResource属性以便利用 Asp.Net 2.0 Web资源处理器。下列代码展示了如何把一个JavaScript文件注册为一个嵌入式资源:

     
     
[assembly: WebResource("MyControls.SubControl.Script1.js", "text/javascript")]
namespace MyControls{
public class SubControl: Control, IScriptControl
{
//………
IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
return new

ScriptReference(this.Page.ClientScript.GetWebResourceUrl(
this.GetType(), "MyControls.SubControl.Script1.js"));
}
}
}
此外,如果我们想实现IScriptControl接口而不是从ScriptControl中继承的话,我们还必须重载OnPreRender与Render方法。这样将能确保ScriptManger识别出该服务器控件是一个支持Ajax功能的控件。
下列代码展示了开发基于ASP.NET 2.0服务器端控件的AJAX控件时必须在服务器端实现的最少代码:

     
     
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DummyNamespace
{
public class DummyControl : Control, IScriptControl
{
public DummyControl(): base()
{}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
ScriptManager scriptManager = ScriptManager.GetCurrent(Page);
if (scriptManager == null)
{
throw new InvalidOperationException(
"此页面中必须存在一个ScriptManager控件!");
}
scriptManager.RegisterScriptControl(this);
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.Write("这是一个哑元控件");
writer.RenderEndTag();
if (!DesignMode) {
ScriptManager.GetCurrent(this.Page).RegisterScriptDescriptors(this);
}
}
IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
{
//因为这仅是一个哑元控件,所以我们只是创建一个新的实例
return new ScriptControlDescriptor("DummyNamespace.DummyControl", ClientID);
}
IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
return new ScriptReference(Page.ResolveUrl("~/DummyControl.js"));
}
}
}
上面代码中,我们在OnPreRender方法中实现注册控件,而在Render方法中注册脚本描述符部分。当然,如果页面上不存在 ScriptManager控件的话,我们必须抛出一个错误提示。但是,如果你正在开发非基于ASP.NETAJAX框架的控件的话,你完全可以从页面中 删除ScriptManager控件。
五、创建基于ASP.NET服务器端控件的增强AJAX图像控件
(一)创建示例AJAX网站
启动Visual Studio 2005,选择“文件→新建网站…”,然后选择“ASP.NET AJAX-Enabled Web Site”模板,命名工程为“AjaxServCtrlTest”,并选择C#作为内置支持语言,最后点击“确定”。
(二)创建AJAX技术支持的增强服务器控件
点击菜单“文件→添加→新建项目…”,在“添加新项目”对话框中,从左边选择“项目类型”为“Visual C#→Windows”,从右边选择“模板类型”为“Web控件库”,输入控件库的名字为AjaxImageButtonLib,选择目标目录为前面创建 的网站根目录,最后点击“确定”。
接下来,根据我们前面的分析,把类库源WebCustomControl1.cs文件的内容更改为以下形式:

     
     
//…………(省略命名空间引用部分)
namespace AjaxImageButtonLib
{
public class MySrvImageButton :
System.Web.UI.WebControls.ImageButton, IScriptControl
{
public string HoverImageUrl
{
get
{
object value = ViewState["hoverImageUrl"];
return (value == null) ? string.Empty : (string)value;
}
set
{
ViewState["hoverImageUrl"] = value;
}
}
public string ClientClickFunction
{
get
{
object value = ViewState["clientClickFunction"];
return (value == null) ? string.Empty : (string)value;
}
set
{
ViewState["clientClickFunction"] = value;
}
}
public MySrvImageButton()
: base()
{
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
ScriptManager scriptManager = ScriptManager.GetCurrent(Page);
if (scriptManager == null)
{
throw new InvalidOperationException
("ScriptManager required on the page.");
}
scriptManager.RegisterScriptControl(this);
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
if (!DesignMode)
{
ScriptManager.GetCurrent(this.Page).RegisterScriptDescriptors(this);
}
}
IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
{
ScriptControlDescriptor desc =
new ScriptControlDescriptor("AjaxImageButtonLib.MySrvImageButton", ClientID);
if (!string.IsNullOrEmpty(HoverImageUrl))
{
desc.AddProperty("hoverImageUrl", HoverImageUrl);
}
if (!string.IsNullOrEmpty(ClientClickFunction))
{
desc.AddEvent("click", ClientClickFunction);
}
yield return desc;
}
IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
yield return new ScriptReference(Page.ResolveUrl("~/SrvImageButton.js"));
}
}
}
首先,我们注意到我们要创建的新控件MySrvImageButton继承自ASP.NET服务器控件ImageButton,并继承了接口IScriptControl。
有了前面的理论描述,在此,我们省略对于其中几个常规方法的描述。
接下来,我们要构建这个控件库(即程序集)。右击此库工程,并点击“生成”命令以生成程序集AjaxImageButtonLib.dll,此库文件中即包含了我们的服务器控件。
(三)创建客户端JavaScript代码
这里创建的客户端控件类相应的JavaScript文件ImageButton.js在内容上完全相同,只不过为了区别起见,我们进行了某些地方的重新命名罢了。在此不再赘述。
(四)在示例网页中应用构建的新控件
以鼠标右击前面网站AjaxServCtrlTest,把它设置为“启动项目”。事实上,因为这个网站工程与前面的类库工程创建于同一个方案下,所 以,在前面生成程序集AjaxImageButtonLib.dll的一结束,新建的服务器控件就被自动添加到Visual Studio 2005工具栏中,如下图3所示。于是,我们可以直接把这个控件拖动到示例网页Default.aspx中。
图3:拖动新建的服务器控件到示例网页中
根据前面的控件代码实现,不出所料,点击上图3中的图形按钮控件,即可在其相应的“属性”对话框中设置这个控件的hoverImageUrl属性,而且指定其ClientClickFunction方法(其实正是此控件的click事件处理器函数指针)。
注意,因为控件代码中的方法GetScriptReferences已经为我们自动生成了前面提到的$create方法,所以我们不需要再在ScriptManager中注册在本篇中创建的JavaScript文件—SrvImageButton.js了。
(五)运行及性能简析
现在,请按F5键运行此页面并移动鼠标到图像按钮上观察,你会注意到结果与上篇中的效果一致(即在鼠标移动切换新图像时,这些动作都发生于客户浏览器端而不再与服务器端相关)。下图4相应于此示例页面运行时刻快照。
图4:示例网页运行时刻屏幕快照
通过以鼠标右击网页并选择弹出菜单中的“查看源文件”观察上、下篇中示例页面相应的源码,我们会注意到其内容基本是一致的。另外,通过使用Fiddler观察这两个示例页面下载到客户端时各模块的大小,你也会注意到基本一致,如下面图5所示。
图5:两个示例页面下载到客户端时各模块大小比较
因为本文两个例子极为简单,所以其性能基本平衡。但随着服务端编程的复杂化,本篇中基于服务器端控件的扩展方案应该有较大的性能损耗。但应该仍具有 令人满意的效果,这也正是AJAX Control Toolkit控件数量急剧增加的重要原因之一。而上篇中的方案基于“纯粹”(相对而言)的客户端,即使性能上与本篇中方案相差无几,但是却明显多出了跨 越服务器端平台的优势,这也正是上篇中方案吸引人的主要原因。
六、总结
虽然以上、下两个篇幅形成此文,但是这也仅能通过简短的例子向你阐述了开发ASP.NETAJAX框架中的Ajax控件所涉及的主要技术。尽管目前 的ASP.NET AJAX框架已经形成正规的1.0版本,而且这个框架为基于AJAX技术开发以ASP.NET 2.0为主的Web应用提供了全方位支持,但是这个框架仍然在许多方面有待改进。事实上,我们可以进一步沿着ASP.NET AJAX客户端与服务器端架构层次关系图进一步扩展其底层。当然,在此框架与Visual Studio整合方面也存在相当的挖掘潜力。
如今,随着微软Silverlight技术的推出,ASP.NET AJAX框架的重要性日显突出。自然,与此框架相关的控件开发也必将在这一大环境中占居着重要的位置。
















本文转自朱先忠老师51CTO博客,原文链接: http://blog.51cto.com/zhuxianzhong/59816 ,如需转载请自行联系原作者

相关文章
|
8月前
|
存储 机器学习/深度学习 人工智能
硅谷GPU单节点服务器:技术解析与应用全景
“硅谷GPU单节点服务器”代表了在单个物理机箱内集成强大计算能力,特别是GPU加速能力的高性能计算解决方案。它们并非指代某个特定品牌,而是一类为处理密集型工作负载而设计的服务器范式的统称。
|
存储 机器学习/深度学习 数据库
阿里云服务器X86/ARM/GPU/裸金属/超算五大架构技术特点、场景适配参考
在云计算技术飞速发展的当下,云计算已经渗透到各个行业,成为企业数字化转型的关键驱动力。选择合适的云服务器架构对于提升业务效率、降低成本至关重要。阿里云提供了多样化的云服务器架构选择,包括X86计算、ARM计算、GPU/FPGA/ASIC、弹性裸金属服务器以及高性能计算等。本文将深入解析这些架构的特点、优势及适用场景,以供大家了解和选择参考。
1607 61
|
11月前
|
人工智能 运维 安全
MCP协议深度解析:客户端-服务器架构的技术创新
作为一名长期关注AI技术发展的博主摘星,我深刻感受到了MCP(Model Context Protocol)协议在AI生态系统中的革命性意义。MCP协议作为Anthropic公司推出的开放标准,正在重新定义AI应用与外部系统的交互方式,其基于JSON-RPC 2.0的通信机制为构建可扩展、安全的AI应用提供了坚实的技术基础。在深入研究MCP协议规范的过程中,我发现这一协议不仅解决了传统AI应用在资源访问、工具调用和上下文管理方面的痛点,更通过其独特的三大核心概念——资源(Resources)、工具(Tools)、提示词(Prompts)——构建了一个完整的AI应用生态系统。MCP协议的客户端-
750 0
MCP协议深度解析:客户端-服务器架构的技术创新
|
安全 网络安全 定位技术
网络通讯技术:HTTP POST协议用于发送本地压缩数据到服务器的方案。
总的来说,无论你是一名网络开发者,还是普通的IT工作人员,理解并掌握POST方法的运用是非常有价值的。它就像一艘快速,稳定,安全的大船,始终为我们在网络海洋中的冒险提供了可靠的支持。
401 22
|
存储 机器学习/深度学习 算法
阿里云X86/ARM/GPU/裸金属/超算等五大服务器架构技术特点、场景适配与选型策略
在我们选购阿里云服务器的时候,云服务器架构有X86计算、ARM计算、GPU/FPGA/ASIC、弹性裸金属服务器、高性能计算可选,有的用户并不清楚他们之间有何区别。本文将深入解析这些架构的特点、优势及适用场景,帮助用户更好地根据实际需求做出选择。
|
存储 机器学习/深度学习 人工智能
阿里云第八代云服务器c8i与g8i深度解析:技术对比、场景适配与选购指南
阿里云服务器计算型c8i与通用型g8i实例属于阿里云的第八代云服务器实例规格,是除了计算型c7与c8y和通用型g7与g8y之外同样深受用户喜欢的云服务器实例规格。本文将详细解析计算型c8i与通用型g8i实例的技术特性、适用场景、性能优势,以及最新的活动价格情况,并为用户提供购买建议。
|
存储 弹性计算 人工智能
阿里云服务器ECS g8i实例怎么样?新一代g8i实例技术特性与场景应用解析
阿里云服务器ECS g8i实例怎么样?对于很多企业用户说,云服务器的性能、安全性和AI能力是用户非常关注的。无论是处理大规模数据、运行复杂算法,还是保障业务应用的安全,都需要云服务器具备卓越的性能和强大的功能。阿里云推出的第八代云服务器ECS g8i实例,凭借其卓越的性能、增强的AI能力和全面的安全防护,成为了市场关注的焦点。本文将为大家解析ECS g8i实例的技术特性、产品优势、适用场景及与同类产品的对比,同时介绍其收费标准和活动价格,以供大家了解和选择。
阿里云服务器ECS g8i实例怎么样?新一代g8i实例技术特性与场景应用解析
|
存储 弹性计算 安全
ECS与VPS技术角力:从算力成本到免备案雷区,企业服务器选型合规指南
在数字化浪潮中,服务器选择至关重要。ECS(云服务器)和VPS(虚拟专用服务器)是热门选项。ECS基于云计算,提供高可用性和弹性伸缩,适合大型项目;VPS通过分割物理服务器实现资源独立,成本较低,适合小型应用。两者在网络、存储及计算性能上各有优劣,需根据需求选择。国内并不存在合法的免备案服务器,建议严格遵守法规,确保网站合法运营。
833 3
|
存储 弹性计算 人工智能
阿里云服务器第九代企业级g9i实例技术特点、性能优势、适用场景简介
阿里云不断推出创新产品和技术,以满足市场对高性能、高可靠、高性价比云计算资源的需求。近日,阿里云正式面向全球发布了第九代企业级实例ECS g9i,并开启了邀测活动。本文将深入解析阿里云ECS g9i实例的技术特点、性能优势、适用场景以及购买建议,帮助用户更好地了解并选择合适的云服务器实例。
|
安全 大数据 Linux
云上体验最佳的服务器操作系统 - Alibaba Cloud Linux | 飞天技术沙龙-CentOS 迁移替换专场
本次方案的主题是云上体验最佳的服务器操作系统 - Alibaba Cloud Linux ,从 Alibaba Cloud Linux 的产生背景、产品优势以及云上用户使用它享受的技术红利等方面详细进行了介绍。同时,通过国内某社交平台、某快递企业、某手机客户大数据业务 3 大案例,成功助力客户实现弹性扩容能力提升、性能提升、降本增效。 1. 背景介绍 2. 产品介绍 3. 案例分享
491 1