1. 开发模式(根据张子阳《Asp.Net Ajax的两种基本开发模式》总结)
(1). 第一种UpdatePanel模式
就是在页面上拖入一个ScriptManager和UPdatePanel,在UpdatePanel中放入需要无刷新执行的控件,需要注意的是不同的UpdatePanel之间如果要互相不影响,则设置UpdateMode属性为Conditional。
(2). Web Service模式
安装AjaxToolKit;
在WebApplication中添加WCF服务(AJAX-enabled WCF Service),在wcf中写入一个方法,例如:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SimpleService
{
// Add [WebGet] attribute to use HTTP GET
[OperationContract]
public string GetDateTime(string clientDate)
{
string rtn = DateTime.Now.ToString();
return rtn;
}
// Add more operations here and mark them with [OperationContract]
}
在需要用到该服务的页面中注册WCF服务,注册方法为在页面中添加一个ScriptManager:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/SimpleService.svc" />
</Services>
</asp:ScriptManager>
在页面中使用这个WCF服务的方法当然是给它传递参数,然后获取运行后的返回值,这些都是在javascript中完成的:
<script type="text/javascript">
//在javascript中注册一个按纽的click事件
//在click事件中调用WCF服务,给它传递参数
function btn_onclick(){
var clientDate=new Date();
var param4="This is param4.";
//在这里面调用WCF服务的时候参数有几个,前面的参数是要传递给WCF服务的,
//OnSuccess是当调用服务成功时的回调javascript方法
//OnFailed是当调用失败时的回调javascript方法
//最后一个参数是附带的参数,可以将一些需要的信息传递给回调方法
SimpleService.GetDateTime(clientDate,OnSuccess,OnFailed,param4);
return true;
}
//这是调用成功时的回调函数
//它有2个参数,第一个是WCF方法传递回来的结果
//第二个是在调用WCF服务的时候传递给调用函数的最后一个附带的参数
function OnSuccess(result,param4){
}
//调用失败时的回调函数
function OnFailed(args){
}
</script>
关于运用XML和Ajax来优化网站性能,参考:http://www.cnblogs.com/JimmyZhang/archive/2008/12/07/1349454.html
假如用WebService的话也差不多,不同的是WCF中需要调用的方法上加[OperationContract],而在WebService中需要在调用的方法上加上[WebMothod],同时加上[ScriptService](这个需要引用System.Web.Script.Services命名空间),注册方法也一样,调用时采用
[NameSpace].[ClassName].[MethodName](param1, param2 …, onSucceeded, onFailed)
这种格式。
关于Ajax异步调用WebService,参考:《使用ASP.NET AJAX异步调用WebService》
2. JQuery中的Ajax
(1). ajax最基本的用法XMLHTTPRequest
用浏览器的xmlHttpRequest对象可以向服务器发送请求;
XmlHttp是一套可以在Javascript、VbScript、Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API。
下面的小例子演示了基本用法:
<script language="javascript" type="text/javascript">
function Button1_onclick() {
var txt=$("#Text1").val();
var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
if(!xmlhttp){
alert("xmlhttp not supported");
return false;
}
xmlhttp.open("POST","TxtHandler.ashx?txt="+txt,false);
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4){
if(xmlhttp.status==200){
$("#Text2").val(xmlhttp.responseText);
}else{
alert("ajax server error");
}
}
}
xmlhttp.send();
}
</script>
这是一般处理页面(TxtHandler.ashx)内容,将接收到的字符串进行简单处理之后写入Response:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class TxtHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string txt = context.Request["txt"];
string returnTxt = "This is the text returned: " + txt;
context.Response.Write(returnTxt);
}
public bool IsReusable
{
get
{
return false;
}
}
}
这段代码实现了这么一个功能,在客户端页面中有几个HTML控件:第一个文本框Text1,按纽Button1,第二个文本框Text2,需要在点击按纽的时候将第一个文本框中的内容在不刷新整个页面的情况下经过服务器处理后将处理结果填入第二个文本框中。
这里的var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");并不是在任何浏览器中都可以获得xmlHttp对象的,只有在IE的某些版本中可以获得xmlHttp,最好的办法就是先判断一下是否支持:
if (window.XMLHttpRequest)
{// code for all new browsers
xmlhttp=new XMLHttpRequest();
}
else if (window.ActiveXObject)
{// code for IE5 and IE6
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
如果要更全面浏览器版本支持的要求,参考:http://www.openx.cn/article.asp?id=287
open()
这个方法有3个参数,第一个"GET"/"POST",第二个参数是目标服务器的处理页面(这里是建立的一般处理页面.ashx),第三个参数表明是否异步执行。
关于readyState,status这几个参数所代表的意思,或者一共有几种类型,参考:http://www.blueidea.com/tech/web/2008/5329.asp
(2). JQuery中的Ajax
$.post();/$.get();
<script language="javascript" type="text/javascript">
function Button2_onclick() {
var txt=$("#Text1").val();
$.post("TxtHandler.ashx”,{“txt”:txt},function(data,textStatus){
if(textStatus=="success"){
$("#Text2").val(data);
}else{
alert("ajax failed");
}
});
}
</script>
以上是用JQuery框架中的ajax简化之前的功能代码,JQuery的使用不再赘述。
post方法有3个参数,第一个是目标服务器处理页面(一般处理页面.ashx),不同的是没有“?txt=...”这种参数传递,第二个参数才是传递给服务器的参数集合(dictionary格式{"param1":value1,"param2":value2,...}),第三个参数是一个匿名方法,这个方法是回调方法,其中包含从服务器处理页面回调过来的返回结果(data),以及返回状态(textStatus表明是否处理成功)。
$.ajax();
在JQuery的API中可以查到这个方法,是JQuery中Ajax的底层实现。
上面用$.post()实现的方法可以用$.ajax()来实现:
var txt=$("#Text1").val();
$.ajax({
type:"POST",
url:"TxtHandler.ashx",
data:"txt="+txt,//如果有多个参数用&连接
success:function(data){
$("#Text2").val(data);
}
});
3. 关于ajax传递参数类型
在之前的例子中客户端页中面javascript传递给服务端一般处理页面的参数是字符串,一般处理页面接收到参数之后经过处理再返回字符串,但是很多情况我们需要服务器返回的不是字符串,而是更加复杂的类型(比如自定义类型,DataSet,Json,xml等等),DataSet类型可以参考张子阳文章《从一个范例看XML的应用》,利用XML来解决,下面是Json格式的数据传递方法的一个例子。
(1). 将DataTable序列化为Json格式
数据库test中有一个Users表,现在要更具客户端页面文本框中输入的用户名来查询出所有叫这个名字的用户信息,这个过程中handler处理页面接收到传过来的用户名之后连接数据库查询出拥有该用户名的信息存入DataTable,再将DataTable转换成JSON格式,这里用Newtonsoft.Json.Net20.dll来转换,从网上下载这个dll,添加引用,通过其中的string DataTableToJSON(DataTable dt, string dtName){}方法来转换,返回JSON字符串,写入Response.
客户端的整个代码如下:
<head runat="server">
<script src="js/jquery-1.4.1.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
$("#btnSearch").click(function(){
var username=$("#txtUserName").val();
$.ajax({
type:"POST",
dataType:"json",
url:"ajax/UsersHandler.ashx",
data:"UserName="+username,
success:function(json){
var users=json.Users;
$.each(users,function(i,n){
$("#userInfo").append("用户名:"+n.UserName+" 密码:"+n.Password+"<br>");
});
}
});
});
});
</script>
</head>
<body>
<input type="text" id="txtUserName" /><br />
<input type="button" id="btnSearch" value="搜索" />
<div id="userInfo">
</div>
</body>
服务端的UsersHandler.ashx代码如下:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class UsersHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string username = context.Request["UserName"];
SqlConnection conn = new SqlConnection(@"server=T3-IT03\SQLEXPRESS;user=sa;pwd=sa;database=test");
SqlCommand cmd = new SqlCommand("select * from Users where UserName='"+username+"'", conn);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds);
DataTable dt = ds.Tables[0];
string json = DataTableToJSON(dt, "Users");
context.Response.Write(json);
}
//将DataTable序列化成Json格式的方法
public static string DataTableToJSON(DataTable dt, string dtName)
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jw = new JsonTextWriter(sw))
{
JsonSerializer ser = new JsonSerializer();
jw.WriteStartObject();
jw.WritePropertyName(dtName);
jw.WriteStartArray();
foreach (DataRow dr in dt.Rows)
{
jw.WriteStartObject();
foreach (DataColumn dc in dt.Columns)
{
jw.WritePropertyName(dc.ColumnName);
ser.Serialize(jw, dr[dc].ToString());
}
jw.WriteEndObject();
}
jw.WriteEndArray();
jw.WriteEndObject();
sw.Close();
jw.Close();
}
return sb.ToString();
}
这里为了方便,连接数据库就用最简单的方法连接SQLSERVER
效果图如下:
(2). 将单个对象序列化为Json
对于将实体类对象转换成Json格式,假如在服务端有个自定义的Entity,叫User:
public class User {
public int id { get; set; }
public string name { get; set; }
}
①现在要将一个User类型的数据序列化为Json格式,传递给客户端,同样用Newtonsoft.Json.Net20.dll也可以来实现。
客户端在一个文本框中输入用户名,点击按纽之后在服务端接收这个用户名,然后将具有这个用户名的Entity序列化成Json,传回客户端,客户端显示出这个用户名的id:
客户端:
<head runat="server">
<script src="js/jquery-1.4.1.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
$("#btn").click(function(){
var username=$("#txt").val();
$.ajax({
type:"POST",
dataType:"json",
url:"ajax/AjaxTest3Handler.ashx",
data:"username="+username,
success:function(json){
alert(json.id);
}
});
});
});
</script>
</head>
<body>
<input type="text" id="txt" />
<input type="button" value="传值" id="btn" />
</body>
也可以用$.post来实现,效果是一样的:
$.post("ajax/AjaxTest3Handler.ashx",{"username":username},function(data,status){
var user=$.parseJSON(data);
alert(user.id);
});
需要注意的是通过$.post回传过来的数据data需要经过$.parseJSON(data)转换成Json格式,而用$.ajax则不用转换,本身就是Json格式。
服务端:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class AjaxTest3Handler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string username = context.Request["username"];
User user = new User();
user.id = 1;
user.name = username;
string json = Newtonsoft.Json.JsonConvert.SerializeObject(user, Newtonsoft.Json.Formatting.Indented);
context.Response.Write(json);
}
public bool IsReusable
{
get
{
return false;
}
}
}
public class User {
public int id { get; set; }
public string name { get; set; }
}
②除去用NewtonSoft的序列化工具以外,还可以用JavaScriptSerializer来实现同样的功能
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class AjaxTest3Handler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string username = context.Request["username"];
User user = new User();
user.id = 1;
user.name = username;
//string json = Newtonsoft.Json.JsonConvert.SerializeObject(user, Newtonsoft.Json.Formatting.Indented);
//context.Response.Write(json);
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(user);
context.Response.Write(json);
}
public bool IsReusable
{
get
{
return false;
}
}
}
public class User {
public int id { get; set; }
public string name { get; set; }
}
需要注意的是如果在这个Entity中有某个属性是不需要序列化的,可以在这个属性上方加上[ScriptIgnore]。
在服务端如果要反序列化客户端传来的Json数据,用JavaScriptSerializer的DeserializeObject就可以了。
而在客户端通过Javascript同样也可以进行序列化和反序列化的工作(这部分代码没经过测试):
//序列化
var user={id:1,name:'johnsmith'};
var serializer=Sys.Serialization.JavaScriptSerializer;
var json=serializer.serialize(user);
//反序列化
var user=serializer.deserialize(json);
关于更多JavaScriptSerializer,参考:《ASP.NET AJAX框架编程之JSON序列化剖析》
(3). 将多个对象存入List序列化为Json
现在需要在服务端将多个User对象回传到客户端,可以将多个User对象存入到List中,再将List序列化为Json,然后回传,在客户端先将Json反序列化为List类型的对象,然后遍历这个对象获取User:
客户端:
<script type="text/javascript">
$(function(){
$("#btn").click(function(){
$.post("ajax/AjaxTest3Handler.ashx",function(data,status){
var list=$.parseJSON(data);
for(var i=0;i<list.length;i++){
var user=list[i];
alert(user.id);
}
});
});
});
</script>
或者(效果一样):
<script type="text/javascript">
$(function(){
$("#btn").click(function(){
var username=$("#txt").val();
$.ajax({
type:"POST",
dataType:"json",
url:"ajax/AjaxTest3Handler.ashx",
data:"username="+username,
success:function(json){
var list=json;
for(var i=0;i<list.length;i++){
var user=list[i];
alert(user.id);
}
}
});
});
});
</script>
服务端:
List<User> list = new List<User>();
User user1 = new User();
user1.id = 1;
user1.name = "name1";
list.Add(user1);
User user2 = new User();
user2.id = 2;
user2.name = "name2";
list.Add(user2);
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(list);
context.Response.Write(json);
4. 总结
以上关于ajax在asp.net中的运用是我这段时间总结出来的,其中包括我在学习ajax期间自己领悟到的知识,同时也参考了很多资料,文中已经标明。
关于JQuery中运用Ajax的更详细资料,参考:http://www.cnblogs.com/yeer/archive/2009/07/23/1529460.html