通过jQuery或ScriptManager以Ajax方式访问服务

时间:2023-03-08 22:00:18

1、客户端和服务端

服务端对外提供服务时,可以通过handler或者webservice。handler比较轻便,但是难以对外公开,只有程序员自己知道它到底做了些什么工作。webservice可以将服务对外公开,调用也方便,更加专业些。如果不是要公开的接口,handler完全可以胜任了。下面是将webservice发布的效果。

通过jQuery或ScriptManager以Ajax方式访问服务

客户端在调用服务端的服务时,最简单的莫过于使用jQuery了。当然微软也提供了ScriptMananger来访问WebService。他们之间的关系可以用下图说明。

通过jQuery或ScriptManager以Ajax方式访问服务

2、搞一个Handler

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization; namespace WjjStudy.handler
{
/// <summary>
/// info 的摘要说明
/// </summary>
public class info : IHttpHandler
{ public void ProcessRequest(HttpContext context)
{
//提取参数
//context.Request.QueryString["name"];
//context.Request.Form["name"]; //json 的 contentType 常见写法有 : text/json & text/javascript .
//但是 这个 text/json 其实是根本不存在的, 而 text/javascript 在有些时候客户端处理起来会有歧义.
对于json的contentType , rfc里定义的标准写法是 :application/json.在这里毫无疑问 我们应该选择标准写法的 application/Json。
//如果指定为text/json, 处理方式:firefox,下载;chrome,直接显示。
context.Response.ContentType = "application/json";//只有具体指定了,firefox的json插件才起作用!
//context.Response.Write("{\"name\":\"wjj\",\"age\":\"25\"}");
Hashtable ht = new Hashtable();
ht["name"] = "wjj";
ht["age"] = ""; JavaScriptSerializer js = new JavaScriptSerializer();
string json = js.Serialize(ht);
context.Response.Write(json);
} public bool IsReusable
{
get
{
return false;
}
}
}
}

3、搞一个WebService

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Script.Services;
using System.Web.Services;
using WjjStudy.model; namespace WjjStudy.asmx
{
/// <summary>
/// info 的摘要说明
/// </summary>
[WebService(Namespace = "http://gagarin.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
[System.Web.Script.Services.ScriptService]
public class info : System.Web.Services.WebService
{ [WebMethod(Description = "返回类型是对象")]
public Student GetStudent(int para)
{
return new Student { ID = para, Name = "wjj" };
//{"d":{"__type":"WjjStudy.model.Student","ID":100,"Name":"wjj"}}
} [WebMethod(Description = "返回类型是字符串")]
//[ScriptMethod(ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)] 没用
public string GetStudentJson(int para)//返回给客户端为json字符串,需要将该字符串再次序列化。
{
//1、拼凑JSON字符串
//return "{\"ID\":" + para + ",\"Name\":\"wjj\"}"; //2、借助JavaScriptSerializer
//this.Context.Request.ContentType = "application/json";//没用
//this.Context.Response.ContentType = "application/json";//没用 JavaScriptSerializer jss = new JavaScriptSerializer();
return jss.Serialize(new Student { ID = para, Name = "wjj" });
//{"d":"{\"ID\":100,\"Name\":\"wjj\"}"}
}
}
}

4、jQuery访问Handler

jQuery访问Handler,只要调用$.ajax({}),将url传递进去就ok了,比较简单,就不演示了。当然如果你不怕麻烦你可以使用JS原生的XMLHttpRequest来访问它。

 <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>xmlhttprequest实现ajax访问</title>
<script type="text/javascript">
function createXHR() {
var xhr = null;
try {
// Firefox, Opera 8.0+, Safari,IE7+
xhr = new XMLHttpRequest();
}
catch (e) {
// Internet Explorer
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
xhr = null;
}
}
}
return xhr;
}
//在收到响应后相应数据会填充到XHR对象的属性,有四个相关属性会被填充:
//1. responseText:作为响应主体被返回的文本
//2. responseXML:如果响应内容的类型是”text/xml”或”application/xml”,这个属性将保存包含着相应数据的XML文档
//3. status:响应的HTTP状态(200,404,500等)
//4. statusText:HTTP状态说明
var xhr = createXHR();
//检查XHR对象的readyState属性,该属性表示请求/响应过程中的当前活动阶段,每当readyState值改变的时候都会触发一次onreadystatechange事件。必须在open前就指定该处理函数。
xhr.onreadystatechange = function () {
//readyState
//0:请求未初始化;
//1:服务器已建立连接;
//2:请求已接受;
//3:请求处理中;
//4:请求已完成,且响应就绪。
if (xhr.readyState == 4 && xhr.status == 200) {
console.log('Original Ajax: ' + xhr.responseText);
}
}
xhr.open('post', '../handler/info.ashx', true);//get或post,ashx需要发布后才可以访问
xhr.setRequestHeader("userdef", "haha");//open后,send前
xhr.send('{para:100}');
</script>
</head>
<body>
</body>
</html>

5、使用jQuery和ScriptManager访问WebService及比较

这里才是本文想说的重点呢。因为有好几个地方需要注意,否则很纠结。以下是本人测试得到的结论,仅供参考。

测试的代码如下(由于用到了ScriptManager,这是一个aspx文件):

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="testAjax.aspx.cs" Inherits="WjjStudy.aspx.testAjax" %>

 <!DOCTYPE html>

 <html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jquery、ScriptManager调用WebService</title>
<script src="../js/jquery-1.8.3.min.js"></script>
<script>
//请求类型默认是application/json
function ajaxGo() {//默认返回json
//全路径:命名空间.类名.方法名。不管参数名,按照顺序匹配。
WjjStudy.asmx.info.GetStudent(100, function (result) {
console.log(result);//默认就是json
}, function () {
console.error("访问失败。");
}); WjjStudy.asmx.info.GetStudentJson(100, function (result) {
console.log(result);//默认就是json
}, function () {
console.error("访问失败。");
});
} //请求类型默认是application/x-www-form-urlencoded; charset=UTF-8
function jqAjaxGo() {//默认返回xml,如何改成json?
//1、返回xml
$.ajax({
type: 'post',//默认只支持post,如果需要支持get,需要配置web.config
url: '../asmx/info.asmx/GetStudent',
async: true,
data: { "para": 1000 },
success: function (result) {
console.log(result);
},
error: function () {
console.error("访问失败。");
}
});
//2、返回xml
$.ajax({
type: 'post',//默认只支持post,如果需要支持get,需要配置web.config
url: '../asmx/info.asmx/GetStudentJson',
async: true,
data: { para: 1000 },
success: function (result) {
console.log(result);
},
error: function () {
console.error("访问失败。");
}
}); //如何换成json?大量的尝试后
//不管有没有配置web.config,使用get方法均报错:尝试使用 GET 请求调用方法“GetStudent”,但不允许这样做。
//所以只能post,不能get。 $.ajax({
type: 'post',
url: '../asmx/info.asmx/GetStudent',
async: true,
data: '{para:1000}',
//1、参数列表必须同名,不区分大小写 PARa也行。不管顺序,按照参数名匹配。
//2、如果指定contentType: 'application/json;charset=UTF-8',直接写{para:1000}报错->无效的para json基元。需要写成'{}'
contentType: 'application/json;charset=UTF-8',//指定contentType才有效,dataType不指望。
dataType: 'json',//期待返回的类型,服务器会先 根据返回的数据推断,如果推断不了才会用这里的dataType。一般而言,都可以根据头信息推断出来,所以这里dataType几乎没用。
success: function (result) {
console.log(result);
},
error: function () {
console.error("访问失败。");
}
}); $.ajax({
type: 'post',
url: '../asmx/info.asmx/GetStudentJson',
async: true,
data: '{ para: 1000 }',
contentType: 'application/json;charset=UTF-8',
success: function (result) {
console.log(result);
},
error: function () {
console.error("访问失败。");
}
}); }
</script>
</head>
<body> <form id="form1" runat="server">
<%--注册脚本,会生成很多其他js--%>
<asp:ScriptManager ID="clientService" runat="server">
<Services>
<asp:ServiceReference Path="~/asmx/info.asmx" />
</Services>
</asp:ScriptManager> <div id="container">
<input type="button" value="ScripManager Test Ajax" onclick="ajaxGo();" />
<br />
<input type="button" value="jQuery Test Ajax" onclick="jqAjaxGo();" />
<br />
</div>
</form>
</body>
</html>

执行效果 :

点击ScriptManager Text Ajax:

通过jQuery或ScriptManager以Ajax方式访问服务

点击jQuery Text Ajax按钮

通过jQuery或ScriptManager以Ajax方式访问服务

注意点1

webservice默认只支持post请求,如果要支持get请求,需要配置web.config,在system.web节点中加入以下配置

 <configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<!--加上以下节点,避免Get请求时(默认只支持HttpPost)报错:因 URL 意外地以“/GetStudent”结束,请求格式无法识别。-->
<webServices>
<protocols>
<add name= "HttpPost" />
<add name= "HttpGet" />
</protocols>
</webServices>
</system.web> </configuration>

注意点2

jQuery在发送ajax请求时,请求类型默认是application/x-www-form-urlencoded; charset=UTF-8,webservice默认则会返回xml格式的字符串,如果我们想返回json格式的怎么搞?

我在客户端发送Ajax请求时,设置dataType:'json',可惜没用,我猜测它的本质含义是:期待返回的类型,服务器会先 根据返回的数据推断,如果推断不了才会用这里的dataType。一般而言,都可以根据头信息推断出来,所以这里dataType几乎没用。然后在服务器端设置Response.ContentType="application/json",也不奏效。当然了,同时设置也没有结果...

后来我设置contentType:'application/json',貌似看到了希望,可是报错:无效的para json基元,后来测试(很久时间)发现需要将{para:1000}写成'{para:1000}'才可以。

注意点3

设置了contentType:'application/json'可以返回json字符串了,但是只能使用post方法,不管你的web.config是否有配置。否则报错:尝试使用 GET 请求调用方法“GetStudent”,但不允许这样做。

注意点4

通过ScriptManager来访问WebService时,查看源文件,会发现给你生成很多的JS,开发虽然是简单了,但是这么多的js一定程度上消耗更多的性能,网页加载的速度变慢、数据量增大不可避免了。所以推荐使用jQuery!

6、总结

个人认为最佳模式是jQuery加上WebService,但是我还是习惯于jQuery加上Handler。我觉得这篇文章最有意义的还是如何让返回的xml改成返回json。如果你能够亲自动手做一下,相信会有更深的体会,因为代码里写了较多的注释,会帮助你理解。

参考链接:ASP.NET 使用Ajax