0

我想在发布 HTTP Post 或 Get 请求后返回该对象。我可以在网络应用程序上做。现在我需要在 MS windows phone 应用程序中编写这个函数。我读了一些关于执行 HTTP Get 和 Post 请求的文章,但我仍然无法弄清楚。我想要一个帮助类来执行 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);
 }
4

2 回答 2

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 中,您实际上可以使用称为“等待”的东西,它可以让您按顺序执行操作而不会冻结它……但是对于 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();
}

享受!

于 2012-08-08T19:19:08.813 回答
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/

于 2012-08-09T03:48:34.170 回答