想要在MS窗口手机上的BeginGetRespone之后返回对象

时间:2012-08-08 18:44:01

标签: windows-phone-7

我想在发布HTTP Post或Get请求后返回该对象。我可以在网络应用程序上做。现在我需要在MS Windows Phone应用程序中编写此功能。我读了一些关于执行HTTP Get和Post Request的文章,但我仍然无法弄明白。我想有一个帮助类来执行Web请求并返回对象,就像我在Web应用程序上一样。我的Windows应用程序使用MVVM模式。 web请求将由viewmodel调用。如何重载BeginGetResponse以返回对象而不是IAsyncResult?有人会给我链接或示例来指导我。提前致谢。

Web应用程序上有旧代码

public static T GetData<T>(Uri relativeUri)
    {
        var request = CreateRequest(relativeUri);
        HttpWebResponse r;          

        try
        {
            r = (HttpWebResponse)request.GetResponse();                 
            return Deserializer<T>(r.GetResponseStream());
        }
        catch (WebException webex)
        {
            HttpWebResponse webResp = (HttpWebResponse)webex.Response;            
            setSessionError(webResp.GetResponseStream());

        }

        return Deserializer<T>(request.GetResponse().GetResponseStream());
    }


public static T Deserializer<T>(Stream s)
    {
        //Get results   
        var ser = new DataContractSerializer(typeof(T));
        var reader = XmlDictionaryReader.CreateTextReader(s,
            new System.Xml.XmlDictionaryReaderQuotas());
        ser = new DataContractSerializer(typeof(T));
        var deserializedItem = (T)ser.ReadObject(reader, true);
        reader.Close();
        return deserializedItem;
    }

我想做那样的事情:

public static T GetData<T>(Uri relativeUri)
    {
        var request = CreateRequest(relativeUri);
        Stream ResponseStream;
       request.BeginGetResponse(ReadCallback, request, ResponseStream);
       return Deserializer<T>(ResponseStream);
 }

2 个答案:

答案 0 :(得分:0)

如果不使用IAsyncResults,则无法执行此操作。你有两个选择,WebClient和HttpWebRequest ......

WebClient wc = new WebClient();
wc.DownloadStringCompleted += delegate { //do something };
wc.DownloadStringAsync(new Uri("http://website.com"));

或者您可以使用HttpWebRequest,它具有更多功能,但使用起来有点困难。

我建议像你一样创建一个帮助器类,并为它添加事件处理程序。事件处理程序将返回您的结果。这是一个样本。

public static event EventHandler CompletedDownload;

public static void StartGetData()
{
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://website.com");
    req.Method = "GET"; //or POST
    req.ContentType = "application/x-www-form-urlencoded";

    req.BeginGetRequestStream(GetRequestStreamCompleted, req);
}

//You can send data through this method
public static void GetRequestStreamCompleted(IAsyncResult result)
{
    HttpWebRequest req = (HttpWebRequest)result.AsyncState;
    var stream = req.EndGetRequestStream(result);

    byte[] byteData = Encoding.UTF8.GetBytes("u=" + loginData.Username + "&p=" + loginData.Password);

    stream.Write(byteData, 0, byteData.Length);
    stream.Close();

    request.BeginGetResponse(GetResponseCompleted, request);
}

public static void GetResponseCompleted(IAsyncResult result)
{
    HttpWebRequest request = (HttpWebRequest)result.AsyncState;
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);

    Stream stream = response.GetResponseStream();

    //Now trigger your CompletedDownload event, sending the deserialized data
    if (CompletedDownload != null)
        CompletedDownload(Deserializer(stream), new EventArgs());
}

然后在调用下载的代码中,订阅CompletedDownload。在对象发送者中,您将获得反序列化的数据(您必须将其强制转换)。然后只需调用StartGetData()!

编辑:这是您在主要数据中调用的内容,因为您不确定...

public partial class MainPage : PhoneApplicationPage
{
    ServiceHelper.CompletedDownload += new EventHandler(ServiceHelper_CompletedDownload);

    ServiceHelper.StartGetData();
}

void ServiceHelper_CompletedDownload(object sender, EventArgs e)
{
    var q = sender as List<QueueItem>;

    //do the rest of your work here.



    //if you need to update something on the UI, you MUST call the dispatcher
    since this will be coming from a background thread... you would do this...

    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(delegate
    {
        textBoxTitle.Text = q;
        MessageBox.Show("Download finished!");
    });
}

这有意义吗?当您的服务助手完成下载后,它将调用CompletedDownload事件。您不能简单地按顺序执行此操作并强制下载立即返回某些内容的原因是因为这会冻结您的应用程序直到下载完成。

在Windows 8和WP8中,你实际上可以使用一个名为“await”的东西,它可以让你按顺序做事而不会冻结它......但对于WP7,你必须使用这些IAsyncResults和回调方法

顺便说一句,对于事件处理程序,您可以使用多种方法...以下是另外两种方法:

public partial class MainPage : PhoneApplicationPage
{
    ServiceHelper.CompletedDownload += delegate
    {
        string answer = "I rock";
    };

    ServiceHelper.StartGetData();
}

或者另一个。这两种方法都可以让您完全访问在当前方法中定义的局部变量。第二个方法为您提供了从事件处理程序访问对象发送方和EventArgs e的优势。

public partial class MainPage : PhoneApplicationPage
{
    ServiceHelper.CompletedDownload += (sender, e) =>
    {
        string answer = "I rock";
    };

    ServiceHelper.StartGetData();
}

享受!

答案 1 :(得分:0)

您可以尝试异步CTP包。 http://msdn.microsoft.com/en-us/vstudio/async.aspx 或使用EX可以很容易。

女士已经实现了C#5,因此它将支持异步并等待为此做好工作。

http://reedcopsey.com/2010/10/28/c-5-async-part-1-simplifying-asynchrony-that-for-which-we-await/