Professional Documents
Culture Documents
com
Altas 学习指南
Dflying
http://dflying.cnblogs.com
博客园 @ Dflying i
Atlas 学习指南 Dflying http://dflying.cnblgos.com
目 录
ALTAS学习指南 ............................................................... I
使用 UpdatePanel 很简单,只需要如下几个步骤:
考虑如何与服务器通信,所有的细节,Atlas 已经为你做好了。
使用 UpdatePanel 中应该注意的几个问题:
• ControlValueTrigger:当某个控件的某个指定的属性变化时更新。例如:ControlID="dropDownList1"
PropertyName="SelectedValue"
• ControlEventTrigger:当某个控件发出指定事件时更新。例如:ControlID="button1"
EventName="Click"
博客园 @ Dflying 1
Atlas 学习指南 Dflying http://dflying.cnblgos.com
>
3 <Triggers>
e" />
6 </Triggers>
7 <ContentTemplate>
9 </ContentTemplate>
10 </atlas:UpdatePanel>
11
我曾在此发表了一个对UpdatePanel的简要介绍
(http://dflying.cnblogs.com/archive/2006/03/25/358547.html)并得到了很多的反馈与问题。我
想有必要把这些问题以及有关UpdatePanel的使用技巧总结成一个帖子。希望能有所帮助。在这里感谢阿不,
dudu以及所有提出问题或参与讨论的朋友,让我对UpdatePanel有更深的认识。
首先,最重要的事情就是关注Atlas的老家:http://atlas.asp.net/。我们知道Atlas是一个新的,正在开发
中的Framework,每月,甚至每周都在发生着变化,所以作为一个Atlas开发人员,经常关注
http://atlas.asp.net/是必须的,你会得到最新的消息,最新的特性以及最新的演示程序。对于新手,
http://atlas.asp.net/docs提供了Atlas的API,Class文档可作参考(尚未全部完成,请多加关注)。下面
还有一些Atlas以及ASP.NET的核心人物的个人网站/blog,同样值得经常访问(英文):
1. http://blogs.msdn.com/brada/
2. http://weblogs.asp.net/scottgu/
3. http://www.nikhilk.net/
4. http://weblogs.asp.net/bleroy/
5. http://blogs.msdn.com/jhawk/
定这个属性。
ControlEventTrigger,指定的属性/事件都是服务器端属性/事件,都只在服务器端属性变化或
3. 区别UpdatePanel的两种更新方式:Always和Conditional。请参考:
http://dflying.cnblogs.com/archive/2006/03/25/358547.html。我们应该设定正确的更新方
式以避免更新不必要更新的Panel,造成不必要的性能/网络开销。
内部的控件,在某些情况下可能非常低效,例如,对于一个包含了一个有相当多结点的 TreeView 控
中的服务器端控件 ScriptManager。
会更好或者干脆现在想办法自己解决吧。
C. 绑定(Binding)
Atlas架构提供了一种比ASP.NET中数据绑定(data binding)强大得多的客户端绑定模型。这种模型
异常灵活,甚至有些类似WPF(Windows Presentation Foundation)中的绑定模型。Atlas提供的
绑定模型允许您将某对象的任意一个属性绑定到另外一个对象的任意一个属性上。它不单单可以应用于
数据绑定,甚至可以将某个控件的样式绑定到另外一个控件上。这样使得在 Atlas中将一切关联起来变
成可能。
(注意必须声明一个ScriptManager服务器端对象,以引入 Atlas
HTML和ASPX,定义textbox和select list。
必须的JavaScript文件。)
Atlas脚本,将上面两个HTML控件“升级”成 Atlas控件。
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
<references>
</references>
<components>
<textBox id="myTextBox">
<bindings>
<binding dataContext="mySelect" dataPath="selectedValue" property="text"
direction="InOut" />
</bindings>
</textBox>
<select id="mySelect" />
</components>
</page>
如上所示,我们只需要书写一小段简单的代码即可实现需要的绑定功能。
Atlas是如何实现这些的呢?首先,Atlas需要有一种途径来监听绑定控件的绑定属性的变化(除非你不
需要 Atlas提供的自动绑定功能)。在 Atlas.js中定义了一个名为Sys.INotifyPropertyChanged的接
口,类似.NET中提供的一样。对象可以实现这个接口以期让别的对象监听到自己的属性值的变化。Atlas
中所有组件的基类,Sys.Component,实现了这个接口。Sys.Component同样提供一个方法
raisePropertyChanged(propertyName),这个方法应该在每个属性的setter中被调用以发出
INotifyPropertyChanged.propertyChanged事件。
目前为止,我们可以看一下 Atlas控件中textbox的具体实现。看看textbox中是如何在相应的HTML事件发
出时同样发出propertyChanged事件的。
var _text;
var _changeHandler;
this.get_text = function() {
return this.element.value;
}
this.set_text = function(value) {
if (this.element.value != value) {
this.element.value = value;
this.raisePropertyChanged('text');
}
}
this.initialize = function() {
Sys.UI.TextBox.callBaseMethod(this, 'initialize');
_text = this.element.value;
this._onChanged = function() {
if (this.element.value != _text) {
_text = this.element.value;
this.raisePropertyChanged('text');
}
}
可以看到,当text属性改变时,Atlas发出了propertyChanged事件,这就使绑定到这个属性成为可能。
而后 Atlas的绑定模型捕获到了这个事件,再根据binding声明查找出与其相关的目的对象以及相应的属性,
并调用这个属性的Setter来实现目的对象属性的变化。
如果源对象(source object)实现了INotifyPropertyChanged接口,并且改变的属性就是dataPath 中指
定的属性,同时direction 设定为In或者InOut,Atlas绑定将通过分析引入(incoming)的binding来处
理propertyChanged事件(参考下面将要介绍的evaluateIn()方法)。
类似的,如果目的对象(target object)实现了INotifyPropertyChanged接口,并且改变的属性就
是property中指定的属性,同时direction 设定为Out或者InOut,Atlas绑定将通过分析流出
(outgoing)的binding来处理propertyChanged事件(参考下面将要介绍的evaluateOut()方法)。
接下来让我们察看binding实现代码中的的公有方法和属性来分析一下 Atlas绑定的核心实现。在这里没有必
要列出涉及绑定的全部代码,如果您感兴趣,可以用关键词Sys.BindingBase和Sys.Binding 在 Atlas.js
文件中进行搜索。首先是Sys.BindingBase提供的方法和属性。
1. 属性 automatic:指定当源对象的相应属性变化时(对于 In 和 InOut)
,或者目的对象的相应属性
功返回的时候才开始绑定数据源与显示控件,以确保显示控件真正绑定到了一些数据,这时你需要显
sourceObjectProperty.nestedProperty.nestedNestedProperty。源代码中可以看出 Atlas 能自
4. 属性 property:指定需要绑定的目标对象的属性。你应该总是指定这个属性,否则这个绑定就没有
任何意义。
5. 属性 propertyKey:有时候我们可能需要绑定到某个对象的嵌套属性上。比如,如果需要绑定到
会用到。
7. 事件 transform:这个事件允许在绑定时指定一个 transformer。当你需要在绑定的时候对数据做
Sys.Binding(也在 Atlas.js中)中也有一些重要的方法/属性:
In。
希望这些解释能够让您对 Atlas的“神奇的”绑定有一些更深入的理解。欢迎留言探讨。
PS:这篇文章中有些英文不知道应该如何用中文表示,希望能得到一些建议以及指正:
1. evaluate,我翻译成“处理”,但文中还有“计算求值”的意思,这一点没有体现出来。
2. incoming 和 outgoing,我翻译成“引入”和“流出”……觉得不是一般的别扭。
3. transformer,没有翻译(实在不知道怎么说了)。
4. getter 和 setter,没有翻译(一直都不知道怎么翻译)。
A. DataSource 和 XMLDataSource
我的关于这部分控件的使用心得与经验,希望对各位能有所帮助。请注意这个系列仅仅是一些介绍,也就是
说,这里我会主要谈论一些如何使用的方法,而不会过多涉及到这些控件是如何实现的以及它们的工作原理。
如果您对这些较高级的话题感兴趣,我会在未来的文章中有所涉及。但个人感觉目前的首要任务还是普及
误的部分,这里还请您不吝指出。也欢迎留下您的宝贵看法。
OK,开头部分废话到此为止,让我们切入正题。
象。
1. Sys.Data.DataSource:描述一个表格状数据结构的数据源,例如查询数据库得到的一个集合。
DataSource对象与ASP.NET中的SQLDataSource类似,可用来作为Atlas客户端控件ListView(请
ItemView控件显示集合中的单个数据 )的客户端数据源。您可以使用DataSource对象从服务器端
取得数据并把用户的修改提交回服务器保存。
只能读取数据,不能将用户的改变提交回服务器。
下面我来依次介绍这两个数据源:
Sys.Data.DataSource
DataSource 数据源有如下属性:
1. data:从服务器端取回并保存在客户端的数据。
2. autoLoad:布尔值,用来指定当这个数据源被初始化之后是否自动开始从服务器端取得数据。如
动加载带来的在页面被加载后立刻发生的那一次与服务器的通信。
3. initialData:随着页面加载而同时被送往数据源的数据。在好多情况中,当用户第一次访问某个页
面时候就需要使用一些初始的数据,例如某个列表的第一页的记录。这时候我们可以使用 Atlas 的服
避免在页面传输完成后立刻发生第二次请求。
4. isDirtyAndReady:表示该数据源是否完成了从服务器端的加载,且取得到了不为空的数据集合,
且数据没有被修改过。
5. isReady:表示该数据源是否完成了从服务器端的加载。您可以将这个属性绑定到您的数据显示控
件的 enabled 属性上,这样在数据源加载的过程中数据显示控件将被禁用,以避免误用户的操作。
6. rowCount:数据的条目数。
DataSource 数据源有如下方法:
1. load:从服务器取得数据。
候有效。
DataSource 数据源有如下事件:
1. dataAvailable:将在成功取得数据后被引发。
Sys.Data.XMLDataSource
XMLDataSource 数据源有如下属性:
1. autoLoad:布尔值,用来指定当这个数据源被初始化之后是否自动开始从服务器端取得数据。与
DataSource 数据源类似,如果您需要在页面加载时就指定该数据源的内容,应该使用
initialDocument 属性代替。
XMLDataSource 数据源有如下方法:
1. load:从服务器取得数据。
XMLDataSource 数据源有如下事件:
1. dataAvailable:将在成功取得数据后被引发。
B. DataColumn、DataRow 和 DataTable
在这篇文章中我们将要接触Atlas客户端数据组件中的核心组件——DataTable。顾名思义,DataTable用来表示一个表
格状的数据结构。在Atlas客户端数据组件中,DataTable对象是数据源(例如DataSource对象,请参考:Atlas命名
空间Sys.Data下控件介绍——DataSource和XMLDataSource )和数据显示控件(例如ListView控件,请
的一个字段,DataSource对象从服务器取得的数据将被解析并存放在这个DataTable对象中。DataTable对象还可以被
DataView对象修饰,例如过滤并只显示其中一部分的行,按照某一列排序,分页等等,当然这些操作都是在客户端进行
的,有着极高的效率。
员感到非常熟悉并更加容易上手。
和 DataRow 对象开始:
Sys.Data.DataColumn
DataColumn 类非常简单,只有如下几个很容易理解的属性:
1. columnName:本列的名称。
2. dataType:本列中的数据类型。
3. defaultValue:本列中数据的默认值。
5. readOnly:本列中的数据是否为只读属性。
Sys.Data.DataRow
DataRow 类略显复杂,包含如下属性:
1. $isDirty:该行是否经过修改并且尚未提交到服务器保存。
3. $selected:该行是否被选中。
还包含有如下事件:
1. propertyChanged:当上述的三个属性被改变时被引发。
Sys.Data.DataTable
DataTable 对象有如下属性:
DataTable 对象有如下方法:
数。
还有如下事件:
2. propertyChanged:当以上的某个属性被改变后被引发。
C. DataView 和 DataFilter
这篇文章是Atlas命名空间Sys.Data下控件介绍这个系列的第三篇,也是最后的一篇。在我的前两篇文章(Atlas命名空
间Sys.Data下控件介绍——DataSource和XMLDataSource ,Atlas命名空间Sys.Data下控件介绍
——DataColumn,DataRow和DataTable)中,我们讨论了如何用数据源控件从服务器取得数据并保存在客户端,以
及如何用DataTable对象对客户端的数据进行操作。目前为止,我们可以直接将数据显示给用户了,但是,很多时候我
们需要在这之前对数据进行一定的修饰,例如,当DataTable中的数据量很大时,我们需要实现分页的功能,或是用户
希望根据某一列进行排序,或者用户只对数据中的某一些感兴趣(例如,name等于Dflying的条目)。这也是Atlas中引
入DataView以及DataFilter对象的目的。在这篇文章中,我将介绍如何使用DataView和DataFilter对象修饰取得的数
据,以提供给UI控件显示。
的属性:
这个属性,以备操作。
2. filteredData:经过修饰的数据,例如经过分页的数据或者经过过滤的数据。
4. hasNextPage:当前页后是否有下一页。
5. hasPreviousPage:当前页前是否有前一页。
6. length:当前页中实际的条目数量。
8. pageIndex:当前页的索引。
9. pageSize:每一页的长度(每一页中最多有多少个条目)。如果您需要分页功能,则应该设置这个
属性。
个属性。
DataView 对象还有下面一个方法:
请注意,您可能需要两个位于Sys.Data.UI命名空间的控件:DataNavigator和SortBehavior,来帮助您实现分页和排
实现客户端分页导航 。
供了一个抽象方法,filter。所有的派生类都要采用自己的逻辑来实现这个方法,用来提供相应的过滤规则。
PropertyFilter 有如下两个属性:
2. value:期待的这个属性的值。只有该条目的这个属性的值等于这里指定的值的时候,该条目才能被
这个 Filter 过滤出来。
PropertyFilter 的示例程序将很快完成。
1. DataSource和XMLDataSource(Atlas命名空间Sys.Data下控件介绍——DataSource和
XMLDataSource),用来从服务器端取得数据并将数据保存在客户端,同样在用户修改后可以将数
据提交回服务器保存。
2. DataTable,包括DataRow和DataColumn(Atlas命名空间Sys.Data下控件介绍
——DataColumn,DataRow和DataTable),是客户端数据的实际储存对象。通过DataTable的方
法,您可以在客户端对数据进行操作(添加,删除,修改等)
。
3. DataView 和 DataFilter(本文),用来在显示给用户前对数据进行修饰(分页,排序,过滤等),有
查,所以在书写代码的时候应该格外小心。
ListView 中有如下模版:
1. layoutTemplate:这个模版用来渲染包含列表项目的容器(例如使用<table>标记)
,列表的头
2. itemTemplate:这个模版用来渲染列表中的一个项目(例如使用<tr>标记)。这个模版必须被置
于 layoutTemplate 中。
3. separatorTemplate:这个模版用来渲染列表中的项目之间的分隔元素(例如使用<hr>标记)。
这个模版必须被置于 layoutTemplate 中。
的 DataSource 对象中没有项目,或是正在从服务器中取得的过程中。
ListView 中还有一些属性:
ListView还有一些继承于Sys.UI.Data.DataControl基类的方法/属性,因为在下面的代码中我们不需要使用,这里
们通过一个实例来说明如何使用ListView控件:
的内容。
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class MyService : Microsoft.Web.Services.DataService {
[DataObjectMethod(DataObjectMethodType.Select)]
public DataTable GetListData()
{
System.Threading.Thread.Sleep(2000);
<div id="myList"></div>
<!-- Layout Elements -->
<div style="display: none;">
</div>
空行)。
这里我添加了一个Atlas客户端DataSource对象以从Web Service中取得数据。这里我们暂且不多
谈DataSource(可能在后续文章中有所介绍)。让我们来看一下ListView相关的定义:在ListView
的定义中,我们指定了itemTemplateParentElementId属性。然后在ListView的内部定义了一个
binding段,用来把DataSource中取得的数据与这个ListView绑定起来。我们还定义了四个模版段,
每个模版段都用layoutElement与上面定义过的四种模版关联。注意到在layoutTemplate模版中的第
于Atlas Transformer,请参考我的这篇文章:
http://dflying.cnblogs.com/archive/2006/04/05/367908.html)。
大功告成,运行一下吧。
装载中:
装载完成:
示例代码可以在此下载:http://www.cnblogs.com/Files/dflying/AtlasListViewDemo.zip
有时候我们需要显示给用户列表中某一项的详细信息,例如,在购物程序中的产品详细情况。ASP.NET Atlas
1. canMoveNext:当前记录后是否有下一条记录。
2. canMovePrevious:当前记录前是否有前一条记录。
3. data:控件包含的数据集合。
4. dataIndex:当前记录的 index。
6. length:记录的条目数。
同时还包括下列方法:
1. addItem:添加一条记录到当前的数据集合中。
请注意所有的以上操作都仅在客户端,也就是说只修改了客户端的数据。所以如果您希望将改变提交到服务
ItemView 通过继承获得了以上的属性和方法,并且还对基类有如下扩展:
1. itemTemplate:指定项目模版。Atlas 可以根据这个模版渲染您的内容。
中时,Atlas 会显示这个模版。
例程序,并适当做了一些简化。
定义 item entry 类:
[DataObjectField(true, true)]
public int Id
[DataObjectField(false)]
[DefaultValue("New row")]
[DataObjectField(false)]
[DefaultValue("")]
public Entry()
_id = -1;
_id = id;
_name = name;
_description = description;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
get
if (_data == null)
lock (_dataLock)
if (_data == null)
System.Threading.Thread.Sleep(2000);
tes."));
_nextId = 3;
return _data;
[DataObjectMethod(DataObjectMethodType.Delete)]
if (row.Id == id)
lock (_dataLock)
_data.Remove(row);
break;
[DataObjectMethod(DataObjectMethodType.Select)]
return MyDataService.Data.ToArray();
[DataObjectMethod(DataObjectMethodType.Insert)]
Entry newRow;
lock (_dataLock)
_data.Add(newRow);
return newRow;
[DataObjectMethod(DataObjectMethodType.Update)]
if (row.Id == updateRow.Id)
row.Name = updateRow.Name;
row.Description = updateRow.Description;
break;
的 JavaScript 文件。
3. 导航部分,用于在在客户端集合中导航,以显示集合中不同的记录。
4. 命令部分,用于修改,添加,删除记录(在客户端),并且提交到服务器。
页面上显示出来。
Getting Data
</div>
</div>
<itemView id="detailsView">
<bindings>
<binding dataContext="dataSource" dataPath="data" property="data"/>
<binding dataContext="dataSource" dataPath="isReady" property="enabled"/>
</bindings>
<itemTemplate>
<template layoutElement="detailsTemplate">
<textBox id="nameField">
<bindings>
<binding dataPath="Name" property="text" direction="InOut"/>
</bindings>
</textBox>
<textBox id="descriptionField">
<bindings>
<binding dataPath="Description" property="text" direction="InOut"/>
</bindings>
</textBox>
</template>
</itemTemplate>
<emptyTemplate>
<template layoutElement="emptyTemplate" />
</emptyTemplate>
</itemView>
下面是导航部分的脚本。我们提供了一个label用来显示当前的记录编号(记录index加上 1,使用了Atlas
相应的ItemView的方法)。
<button id="previousButton">
<bindings>
<binding dataContext="detailsView" dataPath="canMovePrevious" property="enabled"
/>
</bindings>
<click>
<invokeMethod target="detailsView" method="movePrevious" />
</click>
</button>
<label id="rowIndexLabel">
<bindings>
<binding dataContext="detailsView" dataPath="dataIndex" property="text" transfor
m="Add" />
</bindings>
</label>
<button id="nextButton">
<bindings>
<binding dataContext="detailsView" dataPath="canMoveNext" property="enabled"/>
</bindings>
<click>
<invokeMethod target="detailsView" method="moveNext" />
</click>
</button>
下面是命令部分的脚本。这里我们能够在客户端添加/删除记录,并将改变提交给服务器或者放弃提交。
<button id="addButton">
<bindings>
<binding dataContext="dataSource" dataPath="isReady" property="enabled"/>
</bindings>
<click>
<invokeMethod target="detailsView" method="addItem" />
</click>
</button>
<button id="delButton">
<bindings>
<binding dataContext="dataSource" dataPath="isReady" property="enabled"/>
</bindings>
<click>
<invokeMethod target="detailsView" method="deleteCurrentItem" />
</click>
</button>
<button id="saveButton">
<bindings>
<binding dataContext="dataSource" dataPath="isDirtyAndReady" property="enabled"/
>
</bindings>
<click>
<invokeMethod target="dataSource" method="save" />
</click>
</button>
<button id="refreshButton">
<bindings>
<binding dataContext="dataSource" dataPath="isReady" property="enabled"/>
</bindings>
<click>
<invokeMethod target="dataSource" method="load" />
</click>
</button>
大功告成,可以在浏览器中测试了。
装载中:
装载完成:
记录间导航:
修改并保存:
上述示例代码可以在此处下载:http://www.cnblogs.com/Files/dflying/AtlasItemViewDemo.zip
把所有的记录统统放在一个页面上绝对不是一个好主意,特别是当您有成百上千条记录时。您的用户需
了类似的功能,这将大大提高我们的开发效率。
DataNavigator控件将与DataView(请参考:Atlas命名空间Sys.Data下控件介绍——DataView和
DataFilter )控件一起工作。我们知道DataView控件没有提供页面导航相关方法,所以我们只能直接
设置它的pageIndex属性来实现导航。虽然没有什么难度,但很多情况下这并不是一个好办法,因为像
我这样好多粗心的开发者往往会忘记检查pageIndex的边界值,造成不必要的麻烦。这也是Atlas要提供
DataNavigator控件的原因之一,DataNavigator控件将作为一个DataView控件的代理(proxy),
提供易用的页面导航接口。
DataNavigator 对象只有一个属性:
到其上。您应该总是指定这个属性。
1. page:将当前页面索引转为命令参数(command argument)中指定的值。通过这个命令我们可
以快速的改变页面的索引。
2. nextpage:切换到下一页(如果存在下一页)。
3. previouspage:切换到上一页(如果存在上一页)
。
4. firstpage:切换到第一页。
5. lastpage:切换到最后一页。
首先我们需要暴露一个 Web Service,以便 Atlas 页面使用。该 Web Service 将返回 100 条记录。下面就
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Web;
using System.Web.Caching;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.Web.Services;
//
// For simplicity this example demonstraes storing and manipulating
// the data objects in memory. A database can also be used.
//
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class MyDataService : DataService
{
static List<Entry> _data;
static object _dataLock = new object();
[DataObjectMethod(DataObjectMethodType.Select)]
public Entry[] SelectRows()
{
return MyDataService.Data.ToArray();
}
}
[DataObjectField(true, true)]
public int Id
{
get { return _id; }
set { _id = value; }
}
[DataObjectField(false)]
[DefaultValue("New row")]
public string Name
{
get { return _name; }
set { _name = value; }
}
[DataObjectField(false)]
[DefaultValue("")]
public string Email
{
get { return _email; }
set { _email = value; }
}
public Entry()
{
_id = -1;
}
ListView 放置于此。
面导航功能。
下面是以上四部分内容的代码,关于ListView控件的模版,请参考我的这篇文章:使用ASP.NET Atlas
ListView控件显示列表数据
</table>
<!-- Empty Template -->
<div id="myList_emptyTemplate">
No Data
</div>
</div>
第二部分:一个DataView控件(请参考:Atlas命名空间Sys.Data下控件介绍——DataView和
显示分页好的数据。
</bindings>
</label>
<label id="lblEmail">
<bindings>
<binding dataPath="Email" property="text"/>
</bindings>
</label>
</template>
</itemTemplate>
<emptyTemplate>
<template layoutElement="myList_emptyTemplate"/>
</emptyTemplate>
</listView>
第五部分:两个 Label,分别显示页面总数以及当前页的序号。
<label id="lblPageNumber">
<bindings>
<binding dataContext="view" property="text" dataPath="pageIndex" transform="Add"/>
</bindings>
</label>
<label id="lblPageCount">
<bindings>
<binding dataContext="view" property="text" dataPath="pageCount"/>
</bindings>
</label>
OK,在浏览器中测试一下:
这个DEMO的源文件可以在此下载:
http://www.cnblogs.com/Files/dflying/DataNavigatorDemo.zip
为您的列表添加排序功能将是非常酷的。一些ASP.NET服务器控件,例如DataGrid,GridView
等已经拥有了内建的排序功能。Atlas同样提供了Sys.UI.Data.SortBehavior Behavior(有关Atlas
Behavior,请参考:在ASP.NET Atlas中创建自定义的Behavior),让您在客户端即可实现排序功能。
SortBehavior将与DataView控件(请参考:Atlas命名空间Sys.Data下控件介绍——DataView和
DataFilter)配合工作,它将通过设定DataView控件的sortDirection属性来实现排序功能。
SortBehavior对象有如下属性:
您应该总是指定这个属性。
您应该总是指定这个属性。
介绍到此为止,我们来看如下的示例程序。
简介。下面为代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Web;
using System.Web.Caching;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.Web.Services;
//
// For simplicity this example demonstraes storing and manipulating
// the data objects in memory. A database can also be used.
//
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class SampleDataService : DataService
{
static List<Entry> _data;
static int _nextId;
static object _dataLock = new object();
[DataObjectMethod(DataObjectMethodType.Delete)]
public void DeleteRow(int id)
{
foreach (Entry row in _data)
{
if (row.Id == id)
{
lock (_dataLock)
{
_data.Remove(row);
}
break;
}
}
}
[DataObjectMethod(DataObjectMethodType.Select)]
public Entry[] SelectRows()
{
return SampleDataService.Data.ToArray();
}
[DataObjectMethod(DataObjectMethodType.Insert)]
public Entry InsertRow(string name, string description)
{
Entry newRow;
lock (_dataLock)
{
newRow = new Entry(_nextId++, name, description);
_data.Add(newRow);
}
return newRow;
}
[DataObjectMethod(DataObjectMethodType.Update)]
public void UpdateRow(Entry updateRow)
{
foreach (Entry row in _data)
{
if (row.Id == updateRow.Id)
{
row.Name = updateRow.Name;
row.Title = updateRow.Title;
break;
}
}
}
}
[DataObjectField(true, true)]
public int Id
{
get { return _id; }
set { _id = value; }
}
[DataObjectField(false)]
[DefaultValue("New row")]
public string Name
{
get { return _name; }
set { _name = value; }
}
[DataObjectField(false)]
[DefaultValue("")]
public string Title
{
get { return _title; }
set { _title = value; }
}
public Entry()
{
_id = -1;
}
放置于此。
下面是以上三部分内容的代码,关于ListView控件的模版,请参考我的这篇文章:使用ASP.NET
Atlas ListView控件显示列表数据
第二部分:一个DataView控件(请参考:Atlas命名空间Sys.Data下控件介绍——DataView和
DataFilter ),用来将第一部分中取得的数据排序。
<dataView id="view">
<bindings>
<binding dataContext="dataSource" dataPath="data" property="data"/>
</bindings>
</dataView>
显示排序后的数据。
<control id="sortId">
<behaviors>
<sortBehavior dataView="view" sortColumn="Id"/>
</behaviors>
</control>
<control id="sortName">
<behaviors>
<sortBehavior dataView="view" sortColumn="Name"/>
</behaviors>
</control>
<control id="sortTitle">
<behaviors>
<sortBehavior dataView="view" sortColumn="Title"/>
</behaviors>
</control>
大功告成,打开浏览器测试一下吧:
初始的顺序:
这个DEMO的源文件可以在此下载:
http://www.cnblogs.com/Files/dflying/SortBehaviorDemo.zip
XSLT是一种修饰XML显示的样式语言,它可以将XML文件中的数据添加修饰(样式,布局等)后输出,
我们熟悉的CSDN论坛中的帖子就采用了XSLT的修饰。更多的XSLT信息,请访问W3C的XSLT标准:
http://www.w3.org/TR/xslt。
Atlas中提供了XMLDataSource控件(请参考:Atlas命名空间Sys.Data下控件介绍——DataSource和
XMLDataSource)和XSLTView控件,您可以使用他们从服务器取得XML以及XSLT数据,将XSLT样
式应用到XML数据中并显示给用户。这是个很有用的功能,例如,您可以在编写在线RSS Feed阅读程序
中使用它。
XSLTView 控件有如下几个属性:
3. parameters:XSLT文件中定义的parameter,将用于渲染的过程。本属性为只读。关于XSLT中
的parameter,请参考:http://www.w3schools.com/xsl/el_param.asp
还有如下方法:
动调用。当然您可以在需要时手动调用。
第一步是取得一些测试的数据,包含一个XML文件和一个XSLT文件。Google了一下,很容易在
http://www.w3schools.com/xsl/xsl_client.asp中找到了一个简单的。在这个示例程序中,为
简单起见,我就使用了原始的XML和XSLT文件。当然在实际的开发中,这两段数据都可以通过Web
Service或者别的CGI动态生成。
的 JavaScript 文件。
第三部分:一个XSLTView控件,将XML数据用XSLT中的定义渲染后输出。注意到这里我们使用
binding(关于binding,请参考:Atlas揭秘 —— 绑定(Binding))来设置这个XSLTView的document
和transform属性。
<xsltView id="dataContent">
<bindings>
<binding property="document" dataContext="dataSource" dataPath="document" />
<binding property="transform" dataContext="xsltSource" dataPath="document" />
</bindings>
</xsltView>
浏览器中运行:
上述示例代码可以在此处下载:
http://www.cnblogs.com/Files/dflying/AtlasXSLTViewDemo.zip
A. 显示真实进度的 ProgressBar(进度条)控件
当后台在进行某些长时间的操作时,如果能在页面上提供一个显示真实进度的进度条,而
不是让用户不知情的等待或是从前的那些简单的估计,将是一个非常难得的出彩之处。现
在使用ASP.NET Atlas完全有可能做到这些。这篇文章将讨论如何完成这一功能并介绍一些有关Atlas
客户端控件开发的基本概念。您同时可以 在这里下载示例程序以及源文件。
用返回的当前进度数据更新进度条的显示。在这个示例中,将有四个部分的代码组成:
中最重要的一个组件,在将来可被重用于其他页面或程序的开发
下面我们一步一步地来实现以上四个步骤:
1 [WebMethod]
2 public void TimeConsumingTask()
3 {
4 ConnectToDataBase();
5 GetSomeValueFromDataBase();
6 CopySomeFilesFromDisk();
7 GetARemoteFile();
8 }
这样我们就可以插入一些辅助方法来确定当前进度完成情况,setProgress(int)用来设定当前的进度完成百
分比:
1 [WebMethod]
2 public void TimeConsumingTask()
3 {
4 setProgress(0);
5 ConnectToDataBase();
6 setProgress(10);
7 GetSomeValueFromDataBase();
8 setProgress(40);
9 CopySomeFilesFromDisk();
10 setProgress(50);
11 GetARemoteFile();
12 setProgress(100);
13 }
1 [WebMethod]
2 public int StartTimeConsumingTask()
3 {
4 string processKey = this.Context.Request.UserHostAddress;
5 string threadLockKey = "thread" + this.Context.Request.UserHostAddress;
6 object threadLock = this.Context.Cache[threadLockKey];
7 if (threadLock == null)
8 {
9 threadLock = new object();
10 this.Context.Cache[threadLockKey] = threadLock;
11 }
12
13 // Only allow 1 running task per user.
14 if (!Monitor.TryEnter(threadLock, 0))
15 return -1;
16
17 DateTime startTime = DateTime.Now;
18
19 // Simulate a time-consuming task.
20 for (int i = 1; i <= 100; i++)
21 {
22 // Update the progress for this task.
23 this.Context.Cache[processKey] = i;
24 Thread.Sleep(70);
25 }
26
27 Monitor.Exit(threadLock);
28
29 return (DateTime.Now - startTime).Seconds;
30 }
31
1 [WebMethod]
2 public int GetProgress()
3 {
4 string processKey = this.Context.Request.UserHostAddress;
5 object progress = this.Context.Cache[processKey];
6 if (progress != null)
7 {
8 return (int)progress;
9 }
10
11 return 0;
12 }
客户端进度条(ProgressBar)控件
第一步:从 Sys.UI.Control 继承
1 Sys.UI.ProgressBar = function(associatedElement) {
2 Sys.UI.ProgressBar.initializeBase(this, [associatedElement]);
3
4 }
5 Type.registerSealedClass('Sys.UI.ProgressBar', Sys.UI.Control);
6 Sys.TypeDescriptor.addType('script','progressBar', Sys.UI.ProgressBar);
7
第二步:添加私有成员并书写相应的 Setter/Getter
下面需要添加一些属性用来设定我们的控件。在这个例子中,我们需要三个属性:
1. Interval. 每次重新查询进度并更新进度条的间隔时间。单位:毫秒
参数。还需要在控件的描述方法(descriptor)中添加对于这些属性的说明。有关描述方法(descriptor)
1 var _serviceMethod;
2
3 this.get_serviceMethod = function() {
4 return _serviceMethod;
5 }
6
7 this.set_serviceMethod = function(value) {
8 _serviceMethod = value;
9 }
Sys.Timer 用于每过一段时间调用一个方法(发出一个事件),我们可以定义一个委托来指向这个方法,并
应该记得做一些必要的清理。
还有,注意当前一个请求并没有返回时,不应该发送第二个请求。
第四步:添加控制方法
须的。Atlas 会利用它来描述这个类型的信息。
1 this.getDescriptor = function() {
2 var td = Sys.UI.ProgressBar.callBaseMethod(this, 'getDescriptor');
3 td.addProperty('interval', Number);
4 td.addProperty('progress', Number);
5 td.addProperty('serviceURL', String);
6 td.addProperty('serviceMethod', String);
7 td.addMethod('start');
8 td.addMethod('stop');
9 return td;
10 }
11
12 this.start = function() {
13 _timer.set_enabled(true);
14 }
15
16 this.stop = function() {
17 _timer.set_enabled(false);
18 }
OK,目前为止客户端的控件就完成了。我们把它存为 ProgressBar.js。
接下来是页面的布局与样式:
1 <style type="text/css">
2 * {
3 font-family: tahoma;
4 }
5 .progressBarContainer {
6 border: 1px solid #000;
7 width: 500px;
8 height: 15px;
9 }
10 .progressBar {
11 background-color: green;
12 height: 15px;
13 width: 0px;
14 font-weight: bold;
15 }
16 </style>
17
18 <div>Task Progress</div>
19 <div class="progressBarContainer">
20 <div id="pb" class="progressBar"></div>
21 </div>
22
<input type="button" id="start" onclick="startTask();return false;" value="Start the Time
Consuming Task!" />
23 <div id="output" ></div>
截图和下载
现在所有的事情都搞定了,可以运行了!
页面初始化:
运行中:
运行完成:
示例程序以及源文件可以 在这里下载。
B. 创建自定义的 Action
些常见的,通用的事件处理方法,例如调用某个方法,设定某个对象的某个属性,引发一个 PostBack
等。
1. Sys.InvokeMethodAction:用来调用一个指定的函数。
2. Set.SetPropertyAction:用来设定某个对象的某个属性值。
3. Sys.WebForms.PostBackAction:用来引发一个 PostBack。
将要显示给用户的内容。
属性中的内容。
AlertAction.js。
Sys.AlertAction = function() {
Sys.AlertAction.initializeBase(this);
// step 2
var _message;
this.get_message = function() {
return _message;
}
this.set_message = function(value) {
_message = value;
}
// step 4
this.getDescriptor = function() {
var td = Sys.AlertAction.callBaseMethod(this, 'getDescriptor');
td.addProperty('message', String);
return td;
}
// step 3
this.performAction = function() {
alert(_message);
return null;
}
}
// step 1
Sys.AlertAction.registerSealedClass('Sys.AlertAction', Sys.Action);
Sys.TypeDescriptor.addType('script', 'alertAction', Sys.AlertAction);
文件的引用。
<script type="text/xml-script">
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
<components>
<button id="myButton">
<click>
<alertAction message="Button Clicked!" />
</click>
</button>
</components>
</page>
</script>
浏览器中的运行结果:
上述示例程序可以在此下载:http://www.cnblogs.com/Files/dflying/AtlasActionDemo.zip
C. 创建自定义的 Behavior
1. Click Behavior:提供对鼠标点击的处理。
的处理。
Behavior 还需要服务器端的处理程序。
的程序中,我们可能需要将左右键的功能分开,例如,左键用来选择,右键用来弹出快捷菜单。虽然我们可
发出不同的事件。
5. 在 getDescriptor()方法中加上对您定义的事件的描述。
代码保存为 ExtendedClickBehavior.js。
Sys.UI.ExtendedClickBehavior = function() {
Sys.UI.ExtendedClickBehavior.initializeBase(this);
var _clickHandler;
// step 2
this.click = this.createEvent();
this.leftClick = this.createEvent();
this.rightClick = this.createEvent();
this.dispose = function() {
// step 3
this.control.element.detachEvent('onmousedown', _clickHandler);
Sys.UI.ExtendedClickBehavior.callBaseMethod(this, 'dispose');
}
this.initialize = function() {
Sys.UI.ExtendedClickBehavior.callBaseMethod(this, 'initialize');
// step 3
_clickHandler = Function.createDelegate(this, clickHandler);
this.control.element.attachEvent('onmousedown', _clickHandler);
}
this.getDescriptor = function() {
var td = Sys.UI.ExtendedClickBehavior.callBaseMethod(this, 'getDescriptor');
// step 5
td.addEvent('click', true);
td.addEvent('leftClick', true);
td.addEvent('rightClick', true);
return td;
}
// step 4
function clickHandler() {
this.click.invoke(this, Sys.EventArgs.Empty);
if (window.event.button == 1)
{
this.leftClick.invoke(this, Sys.EventArgs.Empty);
}
else if (window.event.button == 2)
{
this.rightClick.invoke(this, Sys.EventArgs.Empty);
}
}
}
// step 1
Sys.UI.ExtendedClickBehavior.registerSealedClass('Sys.UI.ExtendedClickBehavior', Sys.UI.Be
havior);
ExtendedClickBehavior.js 文件的引用。
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
<components>
<label id="myButton">
<behaviors>
<extendedClickBehavior>
<click>
<setProperty target="myLabel" property="text" value="clicked" />
</click>
<leftClick>
<setProperty target="myLabel" property="text" value="left clicke
d" />
</leftClick>
<rightClick>
<setProperty target="myLabel" property="text" value="right click
ed" />
</rightClick>
</extendedClickBehavior>
</behaviors>
</label>
<label id="myLabel" />
</components>
</page>
浏览器中的运行结果:
没有点击:
左键点击:
右键点击:
上述示例程序可以在此下载:
http://www.cnblogs.com/Files/dflying/ExtendedClickBehaviorDemo.zip
D. 创建自定义的 Transformer
ASP.NET Atlas中的绑定(binding)是一种将两个对象连接起来的强大方法。(您可以参考
http://dflying.cnblogs.com/archive/2006/04/04/366900.html得到更多关于绑定的信息。)
Atlas绑定会自动将源对象上变化了的属性应用到目标对象的指定属性上。但有时候您会希望在应用到目
标对象之前对这个属性进行一些修改。比如,当显示一个有索引的列表时,您可能希望这个索引从 1 开
的Transformer是一种类似管道的东西,它将插入到由源对象的属性向目标对象的属性赋值的过程中,
以期对将要赋值的属性进行必要的过滤/装饰/转换(在这里是将源属性加 1),然后再赋值给目标属性。
悉如何书写自定义的 transformer。
Completed/InProgress。如果我们选择使用绑定来将一个布尔值显示给用户,那么这个 transformer 将会
是十分有用的,它带给用户更加友好的用户体验。
1. 取得从源绑定对象中传入的将被转换的值。这里我们首先调用 get_value()取得传入的值,并将其转
换为布尔型。
将被转换为第一部分,false 将被转换为第二部分。如果传入的参数为空,则用默认的字符串
true/false 代替。
3. 进行转换。在这个步骤应当通过您自己的逻辑把传入的值转换成将要传出的值(一般会用到上一步骤
4. 将转换后的值输出,调用方法 set_value()来实现。
CustomBooleanTransformer.js 文件的引用。
转化为 No。
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
<references>
</references>
<components>
<checkBox id="myCheckbox" />
<textBox id="myTextBox">
<bindings>
<binding dataContext="myCheckbox" dataPath="checked"
property="text" transform="CustomBoolean" transformerArgument="Yes,No" /
>
</bindings>
</textBox>
</components>
</page>
浏览器中的实际结果:
E. 创建自定义的 Validator
1. requiredFieldValidator:检查是否有数据输入。
2. typeValidator:检查输入的数据是否为特定的类型。
3. rangeValidator:检查输入的值是否在一个范围之内。
4. customValidator:用自定义的验证函数验证输入。
5. regexValidator:用指定的正则表达式验证输入。
误并可以自定义错误提示。
的 IPv4 地址。
1. 从 Sys.UI.Validator 基类中继承。
2. 实现 validate()方法来验证输入,并返回一个布尔值代表是否验证成功。
Sys.UI.IPAddressValidator = function() {
Sys.UI.IPAddressValidator.initializeBase(this);
this.validate = function(value) {
if (!value) {
return false;
if (String.isInstanceOfType(value)) {
if (value.length == 0) {
return false;
if (ipArray == null)
return false;
return false;
return true;
Sys.UI.IPAddressValidator.registerSealedClass('Sys.UI.IPAddressValidator', Sys.UI.Validator);
引用。
<Scripts>
</Scripts>
</atlas:ScriptManager>
<div class="description">
</div>
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
<components>
<textBox id="ipBox">
<validators>
<ipAddressValidator errorMessage="This IP Address is invalid!" />
</validators>
</textBox>
<validationErrorLabel id="ipValidator" associatedControl="ipBox" />
</components>
</page>
在浏览器中运行结果:
F. 随输入内容自动调整行数的 Textarea
一行。但如果您输入了好多地址,超过了一行的长度,它会自动地变成两行,如果不够,还会变成三行,四
行等。这种文本框既节约了初始空间,又让用户输入大量数据时不感到局促。为了让您对其有更直观的了解
或是有些朋友没有用到过上述产品,请看下面的截图:
初始只有两行: 当您继续输入时,行数会自动增加:
滚动条依然会出现: 行数也会随之自动减少:
的基础功能。
textarea 的行数。这是本控件实现中比较有“技术含量”的部分,您可以参考源文件以得到具体实现。
AutoResizeTextArea 有如下两个属性:
使用 AutoResizeTextArea 控件要注意以下两点:
检查,如果您需要,可以很容易的添加上去。
该控件的源代码以及开头部分示例程序可以在此下载:
http://www.cnblogs.com/Files/dflying/AutoResizeTextArea.zip
AtlasUIDragDrop.js 文件中,感兴趣的朋友可以学习一下它的实现,当然,这部分内容不在本文的范围之
内(今后应该会有所介绍,希望我不会懒)。
现 IDropTarget 接口来定义自己的投放目标对象。当然您可以同时实现上述两个接口(比如,您
希望用户可以在页面上自由拖动并安排购物车的位置)
。
接口提供的方法来启动拖放操作以及注册投放目标对象。通常情况下,您不需要考虑太多关于
DragDropManager 的事情。
DragDropManager 的 startDragDrop()方法以开始拖动的操作(通常这个步骤应该放在处理
型拖放对象。
象。
Atlas提供了一些内建的实现了IDragSource以及IDropTarget接口的Behavior(关于Behavior,请
参考:在ASP.NET Atlas中创建自定义的Behavior)供我们使用。显然,下列客户端Behavior都实
现了IDragSource或IDropTarget接口中的至少一个。
1. DragDropList Behavior可以为一组控件增加拖放功能。典型应用就是使ListView控件(关于
3. DataSourceDropTarget Behavior用来把数据通过拖放的方式加入到DataSource控件(关于
DataSource,请参考:Atlas命名空间Sys.Data下控件介绍——DataSource和XMLDataSource)
中。
在本篇中我将使用Atlas的DragDropList Behavior配合Atlas的ListView控件(关于ListView,请
参考:使用ASP.NET Atlas ListView控件显示列表数据)来实现一个用户可通过拖拽重新排列内容
下载到这个DEMO的源文件。
Atlas 默认加载的。
然后,让我们在页面上添加一个静态的布局,这将是用户加载页面之后看到的初始布局,然后再考虑添加动
态的 Atlas 标记使其能够自由拖动。这里我将创建左右两个区域,区域中的内容既可以在区域之间拖动以改
为 ASP.NET 服务器端控件)。
在上面的代码中,我加入了两个区域和三个 panel,声明了页面的初始样子。下面让我们加入两
个模版:一个用来表示当拖动元素经过可投放区域时,可投放区域高亮的样式(dropCueTemplate)。
一个用来表示当某个可投放区域为空的时候的样式(emptyTemplate)。
下面来定义可拖动的元素:
现在我们可以测试一下了:
初始:
将 Calendar 拖到右面的列表中,左边只剩下了一个可拖动元素:
把左边的可拖动元素也拖到右面,您可以看到 emptyTemplate:
该示例程序可在此下载:http://www.cnblogs.com/Files/dflying/AtlasDragDropDemo.zip
体验,同时也节约了页面空间。该控件是我匆促之间(一个小时)完成,好多代码组织混乱,可能
也会有不少 Bug,仅供各位参考并请不吝指正。
InPlaceEditingInput 控件有如下五个属性,当然,您可以很容易的扩充:
个属性。
2. toolTipTextColor:该输入控件的初始文字的颜色,默认值为#aaa。您可以看到上面 DEMO 中
使用 InPlaceEditingInput 控件要注意以下几点:
该控件的主要开发思路为:
式。
该控件的源代码以及开头部分示例程序可以在此下载:
http://www.cnblogs.com/Files/dflying/InPlaceEditingDemo.zip
J. 结合 Membership 进行身份验证
Sys.Services.AuthenticationService 对象来进新身份验证。
Sys.Services.AuthenticationService 对象有如下几个方法:
1. validateUser():该方法接受用户名,密码两个参数,并将返回一个布尔值代表用户验证(注意,
2. login():这个方法与 validateUser()方法类似,但在其基础上该方法会设置代表登录成功的
Cookie,当然需要在提供的用户名/密码正确的情况下。通过调用这个方法,您可以实现 AJAX 方式
的用户登录。
3. logout():注销当前用户。
<configSections>
SectionGroup">
equirePermission="false"/>
n" requirePermission="false"/>
ationServiceSection" requirePermission="false"/>
ion" requirePermission="false"/>
</sectionGroup>
</configSections>
还有:
<microsoft.web>
<webServices enableBrowserAccess="true"/>
<!--
</microsoft.web>
Tool 来设置并添加用户。
现在我们创建一个简单的登录页面,与所有的登录页面类似,两个 input(用户名/密码)一个按钮(登录)。
下面是用户登录时的处理,注意到我们只是简单的调用了 Sys.Services.AuthenticationService.login()
function OnSubmitLogin() {
nComplete);
return false;
function OnLoginComplete(result) {
password.value = '';
if (result) {
username.value = '';
buttonLoginLogout.onclick = OnSubmitLogout;
else {
下面是用户注销时的处理,通过调用 Sys.Services.AuthenticationService.logout()方法来实现:
function OnSubmitLogout() {
//This call will cause the server to clear the forms authentication cookie.
Sys.Services.AuthenticationService.logout(OnLogoutComplete);
return false;
function OnLogoutComplete(result) {
buttonLoginLogout.onclick = OnSubmitLogin;
以上实例程序可以在此下载:http://www.cnblogs.com/Files/dflying/AuthenticationTest.zip
试。
对于 Atlas调用Page Method来说,传输的数据将会很多,将把表单中所有的域,包括ViewState,一
起传送到服务器。在服务器端,它的工作方式也和普通的PostBack很相似:在这个Page Method被调
用前,所有的服务器控件将得到它自身的状态。这也正是为什么Page Method中可以访问页面中控件状
态的原因。
[WebMethod]
public DateTime GetCurrentDateTime()
{
return DateTime.Now;
}
让我们分别以 Web Service 和 Page Method 运行这一段 Web Method,并用 Fiddler 观察实际运行时的
HTTP 通信内容:
Web Service
Page Method
可以看到以 Web Service 方式运行时 Post 回服务器的 Content-Length 为 0,而以 Page Method 运行时
候为 1718。
介绍
候也没有智能感知提示。并且您还需要在运行时跟踪服务器和客户端的网络通信。而且目前还没有一个非常
其中疏漏之处,还请多多指正。
捕获 HTTP 通信内容
看一下客户端与服务器端的通信,看看通信的内容是不是您所期盼的。
这里我推荐的工具是Fiddler(可以在 http://www.fiddlertool.com/fiddler/下载)。Fiddler是一
个HTTP调试的代理,它可以记录您的计算机和Internet之间HTTP通信的全部内容(包括header,
cookie,通信内容等),设置断点,修改传入/传出的数据等。Fiddler比NetMon或Achilles等同类软
件简单得多,并且提供了一个简单但强大的基于JScript.NET的事件的脚本子系统。Fiddler支持
Internet Explorer以及其它浏览器。
如果您的 Atlas 程序运行在 debug 模式下,那么 Atlas 会自动为您生成一个 Debug Helper Class。 这
果 displayCaller 为 true,该方法将显示出调用者的信息。
2. debug.clearTrace()
清除 trace 的输出。
recursive 为 true,将递归显示该对象内部的所有被包含的对象的信息。indentationPadding
值用来指定输出的每一行的起始文本。
4. debug.fail(message)
5. debug.trace(text)
演示如何使用 debug.dump()请见参考文档
Script Debugging (Other)两项,并选中 Display a notification about every script error 一项。
您需要 attach 调试器到 Internet Explorer 进程上以开始 debug。在 Visual Studio 中使用 F5 来启
Explorer 进程上:在 Internet Explorer 的 View 菜单下,展开 Script Debugger 菜单项,选择 Open。
脚本调试器使用技巧以及现存 Bug
调试 Atlas 应用程序时,应该注意以下问题:
就会解决。(注意这个 WebResource.axd?...是一个很大的文件,需要等待一段时间才能打开。)
行,这样即可在第二行设置相应的断点。
此时您应该选中(高亮)从对象到属性的所有语句,然后再将鼠标移到被选中的内容上,即可得到正
确的值。请见下图:
参考资源
1. http://atlas.asp.net/docs/Overview/debug.aspx
Latest version:
http://www.w3.org/TR/XMLHttpRequest
Editors:
Anne van Kesteren (Opera Software ASA) <annevk@opera.com>
Dean Jackson (W3C) <dino@w3.org>
Copyright ©2006 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability,
trademark and document use rules apply.
Abstract
This specification defines the XMLHttpRequest object, an API that provides some HTTP client
functionality.
This section describes the status of this document at the time of its publication. Other documents may
supersede this document. A list of current W3C publications and the latest revision of this technical
report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This is the 05 April 2006 Working Draft of the XMLHttpRequest Object, the first publication of this
specification. This document is produced by the Web API WG, part of the Rich Web Clients Activity in
the W3C Interaction Domain. The authors of this document are the members of the W3C Web API
Working Group.
Web content and browser developers are encouraged to review this draft. Please send comments to
public-webapi@w3.org, the W3C's public email list for issues related to Web APIs. Archives of the list
are available.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy.
This document is informative only. W3C maintains a public list of any patent disclosures made in
connection with the deliverables of the group; that page also includes instructions for disclosing a
patent. An individual who has actual knowledge of a patent which the individual believes contains
Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent
Policy.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft
document and may be updated, replaced or obsoleted by other documents at any time. It is
inappropriate to cite this document as other than work in progress.
Table of Contents
• 1. Introduction
• 2. Conformance
• 3. The XMLHttpRequest object
• A. References
• B. Authors
1. Introduction
The XMLHttpRequest object is an interface exposed by a scripting engine that allows scripts to
perform HTTP client functionality, such as submitting form data or loading data from a remove Web
site.
The XMLHttpRequest object is implemented today, in some form, by many popular Web browsers.
Unfortunately the implementations are not completely interoperable. The goal of this specification is to
document a minimum set of interoperable features based on existing implementations, allowing Web
developers to use these features without platform-specific code. In order to do this, only features that
are already implemented are considered. In the case where there is a feature with no interoperable
implementations, the authors have specified what they believe to be the most correct behavior.
Future versions of this specification (as opposed to future drafts of this version) may add new features,
after careful examination from browser developers and Web content developers.
This specification was originally derived from the WHAT WG's Web Applications 1.0 document. The
authors acknowledge the work of the WHAT WG in documenting existing behavior.
2. Conformance
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT,
RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC
2119 [RFC2119].
The following interface MAY be used to allow scripts to programmatically connect to their originating
server via HTTP.
A more complete description of what can be done with XMLHttpRequest can be found in the IDL
below and its associated details.
Need to define which IDL specification we are going to conform to, if any.
interface XMLHttpRequest {
raises(DOMException);
raises(DOMException);
raises(DOMException);
void abort();
DOMString getAllResponseHeaders();
// raises(DOMException) on
retrieval
// raises(DOMException) on
retrieval
};
Attributes
An attribute that represents a function that MUST be invoked when readyState changes
value. The function MAY be invoked multiple times when readyState is 3 (Receiving). Its initial
value MUST be null.
The state of the object. The attribute MUSt be one of the following values:
0 Uninitialized
The initial value.
1 Open
The open() method has been successfully called.
2 Sent
The UA successfully completed the request, but no data has yet been received.
3 Receiving
Immediately before receiving the message body (if any). All HTTP headers have been
received.
What about HEAD requests?
4 Loaded
The data transfer has been completed.
responseText of type DOMString
If the readyState attribute has a value other than 3 (Receiving) or 4 (Loaded), it MUST be
the empty string. Otherwise, it MUST be the the body of the data received so far, interpreted
using the character encoding specified in the response, or UTF-8 if no character encoding was
specified. Invalid bytes MUST be converted to U+FFFD REPLACEMENT CHARACTER.
If the readyState attribute has a value other than 4 (Loaded), it MUST be null.
Otherwise, if the Content-Type header contains a media type (ignoring any parameters)
that is either text/xml, application/xml, or ends in +xml, it MUST be an object
that implements the Document interface representing the parsed document. If the document
was not an XML document, or if the document could not be parsed (due to an XML
well-formedness error or unsupported character encoding, for instance), it MUST be null.
If the status attribute is not available it MUST raise an exception. It MUST be available
when readyState is 3 (Receiving) or 4 (Loaded). When available, it MUST represent the
HTTP status code (typically 200 for a successful connection).
Exceptions on retrieval
DOMException INVALID_STATE_ERR SHOULD be raised if this attribute is accessed when
readyState has an inappropriate value.
statusText of type DOMString
Exceptions on retrieval
DOMException INVALID_STATE_ERR SHOULD be raised if this attribute is accessed when
readyState has an inappropriate value.
Methods
abort
When invoked, this method MUST cancels any network activity for which the object is
responsible and resets the object.
No Parameters
No Return Value
No Exceptions
getAllResponseHeaders
If the readyState attribute has a value other than 3 (Receiving) or 4 (Loaded), it MUST
return null. Otherwise, it MUST return all the HTTP headers, as a single string, with each
header line separated by a CR (U+000D) LF (U+000A) pair. The status line MUST not be
included.
r.send();
alert(r.getAllResponseHeaders());
Connection: Keep-Alive
Transfer-Encoding: chunked
No Parameters
Return Value
A single string consisting of all HTTP headers. See prose for details.
No Exceptions
getResponseHeader
If the readyState attribute has a value other than 3 (Receiving) or 4 (Loaded), it MUST
return the empty string. Otherwise, it MUST represent the value of the given HTTP header in
the data received so far for the last request sent, as a single string. If more than one header of
the given name was received, then the values MUST be concatenated, separated from each
other by an U+002C COMMA followed by an U+0020 SPACE. If no headers of that name were
received, then it MUST return the empty string. Header names MUST be compared
case-insensitively to the method argument (header).
r.send();
alert(r.getAllResponseHeaders());
Connection: Keep-Alive
Transfer-Encoding: chunked
Parameters
header of type DOMString
@XXX TDB@
Return Value
@XXX TBD@
No Exceptions
open
Calling this method MUST initialise the object by remembering the method, uri, async (defaulting to
true if omitted), user (defaulting to null if omitted), and password (defaulting to null if omitted)
arguments, setting the readyState attribute to 1 (Open), resetting the responseText,
responseXML, status, and statusText attributes to their initial values, and resetting the list
of request headers.
If the URI given to this method contains a user name and a password (the latter potentially being the
empty string), then these MUST be used if the user and password arguments are omitted. If the
arguments are not omitted, they take precedence, even if they are null.
If open() is called when readyState is 4 (Loaded) the entire object MUST be reset.
Parameters
method of type DOMString
A valid HTTP method name. The GET, POST, and HEAD values MUST be supported.
What about PUT and DELETE?
uri of type DOMString
A URI, which MUST be resolved to an absolute URI using the script's context
window.location.href value as base if available.
This does not reflect what implementations do. document.baseURI might come closer. (
ISSUE-29)
async of type boolean, optional
@XXX TBD@
user of type DOMString, optional
@XXX TBD@
password of type DOMString, optional
@XXX TBD@
No Return Value
No Exceptions
send
If the readyState attribute has a value other than 1 (Open), an exception MUST be raised.
Otherwise, the readyState attribute MUST be set to 2 (Sent) and a request to uri using method
method, authenticating using user and password as appropriate is sent. If the async flag is set to false,
then the method MUST not return until the request has completed. Otherwise, it MUST return
immediately. (See: open().)
If the method is POST or PUT, then the data passed to the send() method MUST be used for the
entity body. If data is a string, the data MUST be encoded as UTF-8 for transmission. If the data is a
Document, then the document MUST be serialised using the encoding given by
data.xmlEncoding, if specified, or UTF-8 otherwise [DOM3]. If data is not a Document or a
DOMString the host language MUST use the stringification mechanisms on the argument that was
passed.
Implementations SHOULD support the send() to be called without the data argument to be passed.
If the response is an HTTP redirect (status code 301, 302, 303 or 307), then it MUST be transparently
followed (unless it violates security or infinite loop precautions). Any other error (including a 401)
MUST cause the object to use that error page as the response.
Immediately before processing the message body (if any), the readyState attribute MUST be set to
to 3 (Receiving). When the request has completed loading, the readyState attribute MUST be set to
4 (Loaded).
Parameters
data of varying types (see IDL)
@XXX TDB@
No Return Value
Exceptions
DOMException INVALID_STATE_ERR MUST be raised if this method is called when
readyState has an inappropriate value.
setRequestHeader
If the readyState attribute has a value other than 1 (Open), an exception MUST be raised.
If the header or value arguments contain any U+000A LINE FEED or U+000D CARRIAGE
RETURN characters, or if the header argument contains any U+0020 SPACE or U+003A
COLON charecters, nothing MUST be done. Otherwise, the request header header MUST
be set to value. If the request header header had already been set, then the new value
MUST be concatenated to the existing value using a U+002C COMMA followed by a U+0020
SPACE for separation.
r.open('get', 'demo.cgi');
r.setRequestHeader('X-Test', 'one');
r.setRequestHeader('X-Test', 'two');
r.send(null);
...
...
The list of request headers MUST be reset when the open() method is called.
User agents MUST not set any headers other than the headers set by the author using this method,
with the following exceptions:
• UAs MUST set the Host header appropriately (see open()) and not allow it to be
overridden.
• UAs MUST set the Authorization header according to the values passed to the
open() method (but MUST allow calls to setRequestHeader() to append values to
it).
• UAs MAY set the Accept-Charset and Accept-Encoding headers and MUST
NOT allow them to be overridden.
• UAs MAY set the If-Modified-Since, If-None-Match, If-Range, and
Range headers if the resource is cached and has not expired (as allowed by HTTP),
and MUST NOT allow those headers to be overridden.
• UAs MUST set the Connection and Keep-Alive headers as described by the
HTTP specification, and MUST NOT allow those headers to be overridden.
• UAs SHOULD set the proxy-related headers according to proxy settings of the
environment, and MUST NOT allow those headers to be overridden.
• UAs MAY give the User-Agent header an initial value, but MUST allow authors to
append values to it.
• UAs SHOULD set Cookie and Cookie2 headers appropriately for the given URI and
given the user's current cookies, and MUST allow authors to append values to these
headers.
Parameters
header of type DOMString
@XXX TDB@
value of type DOMString
@XXX TDB@
No Return Value
Exceptions
DOMException UNKNOWN_ERR @XXX TDB@
HTTP requests sent from multiple different XMLHttpRequest objects in succession SHOULD be
pipelined into shared HTTP connections.
A. References
DOM3
Document Object Model (DOM) Level 3 Core Specification, Arnaud Le Hors (IBM), Philippe Le
Hégaret (W3C), Lauren Wood (SoftQuad, Inc.), Gavin Nicol (Inso EPS), Jonathan Robie
(Texcel Research and Software AG), Mike Champion (Arbortext and Software AG), and Steve
Byrne (JavaSoft).
RFC2119
Key words for use in RFCs to Indicate Requirement Levels, S. Bradner.
RFC2616
Hypertext Transfer Protocol -- HTTP/1.1, R. Fielding (UC Irvine), J. Gettys (Compaq/W3C), J.
Mogul (Compaq), H. Frystyk (W3C/MIT), L. Masinter (Xerox), P. Leach (Microsoft), and T.
Berners-Lee (W3C/MIT).
B. Authors
The authors of this document are the members of the W3C Web APIs Working Group.
Thanks to all those who have helped to improve this specification by sending suggestions and
corrections. (Please, keep bugging us with your issues!)