客户端访问WebService(上)
基本使用方式
赵劼
MSDN特邀讲师
jeffz@live.com
本次课程内容包括 • 客户端访问WebService基础 • 客户端访问PageMethod基础 • 错误处理 • 复杂数据类型使用基础 • 客户端代理使用细节
收听本次课程需具备的条件 • 了解.NET Framework开发 • 熟悉JavaScript开发(应知道怎么调用方法,回调函数的概念 )
一、服务器端释放WebService方法 • 编写一个普通的ASP.NET WebService • 为WebService类添加自定义属性标记 – ScriptServiceAttribute • 释放WebService方法 – 访问级别为public(首先基本public权限的方法 ) – 使用WebMethodAttribute进行标记 • 为页面中的ScriptManager(Proxy)引入asmx文件
二、客户端访问WebService • [Namespaces.]ClassName.MethodName (命名空间 -> 类 -> 方法 ) • 依次传入参数 • 传入一个方法做为成功后的回调函数 • 即使没有返回值也会调用回调函数(因为它只是通知你事件已经处理完毕)
DEMO 1 (客户端访问WebService基础 )
WebServiceFoundation.asmx
<%
@ WebService Language
=
"
C#
"
Class
=
"
Sample.WebServiceFoundation
"
%>
using
System;
using
System.Web;
using
System.Web.Services;
using
System.Web.Services.Protocols;
using
System.Web.Script.Services;
namespace
Sample
...
{ [WebService(Namespace = " http://tempuri.org/ " )] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ScriptService] // 要释放时此处必须标写 public class WebServiceFoundation : System.Web.Services.WebService //继承WebService类 ... { [WebMethod] public int GetRandom() ... { return new Random(DateTime.Now.Millisecond).Next(); } [WebMethod] public int GetRangeRandom( int minValue, int maxValue) ... { //在一个区间获得一个随机数 return new Random(DateTime.Now.Millisecond).Next(minValue, maxValue); } } }
1_WebServiceFoundation.aspx
<%
@ Page Language
=
"
C#
"
AutoEventWireup
=
"
true
"
CodeFile
=
"
1_WebServiceFoundation.aspx.cs
"
Inherits
=
"
_1_WebServiceFoundation
"
%>
<!
DOCTYPE html PUBLIC
"
-//W3C//DTD XHTML 1.0 Transitional//EN
"
"
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
"
>
<
html xmlns
=
"
http://www.w3.org/1999/xhtml
"
>
<
head runat
=
"
server
"
>
<
title
>
Untitled Page
</
title
>
</
head
>
<
body
>
<
form id
=
"
form1
"
runat
=
"
server
"
>
<
asp:ScriptManager ID
=
"
ScriptManager1
"
runat
=
"
server
"
ScriptMode
=
"
Debug
"
>
<
Services
>
<
asp:ServiceReference Path
=
"
WebServiceFoundation.asmx
"
InlineScript
=
"
true
"
/>
//
InlineScript 默认为false
</
Services
>
</
asp:ScriptManager
>
<
input type
=
"
button
"
value
=
"
Get Random
"
onclick
=
"
getRandom()
"
/>
<
input type
=
"
button
"
value
=
"
Get Range Random
"
onclick
=
"
getRandom(50, 100)
"
/>
<
script language
=
"
javascript
"
type
=
"
text/javascript
"
>
function getRandom(minValue, maxValue)
...
{ //客户端提供一个类似重载的功能 if (arguments.length != 2 ) ... { Sample.WebServiceFoundation.GetRandom(getRandomSucceeded); } else ... { Sample.WebServiceFoundation.GetRangeRandom(minValue, maxValue, getRandomSucceeded); } }
function getRandomSucceeded(result)
...
{ alert(result); }
</
script
>
</
form
>
</
body
>
</
html
>
arguments:在JavaScript方法被调用时,都会初始化一个arguments这么一个对象,可当作一个数组类使用,但实际上是一个object,存放的就是这个方法调用时实际传入的参数
三、客户端访问PageMethod • 服务器端 – 只能在aspx页面中定义 – 只能是公开静态方法(static,无法在方法中访问页面控件 ) – 使用WebMethodAttribute标记 – ScriptManager的EnablePageMethods属性设为true (EnablePageMethods默认为false ) • 客户端 – 通过PageMethods.MethodName访问
DEMO 2 (客户端访问PageMethods基础 )
2_PageMethods.aspx
<%
@ Page Language
=
"
C#
"
AutoEventWireup
=
"
true
"
CodeFile
=
"
2_PageMethods.aspx.cs
"
Inherits
=
"
_2_PageMethods
"
%>
<!
DOCTYPE html PUBLIC
"
-//W3C//DTD XHTML 1.0 Transitional//EN
"
"
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
"
>
<
html xmlns
=
"
http://www.w3.org/1999/xhtml
"
>
<
head runat
=
"
server
"
>
<
title
>
Untitled Page
</
title
>
</
head
>
<
body
>
<
form id
=
"
form1
"
runat
=
"
server
"
>
<
asp:ScriptManager ID
=
"
ScriptManager1
"
runat
=
"
server
"
EnablePageMethods
= " true "
/>
<
input type
=
"
button
"
value
=
"
Get Current Time
"
onclick
=
"
getCurrentTime()
"
/>
<
script language
=
"
javascript
"
type
=
"
text/javascript
"
>
function getCurrentTime()
...
{ PageMethods.GetCurrentTime(getCurrentTimeSucceeded); }
function getCurrentTimeSucceeded(result)
...
{ alert(result); }
</
script
>
</
form
>
</
body
>
</
html
>
2_PageMethods.aspx.cs
using
System;
using
System.Data;
using
System.Configuration;
using
System.Collections;
using
System.Web;
using
System.Web.Security;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Web.UI.WebControls.WebParts;
using
System.Web.UI.HtmlControls;
using
System.Web.Services;
public
partial
class
_2_PageMethods : System.Web.UI.Page
...
{ protected void Page_Load( object sender, EventArgs e) ... { } [WebMethod] public static DateTime GetCurrentTime() ... { return DateTime.UtcNow; //得到一个UTC时间 } }
运行结果:
当点击button时将 弹出
Mon May 14 15:11:57 UTC+0800 2007
四、错误处理 • 调用时可以提供一个额外的错误回调函数 • 包括超时和服务器端抛出的异常 • 超时只能设置在WebService级别 – 或者设置在PageMethods对象上 – 无法在每个Method Call时指定(只能在Page中设定 ) • Sys.Net.WebServiceError (是个类) – timedout、message、exceptionType、stackTrace属性只有timeout为布尔型,其他都为字符型
DEMO 3 (错误处理 )
ErrorHandling.asmx
<%
@ WebService Language
=
"
C#
"
Class
=
"
ErrorHandling
"
%>
using
System;
using
System.Web;
using
System.Web.Services;
using
System.Web.Services.Protocols;
using
System.Web.Script.Services;
using
System.Threading; [WebService(Namespace
=
"
http://tempuri.org/
"
)] [WebServiceBinding(ConformsTo
=
WsiProfiles.BasicProfile1_1)] [ScriptService]
public
class
ErrorHandling : System.Web.Services.WebService
...
{ [WebMethod] public int GetDivision( int a, int b) ... { return a / b; // 当a b为浮点数时,b为0时,不返回错误,而是返回一个无穷大的数 } [WebMethod] public int Timeout() ... { Thread.Sleep( 5000 ); return 0 ; } }
3_ErrorHandling.aspx
<%
@ Page Language
=
"
C#
"
AutoEventWireup
=
"
true
"
CodeFile
=
"
3_ErrorHandling.aspx.cs
"
Inherits
=
"
_3_ErrorHandling
"
%>
<!
DOCTYPE html PUBLIC
"
-//W3C//DTD XHTML 1.0 Transitional//EN
"
"
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
"
>
<
html xmlns
=
"
http://www.w3.org/1999/xhtml
"
>
<
head runat
=
"
server
"
>
<
title
>
Untitled Page
</
title
>
</
head
>
<
body
>
<
form id
=
"
form1
"
runat
=
"
server
"
>
<
asp:ScriptManager ID
=
"
ScriptManager1
"
runat
=
"
server
"
>
<
Services
>
<
asp:ServiceReference Path
=
"
ErrorHandling.asmx
"
/>
</
Services
>
</
asp:ScriptManager
>
<
input type
=
"
button
"
value
=
"
getDivision
"
onclick
=
"
getDivision(5, 0)
"
/>
<
input type
=
"
button
"
value
=
"
timeout
"
onclick
=
"
timeout()
"
/>
<
script language
=
"
javascript
"
type
=
"
text/javascript
"
>
function getDivision(a, b)
...
{ ErrorHandling.GetDivision(a, b, null , failedCallback); // (a b)为传入的参数,null为正确运行以后回调处理的的方法名,此处为空,表示不处理。 // failedCallback为出错时处理的方法名 }
function timeout()
...
{ ErrorHandling.set_timeout( 2000 ); //当不设置超时时间时,将不作任何处理 ErrorHandling.Timeout( null , failedCallback); }
function failedCallback(error)
...
{ var message = String.format( " Timeout: {0} Message: {1} ExceptionType: {2} StackTrace: {3} " , error.get_timedOut(), error.get_message(), error.get_exceptionType(), error.get_stackTrace()); alert(message); }
</
script
>
</
form
>
</
body
>
</
html
>