Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6747581
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T12:27:40+00:00 2026-05-26T12:27:40+00:00

fellow devs! I have a class for posting to website using a POST or

  • 0

fellow devs!

I have a class for posting to website using a POST or GET and read the response. It’s all Async now and doesn’t cause the UI to hang.

I need to upgrade it to handle cancellation now. All the Async methods being used are NOT accepting the cancellation token. I need to understand why and what are my alternatives. If its possible, should i create the CancellationTokenSource object within the class or parametrize it from the UI?

Secondly, I need to expose the progress of the PostData() method. How would I do that?

The class:

using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using System.Collections.Generic;
using RESTClient.Core.UploadFile;
using System.Threading;

namespace RESTClient.Core {

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

        #region Backing Store
        private string _URL = string.Empty;
        private NameValueCollection _PostValues = new NameValueCollection();
        private PostTypeEnum _PostType = 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() {
            _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) {
            _PostValues = values;
        }
        #endregion

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

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

        /// <summary>
        /// Gets or sets the type of action to perform against the url.
        /// </summary>
        public PostTypeEnum Type {
            get {
                return _PostType;
            }
            set {
                _PostType = 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 < _PostValues.Count; i++) {
                EncodeAndAddItem(ref parameters, _PostValues.GetKey(i), _PostValues[i]);
            }
            string result = await PostData(_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) {
            _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) {
            _PostValues = 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 (_PostType == PostTypeEnum.POST) {
                Uri uri = new Uri(url);
                request = WebRequest.Create(uri) as HttpWebRequest;
                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 = WebRequest.Create(uri) as HttpWebRequest;
                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();
                    }
                }
            }
        }

        /// <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));
        }

        public async void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {
            //log.Debug(string.Format("Uploading {0} to {1}", file, url));
            string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
            byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

            HttpWebRequest wr = WebRequest.Create(url) as HttpWebRequest;
            wr.ContentType = "multipart/form-data; boundary=" + boundary;
            wr.Method = "POST";
            wr.KeepAlive = true;
            wr.Credentials = CredentialCache.DefaultCredentials;

            Stream rs = await wr.GetRequestStreamAsync();

            string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
            foreach (string key in nvc.Keys) {
                await rs.WriteAsync(boundarybytes, 0, boundarybytes.Length);
                string formitem = string.Format(formdataTemplate, key, nvc[key]);
                byte[] formitembytes = Encoding.UTF8.GetBytes(formitem);
                await rs.WriteAsync(formitembytes, 0, formitembytes.Length);
            }
            await rs.WriteAsync(boundarybytes, 0, boundarybytes.Length);

            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
            string header = string.Format(headerTemplate, paramName, file, contentType);
            byte[] headerbytes = Encoding.UTF8.GetBytes(header);
            rs.WriteAsync(headerbytes, 0, headerbytes.Length);

            FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
            byte[] buffer = new byte[4096];
            int bytesRead = 0;
            while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) != 0) {
                await rs.WriteAsync(buffer, 0, bytesRead);
            }
            fileStream.Close();

            byte[] trailer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
            await rs.WriteAsync(trailer, 0, trailer.Length);
            rs.Close();

            WebResponse wresp = null;
            try {
                wresp = await wr.GetResponseAsync();
                Stream stream2 = wresp.GetResponseStream();
                StreamReader reader2 = new StreamReader(stream2);
                //log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
            }
            catch (Exception ex) {
                //log.Error("Error uploading file", ex);
                if (wresp != null) {
                    wresp.Close();
                    wresp = null;
                }
            }
            finally {
                wr = null;
            }

            /**
            NameValueCollection nvc = new NameValueCollection();
            nvc.Add("id", "TTR");
            nvc.Add("btn-submit-photo", "Upload");
            HttpUploadFile("http://your.server.com/upload",          @"C:\test\test.jpg", "file", "image/jpeg", nvc);        
            **/
        }

        public async Task<String> ExecutePostRequest(Uri url, Dictionary<string, string> postData, FileInfo fileToUpload, string fileMimeType, string fileFormKey) {
            HttpWebRequest request = WebRequest.Create(url.AbsoluteUri) as HttpWebRequest;
            request.Method = "POST";
            request.KeepAlive = true;

            String boundary = Utility.CreateFormDataBoundary();
            request.ContentType = "multipart/form-data; boundary=" + boundary;

            Stream requestStream = await request.GetRequestStreamAsync();
            postData.WriteMultipartFormData(requestStream, boundary);

            if (fileToUpload != null) {
                //TODO: Need async here...
                fileToUpload.WriteMultipartFormData(requestStream, boundary, fileMimeType, fileFormKey);
            }

            byte[] endBytes = Encoding.UTF8.GetBytes("--" + boundary + "--");

            await requestStream.WriteAsync(endBytes, 0, endBytes.Length);
            requestStream.Close();

            using (WebResponse response = await request.GetResponseAsync()) {
                using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
                    return await reader.ReadToEndAsync();
                }
            }
        }

    }

}

Note: There are three method in the end that are for file uploading. I still need to figure then out and before I do, I need to understand the Cancellation and Progress reporting.

Related question Async CTP for a PostSubmitter

Any help would be much appreciated.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T12:27:41+00:00Added an answer on May 26, 2026 at 12:27 pm

    You support progress and cancellation by taking IProgress<T> and CancellationToken parameters.

    For cancellation, periodically check whether cancellation has been requested by calling CancellationToken.ThrowIfCancellationRequested. For more information, see Cancellation on MSDN.

    For progress, you need to first decide what kind of “progress” makes sense. E.g., if “progress” is just a number of bytes transferred, then you can use IProgress<int>. Once you’ve decided on your progress type, then call IProgress<T>.Report to report the progress. There are two things to be aware of for IProgress<T>:

    1. The IProgress<T> parameter may be null.
    2. IProgress<T>.Report operates asynchronously. This means that you must either: A) use a value type for T in IProgress<T>; B) perform a deep copy of every T object passed to IProgress<T>.Report; or C) create a new T object each time you call IProgress<T>.Report.
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Hi all fellow programmer I'd like to have a separate js file for each
Hi fellow stackers... I have an ASP.NET 3.5 app using forms authentication. I would
Fellow Coders, so far I have been using the CI url helper to build
Hello fellow programmers I have been searching the internet for a few days now
Fellow coders, I have asked this question before but did not get a conclusive
Hello fellow programmers, I am building a website and i read about sitemap.xml, but
hello fellow java developers. I'm having a bit of an issue here. I have
A fellow developer changed all the values in the userid column of table map
Avast there fellow programmers! I have the following problem: I have two rectangles overlapping
Hello Fellow Computer People! Anyone willing to help will have my gratitude ;) Just

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.