/// <summary>
        /// Sends a message to a remote server asychronously.
        /// </summary>
        /// <param name="action">The action to perform.</param>
        /// <param name="request">The request to send to the server.</param>
        /// <param name="userState">Any user state data.</param>
        public virtual void SendMessageAsync(string action, ServerRequest request, object userState)
        {
            // Ensure that async is only called once (or once with the user state)
            lock (lockObject)
            {
                if (userState == null)
                {
                    if (isBusy) throw new InvalidOperationException();
                    isBusy = true;
                }
                else if (asyncOperations.ContainsKey(userState))
                {
                    if (asyncOperations.ContainsKey(userState)) throw new ArgumentException("Duplicate userState", "userState");
                }
            }

            // Initialise the web client
            WebClient client = new WebClient();
            client.UploadValuesCompleted += delegate(object sender, UploadValuesCompletedEventArgs e)
            {
                if (SendMessageCompleted != null)
                {
                    if ((e.Error != null) && !e.Cancelled)
                    {
                        // Convert the response into a response object
                        string response = Encoding.UTF8.GetString(e.Result);
                        Response result = XmlConversionUtil.ProcessResponse(response);

                        MessageReceivedEventArgs args = new MessageReceivedEventArgs(result, null, false, userState);
                        SendMessageCompleted(this, args);
                    }
                    else
                    {
                        MessageReceivedEventArgs args = new MessageReceivedEventArgs(null, e.Error, e.Cancelled, userState);
                        SendMessageCompleted(this, args);
                    }
                }
                CompleteAsyncCall(userState);
            };
            lock (lockObject)
            {
                asyncOperations.Add(userState ?? string.Empty, client);
            }

            try
            {
                // Generate the target URI
                Uri targetAddress = GenerateTargetUri(request);

                // Build the request and send it
                NameValueCollection formData = new NameValueCollection();
                formData.Add("action", action);
                formData.Add("message", request.ToString());
                client.UploadValuesAsync(targetAddress, "POST", formData);
            }
            catch (Exception error)
            {
                if (SendMessageCompleted != null)
                {
                    MessageReceivedEventArgs args = new MessageReceivedEventArgs(null, error, false, userState);
                    SendMessageCompleted(this, args);
                }
                CompleteAsyncCall(userState);
            }
        }
 public void TriggerSendMessageCompleted(Response response, Exception error, bool cancelled, object userState)
 {
     var args = new MessageReceivedEventArgs(response, error, cancelled, userState);
     this.SendMessageCompleted(this, args);
 }
 /// <summary>
 /// Passes on the <see cref="SendMessageCompleted"/> event.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="args"></param>
 private void PassOnSendMessageCompleted(object sender, MessageReceivedEventArgs args)
 {
     if (SendMessageCompleted != null)
     {
         SendMessageCompleted(this, args);
     }
 }
        /// <summary>
        /// Sends a message to a remote server asychronously.
        /// </summary>
        /// <param name="action">The action to perform.</param>
        /// <param name="request">The request to send to the server.</param>
        /// <param name="userState">Any user state data.</param>
        /// <remarks>
        /// This operation will still be done in a synchronous mode.
        /// </remarks>
        public virtual void SendMessageAsync(string action, ServerRequest request, object userState)
        {
            if (isBusy) throw new InvalidOperationException();

            try
            {
                isBusy = true;
                InitialiseRemoting();
                Response result = client.ProcessMessage(action, request);

                if (SendMessageCompleted != null)
                {
                    MessageReceivedEventArgs args = new MessageReceivedEventArgs(result, null, false, userState);
                    SendMessageCompleted(this, args);
                }
            }
            catch (Exception error)
            {
                if (SendMessageCompleted != null)
                {
                    MessageReceivedEventArgs args = new MessageReceivedEventArgs(null, error, false, userState);
                    SendMessageCompleted(this, args);
                }
            }
            finally
            {
                isBusy = false;
            }
        }
        /// <summary>
        /// Sends a message to a remote server asychronously.
        /// </summary>
        /// <param name="action">The action to perform.</param>
        /// <param name="request">The request to send to the server.</param>
        /// <param name="userState">Any user state data.</param>
        /// <remarks>
        /// This operation will still be done in a synchronous mode.
        /// </remarks>
        public virtual void SendMessageAsync(string action, ServerRequest request, object userState)
        {
            if (isBusy) throw new InvalidOperationException();

            try
            {
                isBusy = true;
                InitialiseClient();
                IAsyncResult async = null;
                async = client.BeginProcessMessage(action, request, (result) =>
                {
                    if (SendMessageCompleted != null)
                    {
                        var response = client.EndProcessMessage(async);
                        var args = new MessageReceivedEventArgs(response, null, false, userState);
                        SendMessageCompleted(this, args);
                    }
                    isBusy = false;
                }, userState);

            }
            catch (Exception error)
            {
                if (SendMessageCompleted != null)
                {
                    var args = new MessageReceivedEventArgs(null, error, false, userState);
                    SendMessageCompleted(this, args);
                }
                isBusy = false;
            }
        }
        /// <summary>
        /// Sends a message to a remote server asychronously.
        /// </summary>
        /// <param name="action">The action to perform.</param>
        /// <param name="request">The request to send to the server.</param>
        /// <param name="userState">Any user state data.</param>
        public virtual void SendMessageAsync(string action, ServerRequest request, object userState)
        {
            // Ensure that async is only called once (or once with the user state)
            lock (lockObject)
            {
                if (userState == null)
                {
                    if (isBusy)
                    {
                        throw new InvalidOperationException();
                    }
                    isBusy = true;
                }
                else if (asyncOperations.ContainsKey(userState))
                {
                    if (asyncOperations.ContainsKey(userState))
                    {
                        throw new ArgumentException("Duplicate userState", "userState");
                    }
                }
            }

            // Initialise the web client
            var client = this.WebClientfactory.Generate();

            client.UploadValuesCompleted += (o, e) =>
            {
                if (SendMessageCompleted != null)
                {
                    if ((e.Error == null) && !e.Cancelled)
                    {
                        // Convert the response into a response object
                        string   response = Encoding.UTF8.GetString(e.Data);
                        Response result   = XmlConversionUtil.ProcessResponse(response);

                        MessageReceivedEventArgs args = new MessageReceivedEventArgs(result, null, false, userState);
                        SendMessageCompleted(this, args);
                    }
                    else
                    {
                        MessageReceivedEventArgs args = new MessageReceivedEventArgs(null, e.Error, e.Cancelled, userState);
                        SendMessageCompleted(this, args);
                    }
                }
                CompleteAsyncCall(userState);
            };
            lock (lockObject)
            {
                asyncOperations.Add(userState ?? string.Empty, client);
            }

            try
            {
                // Generate the target URI
                Uri targetAddress = GenerateTargetUri(request);

                // Build the request and send it
                NameValueCollection formData = new NameValueCollection();
                formData.Add("action", action);
                formData.Add("message", request.ToString());
                client.UploadValuesAsync(targetAddress, "POST", formData);
            }
            catch (Exception error)
            {
                if (SendMessageCompleted != null)
                {
                    MessageReceivedEventArgs args = new MessageReceivedEventArgs(null, error, false, userState);
                    SendMessageCompleted(this, args);
                }
                CompleteAsyncCall(userState);
            }
        }