2
\$\begingroup\$

I have a WebPostRequest class which looks like this:

public class WebPostRequest
{
    public const string Success = "OK";

    private WebRequest _webRequest;
    private List<string> _paramsList;

    public WebPostRequest(string url)
    {
        try
        {
            _webRequest = WebRequest.Create(url);
        }
        catch (Exception)
        {
            throw;
        }
        _webRequest.Method = "POST";
        _webRequest.ContentType = "application/x-www-form-urlencoded";
        _paramsList = new List<string>();
    }

    public void Add(string key, string value)
    {
        _paramsList.Add(String.Format("{0}={1}", key, HttpUtility.UrlEncode(value)));
    }

    public void UploadPdf(string postKey, string name, params UserControl[] userControls)
    {
        string fileName = FileHelper.GetTimestampedName(name, "pdf");
        string filePath = PdfHelper.Save(fileName, userControls);
        FtpHelper.UploadFile(filePath);
        this.Add(postKey, fileName);
    }

    public void UploadImage(string postKey, string name, Image image)
    {
        if (image != null)
        {
            string fileName = FileHelper.GetTimestampedName(name, "jpg");
            FtpHelper.UploadFile(fileName, image.ToByteArray());
            this.Add(postKey, fileName);
        }
    }

    public string GetResponse()
    {
        // Build a string containing all the parameters
        string parameters = String.Join("&", _paramsList.ToArray());
        _webRequest.ContentLength = parameters.Length;

        try
        {
            // Write the parameters into the request
            using (StreamWriter streamWriter = new StreamWriter(_webRequest.GetRequestStream()))
            {
                streamWriter.Write(parameters);
            }

            // Execute the query
            HttpWebResponse httpWebResponse = (HttpWebResponse)_webRequest.GetResponse();
            StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream());
            return streamReader.ReadToEnd();
        }
        catch (Exception)
        {
            throw;
        }
    }
}

The WebPostRequest class uses a WebRequest object to POST to a web server and get the response.

The class is used like this:

bool success = false;
try
{
    WebPostRequest webPostRequest = new WebPostRequest(url);

    webPostRequest.Add("key_1", "value_1");
    webPostRequest.Add("key_2", "value_2");

    webPostRequest.UploadPdf("key_3", "pdf_name_1", userControl1);
    webPostRequest.UploadPdf("key_4", "pdf_name_2", userControl2);

    webPostRequest.UploadImage("key_5", "picture_name_1", image1);
    webPostRequest.UploadImage("key_6", "picture_name_1", image2);

    string response = webPostRequest.GetResponse();
    if (response != WebPostRequest.Success)
    {
        throw new Exception(response);
    }
    success = true;
}
catch (Exception ex)
{
    //display error messaage
}
if (success)
{
    //display success message
}

What i would like to do is add a window to display a status message and a progress bar (with marquee style). The window needs to be displayed from the WebPostRequest class, because this class is used in multiple locations in the app. The uploading tasks which may take a long time need to be executed on a different thread so that the UI thread remains responsive. Note that all the files need to be uploaded before the POST is made, so the GetResponse method needs to wait for the uploading tasks to finish. Note also that the helper methods can throw errors which are handled outside the WebPostRequest class.

What tips/suggestions can you give me? Any idea is appreciated.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I would not show any UI from WebPostRequest. For a fast solution you can just wrap the whole upload part and provide some sort of a listener whose methods will be called to notify about progress.

Thus WebPostRequest will not know nothing about UI layer. UI will not be blocked and be able to track upload progress.

Here's a C#-like pseudo code that illustrates what I mean:

class ProgressListener
{
    public void OnProgress(OperationContext)
    {
        //notiy UI in the thread-safe way -> use Control.Invoke for Windows Forms
    }

    public void OnFinish(OperationContext)
    {
        //show success message in UI
    }

    public void OnError(OperationContext)
    {
        //show detailed error message in UI
    }
}

//on UI class
void PerformUpload()
{

    ProgressListener listener = new ProgressListener(Form f);

    Thread thread = new Thread(() =>
    {
        try
        {
            try
            {
                WebPostRequest webPostRequest = new WebPostRequest(url);
                webPostRequest.Add("key_1", "value_1");
                webPostRequest.Add("key_2", "value_2");

                webPostRequest.UploadPdf("key_3", "pdf_name_1", userControl1);

                listener.OnProgress( /*operaton context*/)

                webPostRequest.UploadPdf("key_4", "pdf_name_2", userControl2);

                listener.OnProgress( /*operaton context*/)
                webPostRequest.UploadImage("key_5", "picture_name_1", image1);

                listener.OnProgress( /*operaton context*/)
                webPostRequest.UploadImage("key_6", "picture_name_1", image2);

                listener.OnProgress( /*operaton context*/)

                string response = webPostRequest.GetResponse();
                if (response != WebPostRequest.Success)
                {
                    listener.OnProgress( /*operaton context*/)

                    throw new Exception(response);
                }
                success = true;

                listener.OnFinish( /*operaton context*/)
            }
            catch (Exception ex)
            {
                listener.OnError( /*operaton context*/)
                //display error messaage
            }       
        }
        catch(Exception ex)
        {
            listener.OnError( /*operaton context*/)
            //logging
        }
    });

    thread.Name = "uploader";
    thread.Start();
}
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.