Hello World
Spiga

客户端访问Web Service方法的一个细节

2007-07-23 22:02 by 老赵, 11880 visits

之前遇到一个要求,需要能够取消一个正在进行中的Web Service。这也是我第一次遇到这个功能,不过不难,我想。既然ASP.NET AJAX的客户端与服务器端通信完全通过Microsoft AJAX Library的异步通信层进行,那么我们只要得到正在请求Web Service的Sys.Net.WebRequest对象,调用其abort方法就可以了。但是究竟应该如何得到这个对象呢?于是我粗略地阅读了一下代码。

首先假设有如下的Web Service方法定义(DemoService.asmx):

[ScriptService]
public class DemoService  : System.Web.Services.WebService
{
    [WebMethod]
    public string DemoMethod()
    {
        return "Hello World";
    }    
}

访问DemoService.asmx/jsdebug(或者将其使用ScriptManager引用到页面中之后)就能够得到如下的代理(片断、经过排版)类。

var DemoService = function()
{
    DemoService.initializeBase(this);
    this._timeout = 0;
    this._userContext = null;
    this._succeeded = null;
    this._failed = null;
}
DemoService.prototype =
{
    DemoMethod:function(succeededCallback, failedCallback, userContext)
    {
        return this._invoke(
            DemoService.get_path(),
            'DemoMethod',
            false,
            {},
            succeededCallback,
            failedCallback,
            userContext);
    }
}
DemoService.registerClass('DemoService',Sys.Net.WebServiceProxy);
...

显然,这个代理类继承了Sys.Net.WebServiceProxy类,于是我就把目光转向了其中的_invoke方法:

function Sys$Net$WebServiceProxy$_invoke(
    servicePath, methodName, useGet, params, onSuccess, onFailure, userContext) {

    // validation omitted
    ...
    
    return Sys.Net.WebServiceProxy.invoke(
        servicePath,
        methodName,
        useGet,
        params,
        onSuccess,
        onFailure,
        userContext,
        this.get_timeout());
}

这下又将操作委托给了Sys.Net.WebServiceProxy.invoke静态方法,继续看代码:

Sys.Net.WebServiceProxy.invoke = function Sys$Net$WebServiceProxy$invoke(
    servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, timeout) {

    // validation omitted
    ...

    // Create a web request to make the method call
    var request = new Sys.Net.WebRequest();

    // preparing request omitted
    ...

    request.invoke();

    function onComplete(response, eventArgs) {
        // method body omitted
    }

    return request;
}

嗨,这不就是我所需要的Sys.Net.WebRequest对象吗?原来想要得到这个对象那么简单,于是我就写下了下面的代码:

var request = DemoService.DemoMethod(onComplete);

然后在必要时:

request.abort();

执行,出现了错误:request为undefined,为什么DemoMethod方法调用没有返回request对象?跟踪了代码之后,不大不小地晕了一下,原来问题出在这里:

DemoService._staticInstance = new DemoService();
...
DemoService.DemoMethod = function(onSuccess,onFailed,userContext)
{
    DemoService._staticInstance.DemoMethod(onSuccess,onFailed,userContext);
}

虽然早就知道Web Service代理会在类上创建一个Singleton对象,并且创建静态方法再委托给那个实例上的相应方法,却一直没有意识到这个细节。在上面的静态方法中,居然是直接调用了DemoMethod方法,却没有将结果返回出来,真让我哭笑不得了一下。

不过问题时非常容易解决的,只要使用如下的方式在客户端调用WebService方法就可以了:

var request = DemoService._staticInstance.DemoMethod(onComplete);

不过这个做法似乎……有些奇怪?那么您也可以这样:

var demoService = new DemoService();
var request = demoService.DemoMethod(onComplete);

在这里,重新创建一个demoService对象似乎有些多余,不过在某些时候也是非常有用的做法。例如,您需要将操作分为两类,一类的超时时间为5秒,而另一类为10秒,因此您就可以创建两个代理对象,分别设置不同的超时时间。因为超时时间我们只能在Service的级别上设置,而不能在调用方法时指定。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

35 条回复

  1. zzz[未注册用户]
    *.*.*.*
    链接

    zzz[未注册用户] 2007-07-23 23:37:00

    沙发。。。。
    支持老赵。。。。

  2. 若寒
    *.*.*.*
    链接

    若寒 2007-07-23 23:58:00

    写得太好了.
    谢谢!

  3. long[未注册用户]
    *.*.*.*
    链接

    long[未注册用户] 2007-07-24 08:15:00

    挤进前10

  4. blue[未注册用户]
    *.*.*.*
    链接

    blue[未注册用户] 2007-07-24 08:52:00

    加油啊老赵同志!

  5. 淡泊江湖
    *.*.*.*
    链接

    淡泊江湖 2007-07-24 09:28:00

    笔耕不辍,UP!

  6. Anders Liu
    *.*.*.*
    链接

    Anders Liu 2007-07-24 09:39:00

    漂亮!支持老赵

  7. 老刘.
    *.*.*.*
    链接

    老刘. 2007-07-24 10:07:00

    :)

  8. 一帆(老鼠粮仓之路)
    *.*.*.*
    链接

    一帆(老鼠粮仓之路) 2007-07-24 10:08:00

    一个很不错的小伙啊

  9. Leepy
    *.*.*.*
    链接

    Leepy 2007-07-24 10:58:00

    好细致啊,老赵!

  10. 老赵
    admin
    链接

    老赵 2007-07-24 11:07:00

    @Leepy
    正好遇到了吧,其实我觉得这样的问题价值不大。

  11. 老赵
    admin
    链接

    老赵 2007-07-24 11:07:00

    @若寒
    @zzz
    @淡泊江湖
    @Anders Liu
    @老刘.
    @一帆(老鼠粮仓之路)
    谢谢支持:)

  12. xiao_p
    *.*.*.*
    链接

    xiao_p 2007-07-24 12:03:00

    对老赵同志的追捧要适可而止了哈,我们不能过度崇拜 :P :-)

  13. zzzz[未注册用户]
    *.*.*.*
    链接

    zzzz[未注册用户] 2007-07-24 13:30:00

    绝不过度崇拜。
    只是崇拜过度而已!

  14. volnet(可以叫我大V)
    *.*.*.*
    链接

    volnet(可以叫我大V) 2007-07-24 13:58:00

    怎么所有的评论都是对老赵的追捧啊~呵呵,社区不提倡个人崇拜噢~
    老赵我支持你~~~~·晕死~

  15. bighope
    *.*.*.*
    链接

    bighope 2007-07-24 15:34:00

    老赵本家哦,支持,继续向你学习!

  16. 流言蜚语
    *.*.*.*
    链接

    流言蜚语 2007-07-24 16:47:00

    不顶,对不起党国!更对不起楼上这么多哥们

  17. 老赵
    admin
    链接

    老赵 2007-07-24 17:49:00

    我说……好像夸张了一点,呵呵……

  18. 刚刚
    *.*.*.*
    链接

    刚刚 2007-07-24 17:56:00

    呵呵,确实都很夸张,从我这个评论往上看和往下看(包括我的评论“唯一”词组的前部分),唯一不夸张的就是老赵的随笔内容了,真实可信、实用性高、文采流畅,非常有用哦!
    没收了……

  19. Cat Chen[未注册用户]
    *.*.*.*
    链接

    Cat Chen[未注册用户] 2007-07-24 22:24:00

    原来ASP.NET AJAX的RTM还是那么多bug要人手阅读代码才能处理啊……CTP的时候这样做还是很有乐趣的事情,RTM的话就会让人觉得有点不可靠了。

  20. 老赵
    admin
    链接

    老赵 2007-07-25 00:01:00

    @Cat Chen
    我在想是不是随3.5的发布会修正这一点.

  21. winnerzone
    *.*.*.*
    链接

    winnerzone 2007-07-25 10:10:00

    看完之后再看标题才知道终于是干什么了的.收藏了.

  22. 么么茶
    *.*.*.*
    链接

    么么茶 2007-07-25 12:49:00

    哎~~.NET确实是问题多多,什么时候老赵能结合篇Asp.NET Ajax + Cache 的文章吗,搞来搞去也搞不妥?

  23. 老赵
    admin
    链接

    老赵 2007-07-25 13:36:00

    @么么茶
    嗯?Asp.NET Ajax + Cache是什么意思?

  24. 4kapple
    *.*.*.*
    链接

    4kapple 2007-07-25 16:33:00

    Cache 为咔嚓,就是咔嚓一声,脖子断了,问题搞定了.
    Asp.NET Ajax + Cache就是说老赵同志写一篇文章就将asp.net这点玩意搞定了!
    呵呵~

  25. 孟海86[未注册用户]
    *.*.*.*
    链接

    孟海86[未注册用户] 2007-08-18 02:59:00

    技术是被问题逼出来的……

  26. mengye[未注册用户]
    *.*.*.*
    链接

    mengye[未注册用户] 2007-08-25 11:37:00

    问一个js与webservice或pageMethod方法执行顺序的问题,我有一个js方法:
    function checkStorage(proId,isComepage)
    {
    var rV="0";
    PageMethods.storageCheck(proId,getValue)
    function getValue(result)
    {
    rV=result;
    }
    if(rV=="0")
    return true;
    else
    return confirm(rV);
    }
    方法的功能是当PageMethods.storageCheck返回的值不是“0”的话就执行return confirm(rV);很显然这段代码不达到预期的效果,在还没有等PageMethods.storageCheck执行完返回值就已经执行了下面的代码,结果rV还是="0",不用说你也知道我的问题了,因为checkStorage是通过客户端的按钮触发的,无法通过为AJAX 请求添加客户端结束事件的方法解决执行顺序的问题,@Jeffrey Zhao 有没有解决等执行完pageMethod方法才执行js脚本的办法,谢谢了!

  27. 老赵
    admin
    链接

    老赵 2007-08-25 20:06:00

    @mengye
    没有。使用Callback的异步调用有其特殊的编程方式,因为是做不到阻塞的。

  28. mengye[未注册用户]
    *.*.*.*
    链接

    mengye[未注册用户] 2007-08-27 09:41:00

    郁闷了,看来我只能改程序了,谢谢@Jeffrey Zhao

  29. horsefaced[未注册用户]
    *.*.*.*
    链接

    horsefaced[未注册用户] 2007-08-31 14:49:00

    在实际中有遇到这种事,就是调用httpRequest的abort方法,会在某些机子上发出没有权限这种错误,不知道博主是否有遇到过。

  30. Halie[未注册用户]
    *.*.*.*
    链接

    Halie[未注册用户] 2007-09-10 16:43:00

    就算不认识,也得顶一下.

  31. xxxxxxxx[未注册用户]
    *.*.*.*
    链接

    xxxxxxxx[未注册用户] 2007-12-10 17:34:00

    唉,看不懂,,

  32. Allan Chan
    *.*.*.*
    链接

    Allan Chan 2007-12-29 10:41:00

    看不太懂,请问下如何得到WebService的代理代码啊?能说详细点吗?谢谢老赵。

  33. Arron[未注册用户]
    *.*.*.*
    链接

    Arron[未注册用户] 2008-01-25 09:25:00

    我有个问题想请教一下,在asp.net ajax调用web service过程中,如何让javascript对象以xml格式传输到服务端,因为我发现默认是使用json格式

  34. 老赵
    admin
    链接

    老赵 2008-01-25 10:49:00

    @Arron
    如果客户端要用XML传到服务器端似乎没有什么好办法。
    建议WebMethod的参数用String,然后再服务器端转成XML。

  35. AlexLiu
    *.*.*.*
    链接

    AlexLiu 2008-09-05 08:32:00

    新手问一句,开始学习从webservice,.net remoting .....学起呢。还是可以直接wcf学习,因为听说wcf集成了blablabla。。。谢谢。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我