Пример #1
0
        /// <summary>
        /// Sends a web request with the data either in the query string or in the body.
        /// </summary>
        /// <param name="config">
        /// The configuration for the data to be sent (e.g., contains the URL and request method).
        /// </param>
        /// <param name="context">
        /// The context for the current form submission.
        /// </param>
        /// <param name="data">
        /// The data to send.
        /// </param>
        /// <param name="sendInBody">
        /// Send the data as part of the body (or in the query string)?
        /// </param>
        /// <param name="sendJson">
        /// Send the data as json
        /// </param>
        /// <returns>
        /// True, if the request was a success; otherwise, false.
        /// </returns>
        /// <remarks>
        /// Parts of this function are from: http://stackoverflow.com/a/9772003/2052963
        /// and http://stackoverflow.com/questions/14702902
        /// </remarks>
        private SendDataResult SendData(SendDataConfiguration config, FormSubmissionContext context,
                                        IEnumerable <KeyValuePair <string, string> > data, bool sendInBody, bool sendJson)
        {
            // Construct a URL, possibly containing the data as query string parameters.
            var sendInUrl      = !sendInBody;
            var sendDataResult = new SendDataResult();
            var uri            = new Uri(config.Url);
            var bareUrl        = uri.GetLeftPart(UriPartial.Path);
            var keyValuePairs  = data as KeyValuePair <string, string>[] ?? data.ToArray();
            var strQueryString = ConstructQueryString(uri, keyValuePairs);
            var hasQueryString = !string.IsNullOrWhiteSpace(strQueryString);
            var requestUrl     = hasQueryString && sendInUrl
                ? $"{bareUrl}?{strQueryString}"
                : config.Url;
            var enableLogging       = WebConfigurationManager.AppSettings["Formulate:EnableLogging"];
            var jsonMode            = WebConfigurationManager.AppSettings["Formulate:Send Data JSON Mode"];
            var isJsonObjectMode    = "JSON Object".InvariantEquals(jsonMode);
            var isWrappedObjectMode = "Wrap JSON Object in Array".InvariantEquals(jsonMode);


            // Attempt to send the web request.
            try
            {
                // Construct web request.
                var request = (HttpWebRequest)WebRequest.Create(requestUrl);
                request.AllowAutoRedirect = false;
                request.UserAgent         = WebUserAgent;
                request.Method            = config.Method;


                // Send an event indicating that the data is about to be sent (which allows code
                // external to Formulate to modify the request).
                var sendContext = new SendingDataContext()
                {
                    Configuration     = config,
                    Data              = keyValuePairs,
                    Request           = request,
                    SubmissionContext = context
                };
                SendingData?.Invoke(sendContext);


                // Update the key/value pairs in case they got changed in the sending data event.
                // This only updates the methods that send the data in the body (as the URL has
                // already been set on the request).
                keyValuePairs = sendContext.Data as KeyValuePair <string, string>[]
                                ?? sendContext.Data.ToArray();


                // Send the data in the body (rather than the query string)?
                if (sendInBody)
                {
                    if (sendJson)
                    {
                        // Variables.
                        var json = default(string);


                        // Send an event indicating that the data is about to be serialized to
                        // JSON (which allows code external to Formulate to modify the JSON)?
                        if (SerializingJson != null)
                        {
                            json = SerializingJson.Invoke(sendContext.Data);
                        }
                        else
                        {
                            // If sending as JSON, group duplicate keys/value pairs.
                            var grouped = keyValuePairs.GroupBy(x => x.Key).Select(x => new
                            {
                                Key   = x.Key,
                                Value = x.Select(y => y.Value)
                            }).ToDictionary(x => x.Key,
                                            x => x.Value.Count() > 1 ? x.Value.ToArray() as object : x.Value.FirstOrDefault());


                            // Convert data to JSON.
                            if (isJsonObjectMode)
                            {
                                json = JsonConvert.SerializeObject(grouped);
                            }
                            else if (isWrappedObjectMode)
                            {
                                json = JsonConvert.SerializeObject(new[] { grouped });
                            }
                            else
                            {
                                // Ideally, we can remove this "else" branch later. We never really want this
                                // mode to be used, but it's here for legacy support in case anybody managed
                                // to make use of this funky mode.
                                json = JsonConvert.SerializeObject(new[] { grouped });
                            }
                        }


                        // Log JSON being sent.
                        if (enableLogging == "true")
                        {
                            LogHelper.Info <SendDataHandler>("Sent URL: " + config.Url);
                            LogHelper.Info <SendDataHandler>("Sent Data: " + JsonHelper.FormatJsonForLogging(json));
                        }


                        // Write JSON data to the request request.
                        var postBytes = Encoding.UTF8.GetBytes(json);
                        request.ContentType   = "application/json; charset=utf-8";
                        request.ContentLength = postBytes.Length;
                        using (var postStream = request.GetRequestStream())
                        {
                            postStream.Write(postBytes, 0, postBytes.Length);
                        }
                    }
                    else
                    {
                        // Log data being sent.
                        if (enableLogging == "true")
                        {
                            LogHelper.Info <SendDataHandler>("Sent URL: " + config.Url);
                            LogHelper.Info <SendDataHandler>("Sent Data: " + strQueryString);
                        }


                        // Update the data (since the sending data event may have modified it).
                        uri            = new Uri(config.Url);
                        strQueryString = ConstructQueryString(uri, keyValuePairs);


                        // Write the data to the request stream.
                        var postBytes = Encoding.UTF8.GetBytes(strQueryString);
                        request.ContentType   = "application/x-www-form-urlencoded";
                        request.ContentLength = postBytes.Length;
                        var postStream = request.GetRequestStream();
                        postStream.Write(postBytes, 0, postBytes.Length);
                    }
                }


                // Get and retain response.
                var response = (HttpWebResponse)request.GetResponse();
                sendDataResult.HttpWebResponse = response;
                var responseStream = response.GetResponseStream();
                var reader         = new StreamReader(responseStream);
                var resultText     = reader.ReadToEnd();
                sendDataResult.ResponseText = resultText;
                sendDataResult.Success      = true;
            }
            catch (Exception ex)
            {
                LogHelper.Error <SendDataHandler>(SendDataError, ex);
                sendDataResult.ResponseError = ex;
                sendDataResult.Success       = false;
            }


            // Return the result of the request.
            return(sendDataResult);
        }
Пример #2
0
        /// <summary>
        /// Deserializes the configuration for a send data handler.
        /// </summary>
        /// <param name="configuration">
        /// The serialized configuration.
        /// </param>
        /// <returns>
        /// The deserialized configuration.
        /// </returns>
        public object DeserializeConfiguration(string configuration)
        {
            // Variables.
            var fields = new List <FieldMapping>();
            var config = new SendDataConfiguration()
            {
                Fields = fields
            };
            var configData    = JsonHelper.Deserialize <JObject>(configuration);
            var dynamicConfig = configData as dynamic;
            var properties    = configData.Properties().Select(x => x.Name);
            var propertySet   = new HashSet <string>(properties);
            var handlerTypes  = ReflectionHelper
                                .GetTypesImplementingInterface <IHandleSendDataResult>();


            // Get field mappings.
            if (propertySet.Contains("fields"))
            {
                foreach (var field in dynamicConfig.fields)
                {
                    fields.Add(new FieldMapping()
                    {
                        FieldId   = GuidHelper.GetGuid(field.id.Value as string),
                        FieldName = field.name.Value as string
                    });
                }
            }


            // Set the function that handles the result.
            if (propertySet.Contains("resultHandler"))
            {
                var strHandler  = dynamicConfig.resultHandler.Value as string;
                var handlerType = handlerTypes
                                  .FirstOrDefault(x => x.AssemblyQualifiedName == strHandler);
                var resultHandler = default(IHandleSendDataResult);
                if (handlerType != null)
                {
                    resultHandler = Activator.CreateInstance(handlerType) as IHandleSendDataResult;
                }
                config.ResultHandler = resultHandler;
            }


            // Get simple properties.
            if (propertySet.Contains("url"))
            {
                config.Url = dynamicConfig.url.Value as string;
            }
            if (propertySet.Contains("method"))
            {
                config.Method = dynamicConfig.method.Value as string;
            }
            if (propertySet.Contains("transmissionFormat"))
            {
                config.TransmissionFormat = dynamicConfig.transmissionFormat.Value as string;
            }


            // Return the send data configuration.
            return(config);
        }