您的位置:首页 > 其它

如何在AJAX应用中访问ADO.NET Data Service

2010-02-28 15:38 549 查看
下面这个例子演示了如何使用ASP.NET AJAX的技术访问到ADO.NET Data Service,并且实现了数据的增删改查等常规操作
 
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication2._Default" %>








"MicrosoftAjax.js" type="text/javascript">

"DataService.js" type="text/javascript">

"text/javascript" language="javascript">
function GetService() {
return new Sys.Data.DataService("/NorthwindService.svc");
}

$(function() {
$("#query").click(function() {
//发起一个异步查询
var proxy = GetService();
var query = "/Customers()"; //这里构造的查询字符串可以很复杂
proxy.query(query, function(result, context) {
for (idx in result) {
var customer = result[idx];
$("" + customer.CustomerID + "," + customer.CompanyName + "
").appendTo("#result");
}
});

});

$("#insert").click(function() {
//插入一个新的客户
var proxy = GetService();
var customer = {
CustomerID: "ABCDE",
CompanyName: "Thinker Inc"
};

proxy.insert(customer, "/Customers", function(result) {
alert("操作已经成功");
});

});

$("#update").click(function() {
//更新一个客户
var proxy = GetService();
var customer;
proxy.query("/Customers('ABCDE')", function(result) {
customer = result;

//修改这个customer
customer.CompanyName = "Changed";
proxy.update(customer, null, function(result) {
alert("更新成功");
});
});

});

$("#delete").click(function() {
//删除一个客户
var proxy = GetService();
var customerID = "ABCDE";
proxy.remove(null, "/Customers('" + customerID + "')", function(result) {
alert("删除成功");
});
});

});




注意,这个DataService.js是单独的,它实际上是封装了四个操作
//------------------------------------------------------------------------------
//
//     Copyright (c) Microsoft Corporation.  All rights reserved.
//
//------------------------------------------------------------------------------

Type.registerNamespace('Sys.Data');

Sys.Data.ActionResult = function(result, error, actionContext, operation) {
/// Represents the result of a single operation in an action sequence batch.
/// Result (if any) of the operation.
/// Error that occurred during the operation.
/// Context object passed to the executor.
/// Short description of the operation performed.
this._result = result;
this._error = error;
this._actionContext = actionContext;
this._operation = operation;
}

Sys.Data.ActionResult.prototype = {

/*
* PROPERTIES
*/

get_result: function() {
/// Gets the result (if any) of the operation.
/// Operation result.
return this._result;
},
get_error: function() {
/// Gets the error that occurred during the operation.  Returns null if no error occurred.
/// Operation error.
return this._error;
},
get_actionContext: function() {
/// Gets the context object passed to the executor.
/// Operation context object.
return this._actionContext;
},
get_operation: function() {
/// Gets a short description of the operation performed.
/// Operation description.
return this._operation;
}

};

Sys.Data.ActionResult.registerClass("Sys.Data.ActionResult");

Sys.Data.ActionSequence = function(dataService) {
/// Exposes methods for performing batch operations against a web-based data service.
/// The DataService object against which to perform operations.
this._dataService = dataService;
this._actionQueue = new Array();
}

Sys.Data.ActionSequence.prototype = {

/*
* PROPERTIES
*/

get_service: function() {
/// Gets the DataService object against which operations are performed.
/// The DataService.
return this._dataService;
},

/*
* METHODS
*/

addInsertAction: function(item, resourceSetUri, actionContext) {
/// Adds an insertion to the execution queue.
/// Item to insert.
/// Resource set into which the item should be inserted.
/// A context object associated with this operation.

var dataService = this._dataService;
Array.enqueue(this._actionQueue, function(o) { dataService.insert(
item,
resourceSetUri,
Sys.Data.ActionSequence._genSuccessCallback(o),
Sys.Data.ActionSequence._genFailureCallback(o),
actionContext // userContext (per-action)
)});
},

addUpdateAction: function(item, resourceUri, actionContext) {
/// Adds an update to the execution queue.
/// Item to update.
/// Resource set in which the item should be updated.
/// A context object associated with this operation.

var dataService = this._dataService;
Array.enqueue(this._actionQueue, function(o) { dataService.update(
item,
resourceUri,
Sys.Data.ActionSequence._genSuccessCallback(o),
Sys.Data.ActionSequence._genFailureCallback(o),
actionContext // userContext (per-action)
)});
},

addRemoveAction: function(item, resourceUri, actionContext) {
/// Adds a removal to the execution queue.
/// Item to remove.
/// Resource set from which the item should be removed.
/// A context object associated with this operation.

var dataService = this._dataService;
Array.enqueue(this._actionQueue, function(o) { dataService.remove(
item,
resourceUri,
Sys.Data.ActionSequence._genSuccessCallback(o),
Sys.Data.ActionSequence._genFailureCallback(o),
actionContext // userContext (per-action)
)});
},

clearActions : function() {
/// Clears the action queue.
Array.clear(this._actionQueue);
},

executeActions: function(actionsCallback, userContext) {
/// Executes operations in the action queue.
/// Callback to execute upon completion of all operations.
/// A context object associated with this batch.

// state object for internal callback methods
var o = {
actionResultQueue: new Array(),
hasError: false,
remainingActions: this._actionQueue
};

// break reference to array so user can't modify after kickoff
this._actionQueue = new Array();

// kickoff - ensure final callback is asynchronous so as not to break method contract
Array.enqueue(o.remainingActions, function(o) {
if (actionsCallback) {
window.setTimeout(function() { actionsCallback(o.actionResultQueue, o.hasError, userContext); }, 0);
}
});
Array.dequeue(o.remainingActions)(o);
}

}

/*
* STATIC INTERNAL HELPER METHODS
*/

// generates an onSuccess callback
Sys.Data.ActionSequence._genSuccessCallback = function(o) {
return function(result, actionContext, operation) {
var newAR = new Sys.Data.ActionResult(result, null, actionContext, operation);
Array.enqueue(o.actionResultQueue, newAR);
Array.dequeue(o.remainingActions)(o); // kickoff next function
};
};

// generates an onFailure callback
Sys.Data.ActionSequence._genFailureCallback = function(o) {
return function(error, actionContext, operation) {
o.hasError = true;
var newAR = new Sys.Data.ActionResult(null, error, actionContext, operation);
Array.enqueue(o.actionResultQueue, newAR);
Array.dequeue(o.remainingActions)(o); // kickoff next function
};
};

Sys.Data.ActionSequence.registerClass("Sys.Data.ActionSequence");

Sys.Data.DataService = function(serviceUri) {
/// Exposes methods for interacting with a web-based data service.
/// URI (absolute or relative) of the data service.
this._serviceUri = serviceUri;
this._timeout = 0;
this._defaultUserContext = null;
this._defaultSucceededCallback = null;
this._defaultFailedCallback = null;
}

Sys.Data.DataService.prototype = {

/*
* PROPERTIES
*/

get_serviceUri: function() {
/// Gets the URI of the data service.
/// The URI of the data service.
return this._serviceUri;
},

get_timeout: function() {
/// Gets the timeout period of each operation.
/// The timeout period (in milliseconds) for each operation.
if (this._timeout === 0) {
return Sys.Net.WebRequestManager.get_defaultTimeout();
}
return this._timeout;
},
set_timeout: function(value) {
this._timeout = value;
},

get_defaultUserContext: function() {
/// Gets the default user context (state object) of each operation.
/// The default user context for each operation.
return this._defaultUserContext;
},
set_defaultUserContext: function(value) {
this._defaultUserContext = value;
},

get_defaultSucceededCallback: function() {
/// Gets the default callback executed after each successful operation.
/// The default success callback for each operation.
return this._defaultSucceededCallback;
},
set_defaultSucceededCallback: function(value) {
this._defaultSucceededCallback = value;
},

get_defaultFailedCallback: function() {
/// Gets the default callback executed after each unsuccessful operation.
/// The default failure callback for each operation.
return this._defaultFailedCallback;
},
set_defaultFailedCallback: function(value) {
this._defaultFailedCallback = value;
},

/*
* METHODS
*/

query: function(query, succeededCallback, failedCallback, userContext, webRequest) {
/// Performs a query (read) against the data service.
/// Path to query.
/// Callback to execute upon successful completion of the operation.
/// Callback to execute upon unsuccessful completion of the operation.
/// A context object associated with this operation.
/// A WebRequest object to use for this operation.

var wRequest = this._prepWebRequest(null, query, "GET", succeededCallback, failedCallback, userContext, query, webRequest);
wRequest.invoke();
},

loadProperty: function(item, property, succeededCallback, failedCallback, userContext, webRequest) {
/// Populates the property of a given item.
/// Item containing the property to be populated.
/// Name of the property which should be populated.
/// Callback to execute upon successful completion of the operation.
/// Callback to execute upon unsuccessful completion of the operation.
/// A context object associated with this operation.
/// A WebRequest object to use for this operation.

var succeededHelper = function(result, context, operation) {
item[operation] = result;
if (!succeededCallback) {
succeededCallback = this._defaultSucceededCallback;
}
if (succeededCallback) {
succeededCallback(item, context, operation);
}
};

var uri;
if (item[property] && item[property].__metadata && item[property].__metadata.uri) {
uri = item[property].__metadata.uri;
}
else if (item.__metadata && item.__metadata.uri) {
uri = item.__metadata.uri + '/' + property;
}
else {
throw Error.create(Sys.Data.Res.dataServiceLoadPropertyUriNotPresent);
}

var wRequest = this._prepWebRequest(null, uri, "GET", succeededHelper, failedCallback, userContext, property, webRequest);
wRequest.invoke();
},

insert: function(item, resourceSetUri, succeededCallback, failedCallback, userContext, webRequest) {
/// Performs an insertion against the data service.
/// Item to insert.
/// Resource set into which the item should be inserted.
/// Callback to execute upon successful completion of the operation.
/// Callback to execute upon unsuccessful completion of the operation.
/// A context object associated with this operation.
/// A WebRequest object to use for this operation.

var wRequest = this._prepWebRequest(null, resourceSetUri, "POST", succeededCallback, failedCallback, userContext, "insert", webRequest);

// moved serialization logic out since we ignore metadata
wRequest.set_body(Sys.Serialization.JavaScriptSerializer.serialize(item));
wRequest.get_headers()["Content-Type"] = "application/json";
wRequest.invoke();
},

update: function(item, resourceUri, succeededCallback, failedCallback, userContext, webRequest) {
/// Performs an update against the data service.
/// Item to update.
/// Resource set in which the item should be updated.
/// Callback to execute upon successful completion of the operation.
/// Callback to execute upon unsuccessful completion of the operation.
/// A context object associated with this operation.
/// A WebRequest object to use for this operation.

var wRequest = this._prepWebRequest(item, resourceUri, "PUT", succeededCallback, failedCallback, userContext, "update", webRequest);
wRequest.get_headers()["Content-Type"] = "application/json";
wRequest.invoke();
},

remove: function(item, resourceUri, succeededCallback, failedCallback, userContext, webRequest) {
/// Performs a removal against the data service.
/// Item to remove.
/// Resource set from which the item should be removed.
/// Callback to execute upon successful completion of the operation.
/// Callback to execute upon unsuccessful completion of the operation.
/// A context object associated with this operation.
/// A WebRequest object to use for this operation.

if (!((item && item.__metadata && item.__metadata.uri) || resourceUri)) {
// must specify URI in item metadata or as parameter
throw Error.create(Sys.Data.Res.dataServiceRemoveUriNotPresent);
}

var wRequest = this._prepWebRequest(item, resourceUri, "DELETE",
this._cbReplaceResult(succeededCallback, null) /* don't return any object to success callback */,
failedCallback, userContext, "remove", webRequest);

// we can't actually serialize an item when we perform a removal
delete wRequest.get_headers()["Content-Type"];
wRequest.set_body(null);

wRequest.invoke();
},

invoke: function(operationUri, httpVerb, parameters, succeededCallback, failedCallback, userContext, webRequest) {
/// Invokes a method exposed by the data service.
/// Path to the service operation to invoke.
/// HTTP verb to be used for this service call.
/// Dictionary of parameters to be passed to the service method.
/// Callback to execute upon successful completion of the operation.
/// Callback to execute upon unsuccessful completion of the operation.
/// A context object associated with this operation.
/// A WebRequest object to use for this operation.

var qb = new Sys.Data.QueryBuilder(operationUri);
for (key in parameters) {
qb.get_queryParams()[encodeURIComponent(key)] = encodeURIComponent(parameters[key]);
}

var wRequest = this._prepWebRequest(null, qb.toString(), httpVerb, succeededCallback, failedCallback, userContext, operationUri, webRequest);
if (httpVerb == "POST") {
// prevents CSRF (SQLBUDT 554530)
wRequest.get_headers()["X-Service-Post"] = "true";
}
wRequest.invoke();
},

createActionSequence: function() {
/// Creates a new action sequence for execution against this data service.
/// An ActionSequence object.
return new Sys.Data.ActionSequence(this);
},

/*
* INTERNAL HELPER FUNCTIONS
*/

// common code for preparing a WebRequest
_prepWebRequest: function(item, relUri, verb, onSuccess, onFailure, context, operation, wRequest) {

if (!relUri) {
relUri = "";
}
if (!wRequest) {
wRequest = new Sys.Net.WebRequest();
}

wRequest.set_url(Sys.Data.DataService._concatUris(this._serviceUri, relUri));
wRequest.set_httpVerb(verb);
wRequest.set_timeout(this.get_timeout());

var headers = wRequest.get_headers();
headers["Accept"] = "application/json";

if (item) {
wRequest.set_body(Sys.Serialization.JavaScriptSerializer.serialize(item));
headers["Content-Type"] = "application/json";
if (item.__metadata && item.__metadata.uri)
wRequest.set_url(item.__metadata.uri);
}

// set defaults
if (!onSuccess) {
onSuccess = this._defaultSucceededCallback;
}
if (!onFailure) {
onFailure = this._defaultFailedCallback;
}
if (!context) {
context = this._defaultUserContext;
}

wRequest.add_completed(function(executor, eventArgs) {
Sys.Data.DataService._callbackHelper(executor, eventArgs, onSuccess, onFailure, context, operation);
});

return wRequest;

},

// helper to replace the result object for callbacks
_cbReplaceResult: function(cb, retVal) {
if (!cb) {
cb = this._defaultSucceededCallback;
}
return (cb)
? function(result, context, operation) { cb(retVal, context, operation); }
: null;
}

}

/*
* STATIC INTERNAL HELPER FUNCTIONS
*/

// concatenation of URIs
Sys.Data.DataService._concatUris = function(serviceUri, resourceUri) {

if (serviceUri.endsWith('/')) {
serviceUri = serviceUri.substr(0, serviceUri.length - 1);
}

if (resourceUri.startsWith('/')) {
resourceUri = resourceUri.substr(1);
}

return serviceUri + '/' + resourceUri;

};

// heavily modified preexisting WebServiceProxy code handles deserialization of data service responses
Sys.Data.DataService._callbackHelper = function(executor, eventArgs, onSuccess, onFailure, userContext, operation) {
if (executor.get_responseAvailable()) {
var statusCode = executor.get_statusCode();
// works around an IE bug where 204 responses to PUT requests get turned into 1223 errors.
if (statusCode == 1223) {
statusCode = 204;
}
var result = null;

try {
var contentType = executor.getResponseHeader("Content-Type");
if (contentType.startsWith("application/json")) {
result = executor.get_object();
}
else if (contentType.startsWith("text/xml")) {
result = executor.get_xml();
}
// Default to the executor text
else {
result = executor.get_responseData();
}
} catch (ex) {
}

var error = executor.getResponseHeader("jsonerror");
var errorObj = (error === "true");
if (errorObj) {
if (result) {
result = new Sys.Data.DataServiceError(false, result.Message, result.StackTrace, result.ExceptionType);
}
}
else if (contentType.startsWith("application/json")) {
if (!result || typeof(result.d) === "undefined") {
throw Sys.Data.DataService._createFailedError(operation, String.format("The data operation '{0}' returned invalid data. The JSON wrapper is incorrect.", operation));
}
result = result.d;
}
if (((statusCode < 200) || (statusCode >= 300)) || errorObj) {
if (onFailure) {
if (!result || !errorObj) {
result = new Sys.Data.DataServiceError(false /*timedout*/, String.format("The data operation '{0}' failed.", operation), "", "");
}
result._statusCode = statusCode;
onFailure(result, userContext, operation);
}
// #if DEBUG
else {
// In debug mode, if no error was registered, display some trace information
if (result && errorObj) {
// If we got a result, we're likely dealing with an error in the method itself
error = result.get_exceptionType() + "-- " + result.get_message();
}
else {
// Otherwise, it's probably a 'top-level' error, in which case we dump the
// whole response in the trace
error = executor.get_responseData();
}
throw Sys.Data.DataService._createFailedError(operation, String.format("The data operation '{0}' failed with the following error: {1}", operation, error));
}
// #endif
}
else if (onSuccess) {
onSuccess(result, userContext, operation);
}
}
else {
var msg;
if (executor.get_timedOut()) {
msg = String.format("The data operation '{0}' timed out.", operation);
}
else {
msg = String.format("The data operation '{0}' failed.", operation)
}
if (onFailure) {
onFailure(new Sys.Data.DataServiceError(executor.get_timedOut(), msg, "", ""), userContext, operation);
}
// #if DEBUG
else {
// In debug mode, if no error was registered, display some trace information
throw Sys.Data.DataService._createFailedError(operation, msg);
}
// #endif
}
};

//#if DEBUG
Sys.Data.DataService._createFailedError = function(operation, errorMessage) {
var displayMessage = "Sys.Data.DataServiceFailedException: " + errorMessage;
var e = Error.create(displayMessage, { 'name': 'Sys.Data.DataServiceFailedException', 'operation': operation });
e.popStackFrame();
return e;
}
//#endif

Sys.Data.DataService.registerClass("Sys.Data.DataService");

Sys.Data.DataServiceError = function(timedOut, message, stackTrace, exceptionType) {
/// Represents a web-based data service error.
/// Whether the operation failed because of a timeout.
/// The error message.
/// The stack trace of the error.
/// The server exception type.
this._timedOut = timedOut;
this._message = message;
this._stackTrace = stackTrace;
this._exceptionType = exceptionType;
this._statusCode = -1;
}

Sys.Data.DataServiceError.prototype = {

/*
* PROPERTIES
*/

get_timedOut: function() {
/// True if the data service operation failed due to timeout.
/// Whether the operation failed due to timeout.
return this._timedOut;
},

get_statusCode: function() {
/// HTTP status code of the response if any, defaults to -1 otherwise
/// Int representing the status of the response.
return this._statusCode;
},

get_message: function() {
/// Error message
/// Error message
return this._message;
},

get_stackTrace: function() {
/// Stack trace of the error
/// Stack trace of the error.
return this._stackTrace;
},

get_exceptionType: function() {
/// Exception type of the error
/// Exception type of the error.
return this._exceptionType;
}
}

Sys.Data.DataServiceError.registerClass("Sys.Data.DataServiceError");

Sys.Data.QueryBuilder = function(uri) {
/// Allows construction of ADO.NET Data Service queries.
/// The URI (absolute or relative) to parse.
this._queryparams = new Object();
this._uri = uri;

var idxQuery = uri.indexOf('?');
if (idxQuery >= 0) {
// split query string if already exists
this._uri = uri.substr(0, idxQuery);
var params = uri.substr(idxQuery + 1).split('&');
for (var i in params) {
param = params[i];
var idxValue = param.indexOf('=');
if (idxValue >= 0) {
this._queryparams[param.substr(0, idxValue)] = param.substr(idxValue + 1);
}
else {
this._queryparams[param] = "";
}
}
}
}

Sys.Data.QueryBuilder.prototype = {

/*
* PROPERTIES
*/

get_skip: function() {
/// Gets the starting index at which elements should be returned.
/// The number of elements to skip when returning results,
/// or null if no skip value is specified.
return this._getIntParam("$skip");
},
set_skip: function(value) {
this._setParam("$skip", value);
},

get_top: function() {
/// Gets the maximum number of elements to return.
/// The maximum number of elements to return,
/// or null if no maximum is specified.
return this._getIntParam("$top");
},
set_top: function(value) {
this._setParam("$top", value);
},

get_orderby: function() {
/// Gets the ordering string that should be applied to the result set.
/// The ordering applied to the result set,
/// or null if no ordering is specified.
return this._getStringParam("$orderby");
},
set_orderby: function(value) {
this._setParam("$orderby", value);
},

get_filter: function() {
/// Gets the filter string that should be applied to the result set.
/// The filter applied to the result set,
/// or null if no filter is specified.
return this._getStringParam("$filter");
},
set_filter: function(value) {
this._setParam("$filter", value);
},

get_expand: function() {
/// Gets the property expansion string that should be applied to the result set.
/// The property expansion applied to the result set,
/// or null if no property expansion is specified.
return this._getStringParam("$expand");
},
set_expand: function(value) {
this._setParam("$expand", value);
},

get_resourcePath: function() {
/// Gets the resource path (without query parameters) originally passed as an argument to
/// this object's constructor.
/// The resource path of this QueryBuilder object.
return this._uri;
},
/* setter temporarily removed until we can figure out how to spec it
set_resourcePath: function(value) {
var idxQuery = value.indexOf('?');
this._uri = (idxQuery >= 0) ? value.substr(0, idxQuery) : value;
}, */

get_queryParams: function() {
/// Gets the dictionary of query parameters for the current QueryBuilder.
/// A dictionary of query parameters.  This object will be non-null but may
/// contain no fields if no query parameters have been set.
return this._queryparams;
},

/*
* METHODS
*/

toString: function() {
/// Generates a complete query string based on this object's resource path and parameter dictionary.
/// The complete query string.
var params = new Array();
for (var key in this._queryparams) {
if (!Array.contains(Sys.Data.QueryBuilder._queryOptions, key)) {
var value = this._queryparams

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: