VS 2008
本文介绍在客户端js中如何调用程序内部的Web Services
1. 创建可供客户端js调用的Web Service
新建一个Web Service: UserSvc.asmx
using
System;
using
System.Collections;
using
System.Linq;
using
System.Web;
using
System.Web.Services;
using
System.Web.Script.Services;
using
System.Web.Services.Protocols;
using
System.Xml.Linq;


/**/
/// <summary>
/// Summary description for UserSvc
/// </summary>
[WebService(Namespace
=
"
http://tempuri.org/
"
)]
[WebServiceBinding(ConformsTo
=
WsiProfiles.BasicProfile1_1)]
//
To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[ScriptService]

public
class
UserSvc : System.Web.Services.WebService
{


public UserSvc ()
{

//Uncomment the following line if using designed components
//InitializeComponent();
}

[WebMethod]

public string GetUserName(int userId)
{
return userId == 1 ? "guozhijian" : string.Empty;
}
}
1) 添加using System.Web.Script.Services
2) 为类UserSvc加上[ScriptService]的Attribute
3) 与普通WebServices一样,方法需要加上[WebMethod]的Attribute
现在转到客户端,在页面上添加ScriptManager控件
<
asp:ScriptManager ID
=
"
sMgr
"
runat
=
"
server
"
>
<
Services
>
<
asp:ServiceReference Path
=
"
~/UserSvc.asmx
"
/>
</
Services
>
</
asp:ScriptManager
>
在页面上置一个input button,点击后调用UserSvc的GetUserName方法
<
input type
=
"
button
"
id
=
"
btnGetUserName
"
value
=
"
get UserName
"
onclick
=
"
btnGetUserNameClickHandler();
"
/>
<
script type
=
"
text/javascript
"
>

function btnGetUserNameClickHandler()
{

UserSvc.GetUserName(1, getUserNameSucceed, getUserNameFailed,
{msg: "this is a message"});
}

function getUserNameSucceed(result, ctx, methodName)
{
alert(result);
alert(ctx.msg);
alert(methodName);
}

function getUserNameFailed(err, ctx, methodName)
{
alert(err.get_message());
alert(ctx.msg);
alert(methodName);
}
</
script
>
如果使用VS 2008,在客户端将会智能感知出UserSvc及其方法。在UserSvc中定义的GetUserName方法,在客户端调用的时候接受几个参数,首先是在UserSvc中定义的参数列表,然后是Webservice调用成功后回调的方法,调用失败后回调的方法,最后一个是上下文参数。
本例中,调用web service成功后回调的方法是 getUserNameSucceed, 失败后的回调方法是getUserNameFailed方法,而上下文参数我随便定义了一个{msg : "this is a message"}的对象
对于回调函数的方法,定义为3个参数,第一个result是web service 方法的返回值,第二个是上下文参数,第三个methodName为本次调用的Webservice中定义的方法名。
为测试异常发生的情况,将UserSvc中的GetUserName方法略作修改:
[WebMethod]

public
string
GetUserName(
int
userId)
{
//return userId == 1 ? "guozhijian" : string.Empty;
throw new Exception("an error occured");
}
调用Web Service的时候,可以设置调用超时的时间限制:
function btnGetUserNameClickHandler()
{
UserSvc.set_timeout(1000);

UserSvc.GetUserName(1, getUserNameSucceed, getUserNameFailed,
{msg: "this is a message"});
}
既是在调用GetUserName方法前调用set_timeout方法,本例意为:1秒超时
改一下web service端的GetUserName方法:
[WebMethod]

public
string
GetUserName(
int
userId)
{
System.Threading.Thread.Sleep(2000);
return userId == 1 ? "guozhijian" : string.Empty;
}
这样,1秒以后就是调用 getUserNameFailed方法。提示超时错误。
2. 处理复杂类型
在服务端新建一个UserInfo类:
public
class
UserInfo

{

public int UserId
{
get;
set;
}

public string UserName
{
get;
set;
}
}
在UserSvc中定义一个获取UserInfo的方法:
[WebMethod]

public
UserInfo GetUserInfo(
int
userId)
{

return userId == 1 ? new UserInfo()
{ UserId = 1, UserName = "guozhijian" } : null;
}
在客户端调用该方法,并获得返回的UserInfo:
function btnGetUserNameClickHandler()
{

UserSvc.GetUserInfo(1, getUserNameSucceed, getUserNameFailed,
{msg: "this is a message"});
}

function getUserNameSucceed(result, ctx, methodName)
{
alert(result.UserId);
alert(result.UserName);
}
因为 在UserSvc中的方法引用了UserInfo类,所以在客户端可以直接new UserInfo对象,并传递到服务端:
[WebMethod]

public
bool
Update(UserInfo info)
{
// to update
return true;
}
function btnGetUserNameClickHandler()
{
var info = new UserInfo();
info.UserId = 1;
info.UserName = "guozhijian";

UserSvc.Update(info, getUserNameSucceed, getUserNameFailed,
{msg: "this is a message"});
}
如果UserSvc中的方法还没有引用到UserInfo类,而在客户端有想创建一个UserInfo对象,那么可以在UserSvc类定义加上一个Attribute:
[GenerateScriptType(
typeof
(UserInfo))]
泛型支持:
[WebMethod]

public
List
<
UserInfo
>
GetUsers()
{

return new List<UserInfo>()
{

new UserInfo()
{UserId = 1, UserName = "guozhijian"},

new UserInfo()
{UserId = 2, UserName = "zhenglanzhen"}
};
}
function btnGetUserNameClickHandler()
{

UserSvc.GetUsers(getUserNameSucceed, getUserNameFailed,
{msg: "this is a message"});
}

function getUserNameSucceed(result, ctx, methodName)
{

for(var i=0; i<result.length; i++)
{
alert(result[i].UserId + "," + result[i].UserName);
}
}
3. Page Method
客户端js还可以调用在页面的后台代码页的方法:
[System.Web.Services.WebMethod()]

public
static
string
GetUserName()
{
return "Guozhijian";
}
必须定义为static
<
asp:ScriptManager ID
=
"
sMgr
"
runat
=
"
server
"
EnablePageMethods
=
"
true
"
></
asp:ScriptManager
>
<
div
>
<
input type
=
"
button
"
id
=
"
btnShowName
"
onclick
=
"
btnShowNameClickHandler()
"
value
=
"
show name
"
/>
</
div
>
必须设置scriptManager控件的 EnablePageMethods="true"
<
script type
=
"
text/javascript
"
>

function btnShowNameClickHandler()
{

PageMethods.GetUserName(onSucceed,null,
{msg : "this is a message"});
}

function onSucceed(result, ctx, methodName)
{
alert(result);
alert(ctx.msg);
alert(methodName);
}
</
script
>
通过PageMethods引用方法