忙了半个月,现在终于闲下来了,有时间写博,感觉真爽!刚刚看到有人想一起研究ASP.NET AJAX CodePlex Preview 3的帖子,正好前段时间小研究了下.Preview3就出了两个JS(MicrosoftAjaxAdoNet.js和MicrosoftAjaxTemplates.js).
     这里先介绍下MicrosoftAjaxAdoNet类库,对于它的介绍在MS提供的文档中都说明了.这里只是解析下代码,并一起讨论下.先放一张这个类库中的类关系图上来


ASP.NET AJAX CodePlex Preview 3的代码解析
下面看下它的基础类:


AdoNetQueryBuilder类: 
主要属性:
     _queryParameters: uri的?之后的参数数组
     _uri: uri的?之前的地址

用处: 
     对URL的分解,根据查询的参数(?之后)创建参数数组(array),同时也可以设置$skip,$top,$orderby,$filter,$expand这些参数,但是这些参数如何使用的,还不清楚!?
     在该类库中还用在AdoNetServiceProxy的invoke服务,用于分解参数operationUri.


AdoNetActionResult类
主要属性:
     _actionContext, _error, _operation, _result
用处:
     AdoNetActionSequence队列执行完动作后,成功/失败的回调函数返回的结果对象.

_AdoNetUtil类
     这是是内部使用的类,主要包括三个方法
     concatUris(serviceUri, resourceUri): 合并两个uri
     extractETag: 获取item对象的etag属性.(item对象是AdoNetServiceProxy中传给每个服务[insert,update...]的内容参数)
     extractUri: 获取item对象内__metadata的uri属性


AdoNetServiceError类
属性:
     _errorObject: 异常对象
     _message: 异常信息
     _statusCode: 状态码
     _timedOut: 请求是否超时
用处:
     AdoNetServiceProxy中服务请求服务器的过程中,请求失败返回的异常对象

核心的类:
AdoNetActionSequence类: 
主要属性:
     _actionQueue: 服务队列
     _dataService: AdoNetServiceProxy对象
     addInsertAction: 将AdoNetServiceProxy的insert服务加入队列, 
     addInvokeAction: 将AdoNetServiceProxy的invoke服务加入队列, 
     addUpdateAction: 将AdoNetServiceProxy的update服务加入队列, 
     addRemoveAction: 将AdoNetServiceProxy的remove服务加入队列,
     clearActions: 清除队列中的所有服务
     execute: 批量执行队列中的每个服务
作用:

     动作的队列,可以利用add...这些方法将insertAction,InvokeAction,UpdateAction,RemoveAction这些动作放到数组里面,然后再通过execute批量执行. 也就是提供个批量管理和执行服务的接口.
下面是addInsertAction的方法中加入队列的CODE,其他的代码类试:
._dataService;

Array.enqueue(
this._actionQueue,
            function(o) {
                
//dataService的insert服务
                dataService.insert(
                    item,
                    resourceSetUri,
Sys.Data.AdoNetActionSequence._genSuccessCallback(o),
Sys.Data.AdoNetActionSequence._genFailureCallback(o),
                    actionContext 
                )
            }
);


AdoNetServiceProxy类: 
主要属性:
     _defaultFailedCallback: 失败的回调函数
     _defaultSucceededCallback: 成功的回调函数
     _defaultUserContext:
     _serviceUri: 服务器的Uri
     _timeout: Ajax请求的超时时间
     _usePostTunneling:

方法:
     createActionSequence: 创建服务队列
     _prepareWebRequest: 构造WebRequest对象
     insert服务:(item, resourceSetUri, succeededCallback, failedCallback, userContext, webRequest)
     invoke服务:(operationUri, httpVerb, parameters, succeededCallback, failedCallback, userContext, webRequest)
     remove服务:(item, succeededCallback, failedCallback, userContext, webRequest)
     update服务:(item, succeededCallback, failedCallback, userContext, webRequest)
     query服务: (query, succeededCallback, failedCallback, userContext, webRequest)


     这是类库中最核心的类,提供了允许和服务器交互的各种服务.同时也是最复杂的类.大家先看下_prepareWebRequest这是每个服务都要首先调用的方法,因为每个服务都要构造自己的WebRequest对象.

function Sys$Data$AdoNetServiceProxy$_prepareWebRequest(item, relativeUri, verb, onSuccess, onFailure, context, operation, webRequest) {
                webRequest = webRequest || new Sys.Net.WebRequest();
        webRequest.set_url(Sys.Data._AdoNetUtil.concatUris(
this._serviceUri, relativeUri || ""));
        webRequest.set_timeout(
this.get_timeout());

        var headers 
= webRequest.get_headers();
        headers[
"Accept"= "application/json";
        headers[
"DataServiceVersion"= "1.0;AspNetAjax";
        headers[
"MaxDataServiceVersion"= "1.0;";

                webRequest.set_httpVerb(verb);
        
if (this._usePostTunneling) {
            var verbUpper 
= verb.toUpperCase();
            
if ((verbUpper == "PUT"|| (verbUpper == "DELETE"|| (verbUpper == "MERGE")) {
                webRequest.set_httpVerb(
"POST");
                headers[
"X-HTTP-Method"= verbUpper;
            }
        }

                
if (item) {
            webRequest.set_body(Sys.Serialization.JavaScriptSerializer.serialize(item));
            headers[
"Content-Type"= "application/json";

            var eTag 
= Sys.Data._AdoNetUtil.extractETag(item);
            
if (eTag) {
                headers[
"If-Match"= eTag;
            }

            var uri 
= Sys.Data._AdoNetUtil.extractUri(item);
            
if (uri) {
                webRequest.set_url(uri);
            }
        }

                onSuccess 
= onSuccess || this._defaultSucceededCallback;
        onFailure 
= onFailure || this._defaultFailedCallback;
        
if ((typeof(context) === "undefined"|| (context === null)) {
            context 
= this._defaultUserContext;
        }

        webRequest.add_completed(Function.createDelegate(
this, function(executor) {
            
this._onResponseComplete(executor, onSuccess, onFailure, context, operation);
        }));
        
return webRequest;
    }

看完了吧,先讲下_prepareWebRequest的参数:
参数item: 1, 等待新增/修改/删除的对象,它将被序列化为JSON,然后被设置到webrequest的body上
             2, 如果item中存在__Metedate,并且它的uri也存在的话,那么将该对象的uri赋予到webrequest上.
参数relativeUri: 请求的相对地址,并和_serviceUri属性一起构成webrequest的uri
参数verb: Web请求的类型(GET/POST)

其他的参数都是和回调函数有关的参数,比较容易的.

     在这个地方,我一直有点不理解的地方,就是webrequest的set_uri,它是设定服务器的Uri,但是在这里这个地址来源与item对象中的__Metedate和relativeUri,而且__Metedate的优先级更高,大家再看下上面每个服务的参数,就insert服务有relativeUri这个参数,其他的例如udpate,remove服务都没有这个参数,它们都是需要来自__Metedate.Uri, MS为什么需要这样?一直没有想明白......
     好了,现在去看MicrosoftAjaxTemplates.js了,呵呵!刚刚看完,就写出来了,所以如果有什么理解不对的地方,大家一起讨论下,呵呵!

相关文章: