异步CTP的PostSubmitter [英] Async CTP for a PostSubmitter

查看:81
本文介绍了异步CTP的PostSubmitter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想建立一个REST客户端usign异步CTP。我是新来的CTP,因此,afetr通过一些在互联网上的例子去,我只是张贴(GET或POST)建立了一个CLAS。这里是类迄今:

 使用系统;
使用System.Collections.Specialized;
使用System.IO;
使用System.Net;
使用System.Text;
使用System.Threading.Tasks;
使用的System.Web;命名空间RESTClient.Core {    ///<总结>
    ///后数据提交到URL。
    ///< /总结>
    公共类PostSubmitter {        #地区的后备存储
        私人字符串m_url =的String.Empty;
        私人的NameValueCollection m_values​​ =新的NameValueCollection();
        私人PostTypeEnum m_type = PostTypeEnum.Get;
        #endregion        #区域构造
        ///<总结>
        ///默认构造函数。
        ///< /总结>
        公共PostSubmitter(){        }        ///<总结>
        ///构造函数接受一个url作为参数
        ///< /总结>
        ///< PARAM NAME =URL化合物其中后会提交到URL< /参数>
        公共PostSubmitter(字符串URL)
            : 这个() {
            m_url =网址;
        }        ///<总结>
        ///构造使URL和项目发布的设置。
        ///< /总结>
        ///< PARAM NAME =URL方式>的URL后< /参数>
        ///< PARAM NAME =值>对岗位的价值和LT; /参数>
        公共PostSubmitter(字符串URL,NameValueCollection中值)
            :这(URL){
            m_values​​ =值;
        }
        #endregion        #区域属性
        ///<总结>
        ///获取或设置链接直接提交帖子。
        ///< /总结>
        公共字符串URL {
            获得{
                返回m_url;
            }
            集合{
                m_url =价值;
            }
        }        ///<总结>
        ///获取或设置项目后的名称值集合。
        ///< /总结>
        公众的NameValueCollection PostItems {
            获得{
                返回m_values​​;
            }
            集合{
                m_values​​ =价值;
            }
        }        ///<总结>
        ///获取或设置行动打击的URL执行的类型。
        ///< /总结>
        公共PostTypeEnum类型{
            获得{
                返回m_type;
            }
            集合{
                m_type =价值;
            }
        }
        #endregion        ///<总结>
        ///帖子所提供的数据,以指定的URL。
        ///< /总结>
        ///<返回>将含有该职位的结果的字符串< /回报>
        公共异步任务<串GT;邮政(){
            StringBuilder的参数=新的StringBuilder();
            的for(int i = 0; I< m_values​​.Count;我++){
                烯codeAndAddItem(ref参数,m_values​​.GetKey(i)中,m_values​​ [I]);
            }
            字符串结果=等待的PostData(m_url,parameters.ToString());
            返回结果;
        }        ///<总结>
        ///帖子所提供的数据,以指定的URL。
        ///< /总结>
        ///< PARAM NAME =URL>该网址张贴上述< /参数>
        ///<返回>将含有该职位的结果的字符串< /回报>
        公共异步任务<串GT;邮政(字符串URL){
            m_url =网址;
            返回等待this.Post();
        }        ///<总结>
        ///帖子所提供的数据,以指定的URL。
        ///< /总结>
        ///< PARAM NAME =URL>该网址张贴上述< /参数>
        ///< PARAM NAME =值方式>的值后< /参数>
        ///<返回>将含有该职位的结果的字符串< /回报>
        公共异步任务<串GT;邮报(字符串URL,NameValueCollection中值){
            m_values​​ =值;
            返回等待this.Post(URL);
        }        ///<总结>
        ///帖子数据到指定的URL。请注意,这假定您已经url可连接codeD后的数据。
        ///< /总结>
        ///< PARAM NAME =POSTDATA方式>的数据发布< /参数>
        ///< PARAM NAME =URL>该网址张贴上述< /参数>
        ///<退货和GT;返回后的结果< /回报>
        私人异步任务<串GT;的PostData(URL字符串,字符串POSTDATA){
            HttpWebRequest的要求= NULL;
            如果(m_type == PostTypeEnum.Post){
                开放的我们的uri =新的URI(URL);
                请求=(HttpWebRequest的)WebRequest.Create(URI);
                request.Method =POST;
                request.ContentType =应用/的X WWW的形式urlen codeD;
                request.ContentLength = postData.Length;
                使用(流writeStream =等待request.GetRequestStreamAsync()){
                    UTF8Encoding编码=新UTF8Encoding();
                    字节[]字节= encoding.GetBytes(POSTDATA);
                    writeStream.Write(字节,0,bytes.Length);
                }
            }
            其他{
                开放的我们的uri =新的URI(URL + + POSTDATA?);
                请求=(HttpWebRequest的)WebRequest.Create(URI);
                request.Method =GET;
            }            字符串结果=的String.Empty;            使用(HttpWebResponse响应=(HttpWebResponse)等待request.GetResponseAsync()){
                使用(流responseStream = response.GetResponseStream()){
                    使用(StreamReader的readStream =新的StreamReader(responseStream,Encoding.UTF8)){
                        结果= readStream.ReadToEnd();
                    }
                }
            }            返回结果;
        }        ///<总结>
        ///恩codeS一个项目,它的广告字符串。
        ///< /总结>
        ///< PARAM NAME =baseRequest>在previously EN codeD数据< /参数>
        ///< PARAM NAME =DataItem的方式>的数据连接code< /参数>
        ///<收益方式> /回报>将包含旧数据和pviously的$ P $连接codeD数据&LT串;
        私人无效恩codeAndAddItem(参考StringBuilder的baseRequest,字符串键,字符串的DataItem){
            如果(baseRequest == NULL){
                baseRequest =新的StringBuilder();
            }
            如果(baseRequest.Length!= 0){
                baseRequest.Append(与&);
            }
            baseRequest.Append(键);
            baseRequest.Append(=);
            baseRequest.Append(HttpUtility.UrlEn code(DataItem的));
        }    }}

这是我如何使用它:

 私人无效ButtonSubmit_Click(对象发件人,EventArgs的发送){
        ButtonReset.Enabled = FALSE;
        TextResponse.Text =的String.Empty;
        TextResponse.Text + =开头...+ Environment.NewLine;        尝试{
            TextResponse.Text + = Task.Factory.StartNew(()=方式> PostSomeData()等待());
            //TextResponse.Text + = PostSomeData();
            TextResponse.Text + = Environment.NewLine;
            TextResponse.Text + =功能完成! + Environment.NewLine;
        }
        赶上(例外前){
            TextResponse.Text + =异常! + Environment.NewLine +消息:+ ex.Message + Environment.NewLine;
        }
        最后{
            ButtonReset.Enabled = TRUE;
            TextResponse.Text + =功能端!
        }
    }    私人异步任务<串GT; PostSomeData(){
        PostSubmitter后=新PostSubmitter();
        post.Url = TextURL.Text.Trim();        post.PostItems.Add(TextParam01.Text.Trim(),TextValue01.Text.Trim());
        post.PostItems.Add(TextParam02.Text.Trim(),TextValue02.Text.Trim());
        post.PostItems.Add(TextParam03.Text.Trim(),TextValue03.Text.Trim());
        post.PostItems.Add(TextParam04.Text.Trim(),TextValue04.Text.Trim());
        post.PostItems.Add(TextParam05.Text.Trim(),TextValue05.Text.Trim());
        post.PostItems.Add(TextParam06.Text.Trim(),TextValue06.Text.Trim());
        post.PostItems.Add(TextParam07.Text.Trim(),TextValue07.Text.Trim());
        post.PostItems.Add(TextParam08.Text.Trim(),TextValue08.Text.Trim());
        post.PostItems.Add(TextParam09.Text.Trim(),TextValue09.Text.Trim());
        post.PostItems.Add(TextParam10.Text.Trim(),TextValue10.Text.Trim());
        post.PostItems.Add(TextParam11.Text.Trim(),TextValue11.Text.Trim());
        post.PostItems.Add(TextParam12.Text.Trim(),TextValue12.Text.Trim());
        post.Type = PostTypeEnum.Post;        返回等待post.Post();
    }

时,并不像预期的行为。行 TextResponse.Text + = Task.Factory.StartNew(()=> PostSomeData()等待()); 高手越和我没有得到任何的异常,并在这里是生成的字符串:

开始时...
System.Threading.Tasks.Task
函数来完成!
截至功能!

现在,如果我使用一个帖子,我得到上面的后一个例外。挖掘异常透着的 500内部服务器错误

但是,如果我使用GET,没有任何反应。也不例外,一样的最终结果。

我在做的PostSubmitter类的东西了?

下面是UI投篮paramaeters:

问候。

更新#1
我已经修改UI上的点击事件也是如此。然而


  • 它只有PostType是的 GET 的工作。 POST无法工作。

  • 用户界面的挂起的,而操作持续

的修改:

 专用异步无效ButtonSubmit_Click(对象发件人,EventArgs的发送){
        ButtonReset.Enabled = FALSE;
        TextResponse.Text =的String.Empty;
        TextResponse.Text + =开头...+ Environment.NewLine;        尝试{
            TextResponse.Text + =等待PostSomeData();
            TextResponse.Text + = Environment.NewLine;
            TextResponse.Text + =功能完成! + Environment.NewLine;
        }
        赶上(例外前){
            TextResponse.Text + =异常! + Environment.NewLine +消息:+ ex.Message + Environment.NewLine;
        }
        最后{
            ButtonReset.Enabled = TRUE;
            TextResponse.Text + =功能端!
        }
    }


解决方案

您code只是部分异步的;在需要好好看看的PostData

在特别 ReadToEnd的必须是异步的:

 专用异步任务<串GT;的PostData(URL字符串,字符串POSTDATA)
{
  HttpWebRequest的要求= NULL;
  如果(m_type == PostTypeEnum.Post)
  {
    开放的我们的uri =新的URI(URL);
    请求=(HttpWebRequest的)WebRequest.Create(URI);
    request.Method =POST;
    request.ContentType =应用/的X WWW的形式urlen codeD;
    request.ContentLength = postData.Length;
    使用(流writeStream =等待request.GetRequestStreamAsync())
    {
      UTF8Encoding编码=新UTF8Encoding();
      字节[]字节= encoding.GetBytes(POSTDATA);
      等待writeStream.WriteAsync(字节,0,bytes.Length);
    }
  }
  其他
  {
    开放的我们的uri =新的URI(URL + + POSTDATA?);
    请求=(HttpWebRequest的)WebRequest.Create(URI);
    request.Method =GET;
  }  使用(HttpWebResponse响应=(HttpWebResponse)等待request.GetResponseAsync())
  使用(流responseStream = response.GetResponseStream())
  使用(StreamReader的readStream =新的StreamReader(responseStream,Encoding.UTF8))
  {
    返回等待readStream.ReadToEndAsync();
  }
}

这是除了使事件处理程序的异步,正如其他人提及。

I'm trying to build a REST Client usign Async CTP. I'm new to the CTP and hence, afetr going through a number of examples on the internet, I got a clas built for just posting (GET or POST). Here is the class so far:

using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace RESTClient.Core {

    /// <summary>
    /// Submits post data to a url.
    /// </summary>
    public class PostSubmitter {

        #region Backing Store
        private string m_url = string.Empty;
        private NameValueCollection m_values = new NameValueCollection();
        private PostTypeEnum m_type = PostTypeEnum.Get;
        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor.
        /// </summary>
        public PostSubmitter() {

        }

        /// <summary>
        /// Constructor that accepts a url as a parameter
        /// </summary>
        /// <param name="url">The url where the post will be submitted to.</param>
        public PostSubmitter(string url)
            : this() {
            m_url = url;
        }

        /// <summary>
        /// Constructor allowing the setting of the url and items to post.
        /// </summary>
        /// <param name="url">the url for the post.</param>
        /// <param name="values">The values for the post.</param>
        public PostSubmitter(string url, NameValueCollection values)
            : this(url) {
            m_values = values;
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the url to submit the post to.
        /// </summary>
        public string Url {
            get {
                return m_url;
            }
            set {
                m_url = value;
            }
        }

        /// <summary>
        /// Gets or sets the name value collection of items to post.
        /// </summary>
        public NameValueCollection PostItems {
            get {
                return m_values;
            }
            set {
                m_values = value;
            }
        }

        /// <summary>
        /// Gets or sets the type of action to perform against the url.
        /// </summary>
        public PostTypeEnum Type {
            get {
                return m_type;
            }
            set {
                m_type = value;
            }
        }
        #endregion

        /// <summary>
        /// Posts the supplied data to specified url.
        /// </summary>
        /// <returns>a string containing the result of the post.</returns>
        public async Task<String> Post() {
            StringBuilder parameters = new StringBuilder();
            for (int i = 0; i < m_values.Count; i++) {
                EncodeAndAddItem(ref parameters, m_values.GetKey(i), m_values[i]);
            }
            string result = await PostData(m_url, parameters.ToString());
            return result;
        }

        /// <summary>
        /// Posts the supplied data to specified url.
        /// </summary>
        /// <param name="url">The url to post to.</param>
        /// <returns>a string containing the result of the post.</returns>
        public async Task<String> Post(string url) {
            m_url = url;
            return await this.Post();
        }

        /// <summary>
        /// Posts the supplied data to specified url.
        /// </summary>
        /// <param name="url">The url to post to.</param>
        /// <param name="values">The values to post.</param>
        /// <returns>a string containing the result of the post.</returns>
        public async Task<String> Post(string url, NameValueCollection values) {
            m_values = values;
            return await this.Post(url);
        }

        /// <summary>
        /// Posts data to a specified url. Note that this assumes that you have already url encoded the post data.
        /// </summary>
        /// <param name="postData">The data to post.</param>
        /// <param name="url">the url to post to.</param>
        /// <returns>Returns the result of the post.</returns>
        private async Task<String> PostData(string url, string postData) {
            HttpWebRequest request = null;
            if (m_type == PostTypeEnum.Post) {
                Uri uri = new Uri(url);
                request = (HttpWebRequest)WebRequest.Create(uri);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = postData.Length;
                using (Stream writeStream = await request.GetRequestStreamAsync()) {
                    UTF8Encoding encoding = new UTF8Encoding();
                    byte[] bytes = encoding.GetBytes(postData);
                    writeStream.Write(bytes, 0, bytes.Length);
                }
            }
            else {
                Uri uri = new Uri(url + "?" + postData);
                request = (HttpWebRequest)WebRequest.Create(uri);
                request.Method = "GET";
            }

            string result = string.Empty;

            using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) {
                using (Stream responseStream = response.GetResponseStream()) {
                    using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8)) {
                        result = readStream.ReadToEnd();
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// Encodes an item and ads it to the string.
        /// </summary>
        /// <param name="baseRequest">The previously encoded data.</param>
        /// <param name="dataItem">The data to encode.</param>
        /// <returns>A string containing the old data and the previously encoded data.</returns>
        private void EncodeAndAddItem(ref StringBuilder baseRequest, string key, string dataItem) {
            if (baseRequest == null) {
                baseRequest = new StringBuilder();
            }
            if (baseRequest.Length != 0) {
                baseRequest.Append("&");
            }
            baseRequest.Append(key);
            baseRequest.Append("=");
            baseRequest.Append(HttpUtility.UrlEncode(dataItem));
        }

    }

}

And this is how I'm using it:

    private void ButtonSubmit_Click(object sender, EventArgs e) {
        ButtonReset.Enabled = false;
        TextResponse.Text = String.Empty;
        TextResponse.Text += "Begining..." + Environment.NewLine;

        try {
            TextResponse.Text += Task.Factory.StartNew(() => PostSomeData().Wait());
            //TextResponse.Text +=  PostSomeData();
            TextResponse.Text += Environment.NewLine;
            TextResponse.Text += "Function Done!" + Environment.NewLine;
        }
        catch (Exception ex) {
            TextResponse.Text += "Exception!" + Environment.NewLine + "Message: " + ex.Message + Environment.NewLine;
        }
        finally {
            ButtonReset.Enabled = true;
            TextResponse.Text += "Function Ended!";
        }
    }

    private async Task<String> PostSomeData() {
        PostSubmitter post = new PostSubmitter();
        post.Url = TextURL.Text.Trim();

        post.PostItems.Add(TextParam01.Text.Trim(), TextValue01.Text.Trim());
        post.PostItems.Add(TextParam02.Text.Trim(), TextValue02.Text.Trim());
        post.PostItems.Add(TextParam03.Text.Trim(), TextValue03.Text.Trim());
        post.PostItems.Add(TextParam04.Text.Trim(), TextValue04.Text.Trim());
        post.PostItems.Add(TextParam05.Text.Trim(), TextValue05.Text.Trim());
        post.PostItems.Add(TextParam06.Text.Trim(), TextValue06.Text.Trim());
        post.PostItems.Add(TextParam07.Text.Trim(), TextValue07.Text.Trim());
        post.PostItems.Add(TextParam08.Text.Trim(), TextValue08.Text.Trim());
        post.PostItems.Add(TextParam09.Text.Trim(), TextValue09.Text.Trim());
        post.PostItems.Add(TextParam10.Text.Trim(), TextValue10.Text.Trim());
        post.PostItems.Add(TextParam11.Text.Trim(), TextValue11.Text.Trim());
        post.PostItems.Add(TextParam12.Text.Trim(), TextValue12.Text.Trim());
        post.Type = PostTypeEnum.Post;

        return await post.Post();
    }

The behaviour is not quite as expected. The line TextResponse.Text += Task.Factory.StartNew(() => PostSomeData().Wait()); whiz-by and I get no exceptions and here is the resulting string:

Begining... System.Threading.Tasks.Task Function Done! Function Ended!

Now, if I'm using a POST, I get an exception after the above. Digging into the exception reveals a 500 Internal Server Error

However, if i'm using GET, nothing happens. No exception and just the same final result.

Am I doing something wrong in the PostSubmitter Class?

Here is the UI shot with the paramaeters:

Regards.

Update #1 I have modified the click event on the UI as well. However

  • It only works if the PostType is GET. POST is not working.
  • The UI hangs while the operation lasts

The modifications:

    private async void ButtonSubmit_Click(object sender, EventArgs e) {
        ButtonReset.Enabled = false;
        TextResponse.Text = String.Empty;
        TextResponse.Text += "Begining..." + Environment.NewLine;

        try {
            TextResponse.Text += await PostSomeData();
            TextResponse.Text += Environment.NewLine;
            TextResponse.Text += "Function Done!" + Environment.NewLine;
        }
        catch (Exception ex) {
            TextResponse.Text += "Exception!" + Environment.NewLine + "Message: " + ex.Message + Environment.NewLine;
        }
        finally {
            ButtonReset.Enabled = true;
            TextResponse.Text += "Function Ended!";
        }
    }

解决方案

Your code is only partially asynchronous; take a good look at PostData.

In particular, ReadToEnd needs to be asynchronous:

private async Task<String> PostData(string url, string postData)
{
  HttpWebRequest request = null;
  if (m_type == PostTypeEnum.Post)
  {
    Uri uri = new Uri(url);
    request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = postData.Length;
    using (Stream writeStream = await request.GetRequestStreamAsync())
    {
      UTF8Encoding encoding = new UTF8Encoding();
      byte[] bytes = encoding.GetBytes(postData);
      await writeStream.WriteAsync(bytes, 0, bytes.Length);
    }
  }
  else
  {
    Uri uri = new Uri(url + "?" + postData);
    request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "GET";
  }

  using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
  using (Stream responseStream = response.GetResponseStream())
  using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))
  {
    return await readStream.ReadToEndAsync();
  }
}

This is in addition to making your event handler asynchronous, as others have mentioned.

这篇关于异步CTP的PostSubmitter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆