asp.net|web|程序|创建|客户端
提要 本文介绍了Atlas框架,并探讨它的客户端和服务器端类库及其编程模型。另外,本文还详细剖析了一个支持Atlas功能的示例Web应用程序。
一、 开发环境说明
本文中所提供的信息适用于下列技术:Asp.net 2.0,Asp.net Atlas CTP,Visual Studio Professional 2005和Visual Web Developer 2005。
二、 简介
Atlas是一个框架的代号,该框架对于客户端Web应用程序的开发方面扩展了asp.net。该框架在提供一组客户端和服务器端类来创建跨浏览器兼容的AJAX风格的应用程序的同时,还引入了其它特征,例如桥接技术,gadget,一个JavaScript的声明性脚本模型和扩展。
本文将介绍Atlas框架并探讨它的客户端和服务器端类库及其编程模型。另外,本文还详细剖析了一个支持Atlas功能的示例Web应用程序。
三、 基于客户端和服务器端的Web应用程序
现在,Web应用程序开发主要针对于http客户端(浏览器)和服务器开发。Asp.net Web应用程序是基于服务器的(在该主机上运行),因此,对于由在客户端上的一个服务器控件激发的每一个事件都要求一个完整的回寄。这样的情形可以用图1所示来描述。
图1.一个针对asp.net Web应用程序的http回馈
只在服务器端运行Web应用程序,而几乎不需要(或很少需要)客户端处理,并且不会造成性能下降。不过,其缺点也很容易在一个asp.net Web应用程序发现:一个闪烁的、暂停的、不具有响应性的和相对可怜的UI;或者是,由于数据回寄和服务器过载而导致一个繁忙的线路。
要在asp.net应用程序解决这些性能障碍意味着,必须把一些加载处理移到客户端并且利用客户端平台所提供的技术。客户端平台是可以通过脚本进行编程的,而JavaScript就是适合于这种任务的一种标准的面向对象的编程语言。
那么,上面这些客户端平台技术指的是什么呢?这些客户端平台(浏览器)提供了下列技术:
· 文档对象模型:一种标准化的语言独立的一组对象集合,允许开发者动态地控制HTML文档的结构、内容和风格。
· 动态的超文本标记语言对象模型:一个浏览器供应商特定的特征集合,可以用作DOM的一个扩展。数据绑定、UI效果(例如过滤器和过渡)、HTML元素行为和事件都是在这个对象模型内部所提供的一些特征。
· XmlHttpRequest对象:它允许通过Http检索和提交XML数据而不要求一种整个Web文档的完整的回馈或重新生成。
· 一个JavaScript解释器:包含在所有的Web浏览器中,由它处理用JavaScript书写的命令。JScript是微软版本的JavaScript,它最初由Netscape所创建。两种版本都遵循ECMAScript标准—供应商中立的,跨平台的,通用目的的脚本语言。
这些技术合在一起被称为AJAX,代表的意思是异步JavaScript+XML;而Atlas正是一种利用这些技术的创建Web应用程序的框架。下面的图2展示了一个支持Atlas技术的asp.net Web应用程序。
图2.Http请求和响应一个支持Atlas技术的,基于客户端的asp.net Web应用程序
四、 Atlas框架概要
该框架包含了Microsoft.Web.Atlas.dll装配集,它包含了服务器端托管的和客户端JavaScript API。
下图3展示了Visual Studio的对象浏览器窗口中的Atlas命名空间。
图3.在Microsoft.Web.Atlas.dll装配集中的命名空间
(一) 服务器端库
在图3框架中展示的命名空间中提供的各种类担任服务器端库。该库提供与客户端JavaScript API一起工作的配置、Web服务和控件类。
该Web服务类把asp.net特征,例如认证、轮廓、文化和全球化等信息,暴露给客户端JavaScript代码以便进行异步存取。另一方面,Atlas服务器控件类,在生成这些控件时能够“发出”JavaScript,从而使开发者免于编写复杂的客户端脚本。
服务器端库还提供Atlas extender控件,它能够提供给asp.net控件其它客户端功能。
下列控件是服务器端库的一部分:
· ScriptManager控件:提供了在一个Web页面上的所有的Atlas特征,例如部分页面更新,定制和库客户端脚本参考和生成,针对客户端异步存取的Web服务引用,而异常处理是由该控件管理的。每一个需要实现Atlas功能的asp.net Web页面或用户控件都需要声明这个控件的单个实例。为了在一个页面上使用ScriptManager控件,你可以使用下列声明性语法:
<atlas:ScriptManager
ID="ScriptManager instance identifier"
<!--enables or disables partial page rendering using UpdatePanel controls-->
EnablePartialRendering="boolean true or false"
<!--If set to false the AtlasRuntime.js file, which provides basic 'Atlas functionality is referenced by default.
If set to true the Atlas.js file, which provides the entire Atlas feature set is referenced by default.
The default value is true-->
EnableScriptComponents="boolean true or false"
OnPageError="invoked event handler on PageError "
runat="server" >
<Scripts>
<atlas:ScriptReference
<!--to reference custom script files-->
Path="path to .js file"
<!--to reference client library files that are not included automatically-->
ScriptName="name of script file e.g. AtlasUIGlitz"/>
</Scripts>
<Services>
<atlas:ServiceReference
<!--If set to true the control generates a JavaScript proxy object for asynchronous access for the referenced Web Service.
If set to false it doesn't.-->
GenerateProxy="boolean true or false"
Path="path to a Web service (e.g. asmx) file"
Type="Web service class name"
/>
</Services>
<ErrorTemplate>
<!--Markup for rendering unhandled exception messages for asynchronous postback.
Partial rendering should be enabled. The template has to define an input button with an attributes ID of value "okButton" and runat of value "server" to close the message. -->
</ErrorTemplate>
</atlas:ScriptManager>
· ScriptManagerProxy控件:对于内容页面和用户控件来说,如果它们的父页面已经拥有一个定义好的ScriptManager控件,那么这个控件可以用于参考其它脚本和服务。但是,该控件不能被ScriptManager控件用于删除脚本和服务参考。
· UpdatePanel控件:当通过ScriptManager控件支持一个Web页面的部分生成时,UpdatePanel控件可以用于指定页面上的区域—能够被独立地使用异步回馈进行更新。下列声明性语法用于在一个Web页面中定义一个UpdatePanel控件:
<atlas:UpdatePanel
ID="UpdatePanel instance identifier"
<!-- If Mode attribute is set to Always asynchronous postbacks triggered within the region update its contents automatically;
If it is set to Conditional the region is updated in response to a registered trigger -->
Mode="Always|Conditional"
<!-- If RenderMode attribute is set to Block the content within the UpdatePanel is rendered using a <DIV> element;
If it is set to Inline a <SPAN> element is used as a container for the content within the UpadatePanel -->
RenderMode="Block|Inline"
runat="server">
<ContentTemplate>
<!-- Content to be rendered within the region-->
</ContentTemplate>
<!a€”A Collection of objects that trigger an asynchronous update on the panel. These Objects don't need to be declared within the region. -->
<Triggers>
<ControlValueTrigger
ControlID="object instance identifier"
PropertyName="property value that triggers the update"/>
<ControlEventTrigger
ControlID="object instance identifier"
EventName="the name of the event that triggers the update"/>
</Triggers>
</atlas:UpdatePanel>
· TimerControl:它在客户端生成一个定时器,由该客户端以指定的时间间隔触发异步回馈。该控件通常用作一个要求定时更新内容的UpdatePanelat控件的触发器控件。为了以声明方式定义这个控件,需要使用下列语法:
<atlas:TimerControl Enabled="boolean true or false" ID="Control instance identifier"
<!--If the Enabled property is set to true the control is defined on the client-side. If not it isn't.-->
Interval="Interval in milliseconds. the default is 60000."
OnTick="invoked server-side event handler name" runat="server"/>
· Extender控件:它们使用增加的客户端功能扩展asp.net控件。例如,AutoCompleteExtender控件支持asp.net文本框控件的自动完成行为,而DragOverlayExtender控件支持拖动行为。
· 开发者还可以使用一个与Atlas控件工具箱一同提供的Visual studio 2005工程模板创建定制的asp.net Atlas控件扩展器。
(二) 客户端库
客户端库包括一组(.js)JavaScript文件,它们被打包为Microsoft.Web.Atlas.dll装配集中的资源。
包含在这个类库中的对象提供了下列特征:
· JavaScript语言扩展:允许开发者以JavaScript编程,而同时还能使用使用OO结构,例如命名空间、类、枚举、接口和数据类型。
· JavaScript基库扩展:这包括用于调试,跟踪和字符串操作的其它对象。
· 浏览器兼容性:对于定制脚本和由Atlas控件生成的脚本的自动浏览器可移植性。
· 网络功能:由位于Sys.Net命名空间内部的对象提供。这些功能使得与主机的异步通讯和执行远程方法的编程相当容易。
· HTML控件包装器:它们允许开发者使用xml脚本添加特征—例如数据绑定,行为以及到许多HTML控件和元素的动作。
· Atlas客户端控件:支持开发者使用JavaScript或XML脚本创建丰富的应用程序;这些包括在Sys.UI.Data命名空间内部的控件,例如ListView,DataNavigator,ItemView,XSLTView,等等。
· Xml-Script:一个声明性脚本模型,它允许开发者使用一种类似于asp.net的编程模型书写客户端代码。Atlas声明性脚本被使用下列语法定义在<script></script>标签内部:
<script type="text/xml-script">
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
<references>
</references>
<components>
</components>
</page>
</script>
整个客户端库都包含在Atlas.js文件中,并且当在一个页面中定义一个ScriptManager控件时被默认地参考。另外地,为了减少在客户端生成的脚本的数量,我们可以把ScriptManager控件的EnableScriptComponents设置为false并且使用包含在AtlasRuntime.js文件中的该库的一个简化版本。另外,专门的库文件,例如AtlasDragandDrop.js,AtlasUIMap.js,AtlasUIGlitz.js等等,都可以按名使用ScriptManager控件的脚本集合属性进行引用。
五、 Mash-up和Gadget(widget)
Atlas中引入了两种新的特征:桥接技术和gadget。桥接技术允许Web应用程序消费来自多种远程Web服务的数据—当连接到一个单一的主机上时。这些消费一个或更多的远程服务的Web应用程序通常被称作是Mash-up。为了实现这一目的,该框架引入了桥接文件,以.asbx扩展名标志。其实,桥接文件是XML文件—允许我们以声明方式来定义到服务的连接并实现数据转换。下图4展示了一个通过Atlas桥接技术消费(mashing-up)来自多种远程Web服务上的数据的Web应用程序:
图4.消费来自多种远程服务的数据
对于不同的平台存在不同类型的gadget。一个基于web的gadget是一个可移植的web应用程序—能够被发布到任何gadget宿主网站上,例如,live.com或start.com。一个基于web的gadget的组成如下:
· 一个Xml声明:它包含该gadget本身的信息(标题,描述,出版商,构建信息,等等)以及到该gadget组件的链接(.jss和.css文件)。下列是一个针对一个虚构的gadget(widget)的示例manifest文件:
<?xml version="1.0" ?>
<rss version="2.0" xmlns:binding="http://live.com">
<channel>
<title>Widget alpha</title>
<link>http://www.contoso.com</link>
<description>What does this gadget do?</description>
<language>en-gb</language>
<pubDate>Date</pubDate>
<!--Javascript function entry point; used by the host to load the gadget . -->
<binding:type>Widget.alpha</binding:type>
<item>
<description>The JavaScript code component</description>
<link>http://www.contoso.com/Gadgets/Widget/alpha.js</link>
</item>
<item>
<description>This adds style to the gadget</description>
<link>http://www.contoso.com/Gadgets/Widget/alpha.css</link>
</item>
</channel>
</rss>
· JavaScript代码:包含在该manifest文件链接到的.js文件中;它定义将被宿主的可移植组件。
· 式样表:它定义主机用来生成上面gadget的式样。
六、 测试驱动的框架
本文将在asp.net应用程序中使用Atlas UpdatePanel控件和部分页面生成技术。
这里所提供的示例是一个Amazon电子商务服务Web客户端应用程序,它使用City,Cuisine和Neighbourhood搜索参数来搜索在整个美国的餐馆。该示例应用程序使用了一个UpdatePanel控件来进行异步回馈和部分页面生成;从而使应用程序更为迅速和更具交互性以改进用户体验。
(一) 需求
· 微软Visual Studio 2005,.Net框架2.0及最新的Atlas CTP。
· 注册(免费)Amazon Web服务以取得存取键ID—用它来存取该电子商务服务。
(二) 配置网站
通过使用与框架的CTP一起安装的Atlas工程模板创建一个新的网站:
1. 打开Visual studio 2005。
2. 点击“文件”菜单,选择“新建”,然后点击Website。
3. 从“New Web site”对话框中选择“Atlas project”模板,位置,工程名和开发语言(VB或C#)。本例中所使用的语言为C#。
下面的图5显示了在Visual Studio 2005中的“New Web Site”对话框。
图5.“New Web Site”对话框窗口
(三) 为SOAP请求配置服务
1. 登录到你使用Amazon Web服务创建的帐户并且使用提供的链接来保存到你的计算机上的WSDL文件中。
2. 从.Net框架2.0 SDK命令提示窗下使用WSDL.exe工具为你在第1步保存的WSDL中的服务生成一个代理类:
Wsdl <options> <URL | path>
3. 从你用Visual Studio创建的工程中打开Solution Explorer窗口,并右击工程文件,指向“Add asp.net”文件夹并且点击“App-Code”。
4. 右击Solutions Explorer窗口中的“App-Code”文件夹并且点击“Add Existing Item”。
5. 从“Add Existing Item”对话框中浏览到你前面所创建的代理文件,选择它并且点击“Add”;这将把服务代理文件添加到工程中。
(四) 创建客户端UI
1. 在Solutions Explorer中,双击Default.aspx文件,从而在Visual Studio designer窗口中打开它。
2. 请确保你位于源码视图中,然后在文档的<form id="form1" runat="server">和</form>之间复制并粘贴下列代码:
<atlas:ScriptManager ID="ScriptManager1" EnablePartialRendering="true" runat="server" EnableScriptComponents="true"/>
<asp:Label ID="Label1" runat="server" Width="366px" Font-Bold="True" Font-Names="Verdana Ref" Font-Size="Small" Height="19px">SEARCH FOR RESTAURANTS WITH AMAZON.COM</asp:Label><br />
<br />
<asp:Label ID="Label2" runat="server" Text="Access Key ID:" Width="128px" Font-Names="Verdana Ref"></asp:Label>
<asp:TextBox ID="TxtBAccessKey" runat="server" Width="182px" Font-Names="Verdana Ref"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="*"
Width="16px" ControlToValidate="TxtBAccessKey"></asp:RequiredFieldValidator><br />
<asp:Label ID="Label3" runat="server" Text="Cuisine:" Font-Names="Verdana" Width="58px"></asp:Label>
<!--The ListBoxCuisine ListBox holds all possible entries for the Cuisine parameter supported by the amazon ECS-->
<asp:ListBox ID="ListBoxCuisine" runat="server" Rows="1" Width="206px" OnSelectedIndexChanged="ListBoxCuisine_SelectedIndexChanged" Font-Names="Verdana Ref" AutoPostBack="True">
<asp:ListItem Text="American cuisine" Value="American cuisine"></asp:ListItem>
<asp:ListItem Text="Asian cuisine" Value="Asian cuisine"></asp:ListItem>
<asp:ListItem Text="Seafood" Value="Seafood"></asp:ListItem>
<asp:ListItem Text="Greek" Value="Greek"></asp:ListItem>
<asp:ListItem Text="Indian" Value="Indian"></asp:ListItem>
<asp:ListItem Text="Italian" Value="Italian"></asp:ListItem>
<asp:ListItem Text="Japanese" Value="Japanese"></asp:ListItem>
<asp:ListItem Text="Chinese" Value="Chinese"></asp:ListItem>
</asp:ListBox>
<br />
<asp:Label ID="Label5" runat="server" Font-Names="Verdana" Text="City:"
Width="61px">
</asp:Label>
<!a€”The Amazon E-Commerce Service supports only the cities defined as list items of the ListBox control-->
<asp:ListBox ID="listBoxCity" runat="server" Height="19px" Width="221px" AutoPostBack="True" EnableTheming="False" Rows="1" OnSelectedIndexChanged="listBoxCity_SelectedIndexChanged" Font-Names="Verdana Ref" >
<asp:ListItem Text="Seattle" Value="Seattle"></asp:ListItem>
<asp:ListItem Text="Boston" Value="Boston"></asp:ListItem>
<asp:ListItem Text="San Francisco" Value="San Francisco"></asp:ListItem>
<asp:ListItem Text="New York" Value="New York"></asp:ListItem>
<asp:ListItem Text="Washington, D.C." Value="Washington, D.C."></asp:ListItem>
<asp:ListItem Text="Chicago" Value="Chicago"></asp:ListItem>
</asp:ListBox>
<br />
<asp:Label ID="Label6" runat="server" Font-Names="Verdana Ref" Text="Neighbourhood:" Width="59px">
</asp:Label>
<asp:TextBox ID="TextBox3" runat="server" Width="143px" Font-Names="Verdana Ref">
</asp:TextBox>
<asp:Button id="submitSearch" runat="server" Height="23px" Text="Submit"
Width="54px" Font-Names="Verdana Ref" />
<br />
3. 切换到设计视图;设计器应该生成如图6所示的UI。
图6.示例应用程序的UI
(五) 配置UpdatePanel控件
1. 切换到源码视图;在标注后面的<br和/>标签之间添加下列代码:
<atlas:UpdatePanel ID="UP1" EnableViewState="true" Mode="Conditional" RenderMode="Inline" runat="server">
<ContentTemplate>
</ContentTemplate>
<Triggers>
</Triggers>
</atlas:UpdatePanel>
当触发一个已注册的控件中的事件时,UpdatePanel控件被有条件地进行更新。注册的事件在服务器端被通过异步回寄处理。
2. 在UpdatePanel控件的<ContentTemplate>和</ContentTemplate>元素之间,加入下面的标注:
<atlas:UpdateProgress>
<ProgressTemplate >
<asp:Label ID="Label4" runat="server" Font-Names="Verdana Ref" Font-Size="X-Small"
Text="Loading..." Width="81px"></asp:Label>
</ProgressTemplate>
</atlas:UpdateProgress>
<br />
<asp:Repeater ID="RP1" runat="server">
<ItemTemplate>
</ItemTemplate>
</asp:Repeater>
<asp:Label ID="NoResults" runat="server" Width="449px" Font-Names="Verdana Ref" ></asp:Label>
<br /> <br />
<asp:Label ID="PriceRange" runat="server" Font-Names="Verdana Ref" Font-Size="X-Small">
</asp:Label>
<br />
<br />
<asp:Label ID="labelError" runat="server" Width="451px" Font-Names="Verdana Ref">
</asp:Label>
当正在更新区域时,UpdateProgress控件显示一个忙指示器(“加载中……”)。
Repeater和Label控件负责存储搜索结果及潜在的错误消息结果。
3. 为了注册将触发部分更新的控件,把下列代码片断放到UpdatePanel控件的<Triggers>和</Triggers>元素之间:
<atlas:ControlEventTrigger ControlID="submitSearch" EventName="Click" />
<atlas:ControlEventTrigger ControlID="listBoxCity" EventName="SelectedIndexChanged" />
<atlas:ControlEventTrigger ControlID="listBoxCuisine" EventName="SelectedIndexChanged" />
(六) 在客户端应用程序添加代码
切换到设计视图,双击生成的Web表单以显示页面相应的代码部分(Default.aspx.cs)。选择Ctrl+A来选择所有的自动生成的代码,并按Delete键清除文档。然后,添加下列代码以消费Amazon ECS服务并且显示搜索结果:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
{
protected AWSECommerceService AmazonECS = new AWSECommerceService();
protected ItemSearch Search = new ItemSearch();
protected ItemSearchRequest SearchRequest = new ItemSearchRequest();
protected ItemSearchResponse SearchResponse;
protected void submitSearch_Click(object sender, EventArgs e)
{
Search.AWSAccessKeyId = TxtBAccessKey.Text.ToString();
SearchRequest.SearchIndex = "Restaurants";
SearchRequest.Cuisine = ListBoxCuisine.SelectedValue;
SearchRequest.City = listBoxCity.SelectedValue;
SearchRequest.Neighborhood = TextBox3.Text.ToString();
SearchRequest.ResponseGroup = new String[] { "ItemAttributes" };
Search.Request = new ItemSearchRequest[1] { SearchRequest };
try
{
SearchResponse = AmazonECS.ItemSearch(Search);
if (SearchResponse.Items == null)
{ labelError.Text = "A Server error has occured."; }
else
{
Items responseItems = SearchResponse.Items[0];
Item[] response = responseItems.Item;
if (response != null)
{
foreach (Item I in response)
{
NoResults.Text = "";
Label Results = new Label();
Label Sep = new Label();
Results.Text = "<strong>" + I.ItemAttributes.Title.ToUpper() + "</strong>" + "<br/>"
+ I.ItemAttributes.Address.Address1.ToString() + "<br/>"
+ I.ItemAttributes.Neighborhood + "<br/>"
+ "Tel:" + " " + I.ItemAttributes.PhoneNumber + "<br/>"
+ "Price Rating:" + " " + priceRating(I.ItemAttributes.PriceRating)+"<br/>"+"<br/>";
Sep.Text = "<br/>";
RP1.Controls.Add(Results);
RP1.Controls.Add(Sep); }
PriceRange.Text ="Price per person (based on entree, appetizer or salad, one non-alcoholic drink plus tax and tip)";
}
else
{
NoResults.Text = "No search results found.";
PriceRange.Text = "";
}
}
}
catch (Exception ex)
{
labelError.Text = ex.Message.ToString();
}
}
private string priceRating(string str)
{
if (str=="1"){
return "under $15";}
else if(str=="2"){
return "$15-30";}
else if(str=="3"){
return "$30-45";}
else if(str=="4"){
return "over $45";}
else{return null;}
}
protected void listBoxCity_SelectedIndexChanged(object sender, EventArgs e)
{}
protected void ListBoxCuisine_SelectedIndexChanged(object sender, EventArgs e)
{}
}
(七) 运行应用程序
1. 为了运行应用程序,在设计视图下打开Default.aspx页面。选择TxtBAccessKey TextBox控件;在Properties窗口中把你的Amazon Web服务存取键ID添加到该控件的Text属性中。
2. 按F5键以运行该应用程序。
3. 使用应用程序的过程是相当直接的。从Cuisine:列表框中选择一种cuisine类型,从City:列表框中选择一个城市,然后点击Submit按钮。作为选择,你还可以细化你的搜索。
(八) 从浏览器中使用Amazon ECS Web服务
1. 使用一个桥接文件来指定消费远程Web服务的代理类、调用该服务的方法以及如何操作返回的数据。
2. 使用ScriptManager控件参考桥接文件。
3. 使用html控件,JavaScript和客户端Atlas数据组件来使用服务即可。
七、 结论
Asp.net Atlas是一个创建基于客户端的Web应用程序的框架。这个框架在提供客户端和服务器端API用来创建跨浏览器兼容的AJAX风格的应用程序的同时,还引入了另外一些特征,例如桥接技术,gadget,一个JavaScript声明性脚本模型和扩展,等等。
总之,本文介绍了该框架的典型使用框架;还通过使用Atlas UpdatePanel控件介绍了部分(Partial)页面生成技术,这是在asp.net Web应用程序中增加AJAX功能和改进用户体验的最简单的方法。