Windows Phone 7下动态调用Web Service的异步实现

2010-12-23 13:55 by hackerzhou

前两天写了篇关于.NET 2.0下如何不用Service References从而实现异步的动态Web Service调用。其实本来是写好之后看看是否能直接在Windows Phone 7上跑的,结果发现Win Phone下的Silverlight中的HttpWebRequest的用法有些独特,GetRequestStream和GetResponse都变成了异步操作,代码也需要做略微的调整。

代码链接如下:
1. CallCompletedEventArgs.cs
2. WebServicesUtil.cs

事件框架和上一篇差不多,差别如下:

1.由于GetRequestStream变成异步操作,因此需要在BeginCall的时候执行BeginGetRequestStream,定义一个回调函数(GetRequestStreamCallBack),指示得到了RequestStream了之后该进行的操作。

public void BeginCall(String method, Encoding encoding, params KeyValuePair<String, String>[] para)
{
    if (ServiceUrl == null || method == null)
    {
        throw new Exception("Args Error!");
    }
    String url = ServiceUrl + "/" + method;
    HttpWebRequest req = GetHttpWebRequest(url, "POST", Cookie);
    if (para != null)
    {
        foreach (KeyValuePair<String, String> p in para)
        {
            buf.Append(p.Key + "=" + p.Value + "&");
        }
    }
    req.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallBack), req);
}

2.得到了RequestStream后进入GetRequestStreamCallBack回调函数,往RequestStream里写入POST的数据,同时执行BeginGetResponse,并定义一个回调函数GetResponseStreamCallBack。

public void GetRequestStreamCallBack(IAsyncResult asyncResult)
{
    HttpWebRequest req = (HttpWebRequest)asyncResult.AsyncState;
    Stream requestStream = req.EndGetRequestStream(asyncResult);
    using (StreamWriter writer = new StreamWriter(requestStream))
    {
        String str = buf.ToString();
        //if (str.EndsWith("&"))
        //{
        //    str = str.Substring(0, Math.Max(0, str.Length - 1));
        //}
        writer.Write(str);
        writer.Flush();
    }
    req.BeginGetResponse(new AsyncCallback(GetResponseStreamCallBack), req);
}

3.在GetResponseStreamCallBack中得到了服务器返回的Response,触发事件,整个异步操作完成

        public void GetResponseStreamCallBack(IAsyncResult asyncResult)
        {
            HttpWebRequest req = (HttpWebRequest)asyncResult.AsyncState;
            WebResponse response = req.EndGetResponse(asyncResult);
            using (Stream responseStream = response.GetResponseStream())
            {
                String result = GetStringFromStream(responseStream, Encoding);
                XDocument rootDoc = GetXDocumentFromXmlString(result);
                XDocument doc = GetXDocumentFromXmlString(HttpUtility.HtmlDecode(rootDoc.Root.Value));
                CallCompletedEventArgs e = new CallCompletedEventArgs(doc, null, false, null);
                if (CallCompleted != null)
                {
                    CallCompleted(this, e);
                }
            }
        }

需要说明的两点:

1.在回调事件中使用AsyncState来保存自己需要用到的对象。一开始我遇到了点困难,在于进入回调函数的时候,我拿不到原来的那个HttpWebRequest了,查了MSDN和网上的相关介绍,把HttpWebRequest在BeginGetRequestStream/BeginGetResponse的时候保存起来,在回调函数中可以通过AsyncState来获取保存的对象,执行相关的操作。

2.此例中由于GetRequestStream/GetResponse都是异步操作,而且GetResponse必须在GetRequestStream并且写入POST参数了以后调用,因此采用了回调函数中调用异步Begin操作的方法来实现两个异步操作捆绑成同步操作。

本文基于 署名 2.5 中国大陆 许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 hackerzhou 并包含 原文链接
发表评论

本文有 8 条评论

  1. 路人甲
    2014-06-05 17:34

    楼主,现在wp8.1了,你发的这个还能用不?顺带求两份的完整版,我看过一个demo用了webclient类,但是不会用。以前我使用request.Headers[]设置http头,KeyValuePair是不是也是这个作用啊?现在我需要设置http头,还需要post一个string,请问大神该怎么做。新手,十分感谢

  2. nick
    2014-02-10 18:25

    楼主你好,能发一份动态调用webserivce的demo给我吗?
    [email protected]
    谢谢!

  3. need help
    2013-12-31 10:11

    楼主你好,能否发一份动态调用webserivce服务的demo给我。万分感谢。急需。。
    hendrymc#vip.qq.com

  4. 我要完整demo
    2013-03-28 13:27

    楼主,有没有完整的demo啊,我最近做windows phone动态调用webservice啊,一点不会啊。想求个demo

    邮箱[email protected]

  5. 艾丝凡
    2012-06-24 13:33

    微软极度变态而垃圾的为webs调用,以前同步调用的方法完全不能用了,本来很好用的,不知道吃错什么药了,非要异步调用

  6. 路人乙
    2011-07-20 19:49

    楼主您好!我正在找windows phone 7实现异步获取webservice数据的方法,您那两个类文件链接失效了,能否将类文件或者示例代码发一份给我?kylin17#foxmail.com不胜感激!

    • hackerzhou
      2011-07-21 11:30

      因为之前清理过一次Google Code SVN,我回家之后再传到svn上,届时会发link给你。

发表评论