Пример #1
0
        /// <summary>
        /// Remote API method execution using HTTP "post" method.
        /// </summary>
        private DataType ExecutePostHttpRequest <ContractType, DataType>(ViddlerMethodAttribute methodAttribute, StringDictionary parameters)
        {
            StringBuilder requestPath = new StringBuilder();
            StringBuilder requestData = new StringBuilder();

            requestPath.Append((this.EnableSsl && methodAttribute.IsSecure) ? this.SecureBaseUrl : this.BaseUrl);
            requestPath.Append(methodAttribute.MethodName);
            requestPath.Append(".xml");

            requestData.Append("key=");
            requestData.Append(this.ApiKey);
            if (methodAttribute.IsSessionRequired)
            {
                requestData.Append("&sessionid=");
                requestData.Append(this.SessionId);
            }

            if (parameters != null && parameters.Keys.Count > 0)
            {
                foreach (string key in parameters.Keys)
                {
                    requestData.Append("&");
                    requestData.Append(key);
                    requestData.Append("=");
                    requestData.Append(ViddlerHelper.EncodeRequestData(parameters[key]));
                }
            }
            byte[] postDataBytes = System.Text.Encoding.UTF8.GetBytes(requestData.ToString());

            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestPath.ToString());
                request.Method      = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.UserAgent   = string.Concat("Microsoft .NET, ", this.GetType().Assembly.FullName);
                request.AllowWriteStreamBuffering = true;
                request.Accept = "text/xml";
                request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
                request.KeepAlive        = true;
                request.Timeout          = int.MaxValue;
                request.ReadWriteTimeout = int.MaxValue;

                using (Stream requestStream = request.GetRequestStream())
                {
                    requestStream.Write(postDataBytes, 0, postDataBytes.Length);
                    requestStream.Flush();
                }

                DataType responseObject = ViddlerService.HandleHttpResponse <ContractType, DataType>(request, methodAttribute, this.DumpFolder);
                return(responseObject);
            }
            catch (System.Net.WebException exception)
            {
                throw ViddlerService.HandleHttpError(exception);
            }
        }
Пример #2
0
        /// <summary>
        /// Analyzes target response data object and collects properties of promitive type.
        /// </summary>
        internal static Dictionary <string, Type> GetExpectedPrimitiveTypeNodes(Type type)
        {
            Dictionary <string, Type> nodeNameCollection = new Dictionary <string, Type>();
            ViddlerMethodAttribute    methodAttribute    = ViddlerHelper.GetMethodAttribute(type);

            if (methodAttribute != null)
            {
                string xpath = string.Concat("/", methodAttribute.ElementName, "/");
                ViddlerHelper.CollectExpectedPrimitiveTypeNodes(xpath, type, nodeNameCollection, 0);
            }
            return(nodeNameCollection);
        }
Пример #3
0
 /// <summary>
 /// Analyzes target response data object and collects properties of promitive type.
 /// </summary>
 private static void CollectExpectedPrimitiveTypeNodes(string xpath, Type currentType, Dictionary <string, Type> nodeNameCollection, int depth)
 {
     if (depth > 10)
     {
         throw new StackOverflowException(string.Concat("Potential stack overflow due to recursively nested data types: ", xpath, "; current depth: ", depth));
     }
     foreach (PropertyInfo propertyInfo in currentType.GetProperties())
     {
         if (propertyInfo.PropertyType.IsValueType)
         {
             string elementName = ViddlerHelper.GetXmlElementName(propertyInfo);
             if (!string.IsNullOrEmpty(elementName))
             {
                 nodeNameCollection.Add(string.Concat(xpath, elementName), propertyInfo.PropertyType);
             }
         }
         else if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>))
         {
             Type genericArgumentType = propertyInfo.PropertyType.GetGenericArguments()[0];
             if (genericArgumentType.IsValueType)
             {
                 string elementName = ViddlerHelper.GetXmlElementName(propertyInfo);
                 if (!string.IsNullOrEmpty(elementName))
                 {
                     nodeNameCollection.Add(string.Concat(xpath, elementName), genericArgumentType);
                 }
             }
         }
         else if (propertyInfo.PropertyType.Assembly == typeof(ViddlerHelper).Assembly)
         {
             string elementName = ViddlerHelper.GetXmlElementName(propertyInfo);
             ViddlerHelper.CollectExpectedPrimitiveTypeNodes(string.Concat(xpath, elementName, "/"), propertyInfo.PropertyType, nodeNameCollection, depth + 1);
         }
         else if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(List <>) && propertyInfo.PropertyType.GetGenericArguments()[0].Assembly == typeof(ViddlerHelper).Assembly)
         {
             string elementName = ViddlerHelper.GetXmlElementName(propertyInfo);
             if (string.IsNullOrEmpty(elementName))
             {
                 elementName = ViddlerHelper.GetXmlArrayName(propertyInfo);
                 if (!string.IsNullOrEmpty(elementName))
                 {
                     elementName = string.Concat(elementName, "/", ViddlerHelper.GetXmlArrayItemName(propertyInfo));
                 }
             }
             ViddlerHelper.CollectExpectedPrimitiveTypeNodes(string.Concat(xpath, elementName, "/"), propertyInfo.PropertyType.GetGenericArguments()[0], nodeNameCollection, depth + 1);
         }
     }
 }
Пример #4
0
        /// <summary>
        /// Handles a web response from the remote server.
        /// </summary>
        private static DataType HandleHttpResponse <ContractType, DataType>(HttpWebRequest request, ViddlerMethodAttribute methodAttribute, string dumpPath)
        {
            DataType responseObject = default(DataType);

            using (WebResponse response = request.GetResponse())
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    using (MemoryStream stream = new MemoryStream())
                    {
                        int    count;
                        byte[] buffer = new byte[1024];
                        do
                        {
                            count = responseStream.Read(buffer, 0, 1024);
                            stream.Write(buffer, 0, count);
                        } while (count > 0); // copy response stream to "seek-enabled" stream

                        if (!string.IsNullOrEmpty(dumpPath))
                        {
                            ViddlerService.DumpResposeToFile(dumpPath, stream, methodAttribute.MethodName, request.RequestUri.ToString());
                        }

                        stream.Position = 0;
                        string            messageType    = string.Empty;
                        XmlReaderSettings readerSettings = new XmlReaderSettings();
                        readerSettings.CloseInput     = false;
                        readerSettings.IgnoreComments = true;
                        readerSettings.IgnoreProcessingInstructions = true;
                        using (XmlReader reader = XmlReader.Create(stream, readerSettings))
                        {
                            if (reader.MoveToContent() == XmlNodeType.Element)
                            {
                                messageType = reader.LocalName;
                            }
                        }

                        stream.Position = 0;
                        if (messageType.Equals(methodAttribute.ElementName, StringComparison.Ordinal))
                        {
                            try
                            {
                                XmlSerializer serializer = new XmlSerializer(typeof(ContractType));
                                responseObject = (DataType)serializer.Deserialize(stream);
                            }
                            catch (Exception exception)
                            {
                                if (exception.InnerException != null && exception.InnerException.GetType() == typeof(System.FormatException)) // XmlSerializer has problems with parsing primitive types - removing empty nodes, which are deserialized to properties of primitive type
                                {
                                    stream.Position = 0;
                                    Dictionary <string, Type> nodesToCheck = ViddlerHelper.GetExpectedPrimitiveTypeNodes(typeof(ContractType));
                                    XmlDocument responseXml = new XmlDocument();
                                    responseXml.PreserveWhitespace = true;
                                    responseXml.Load(stream);

                                    foreach (string node in nodesToCheck.Keys)
                                    {
                                        foreach (XmlNode xmlNode in responseXml.SelectNodes(node))
                                        {
                                            if (string.IsNullOrEmpty(xmlNode.InnerText.Trim()))
                                            {
                                                xmlNode.ParentNode.RemoveChild(xmlNode);
                                            }
                                        }
                                    }

                                    using (MemoryStream xmlStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(responseXml.OuterXml)))
                                    {
                                        XmlSerializer serializer = new XmlSerializer(typeof(ContractType));
                                        responseObject = (DataType)serializer.Deserialize(xmlStream);
                                    }
                                }
                                else
                                {
                                    throw;
                                }
                            }
                        }
                        else if (messageType.Equals("error", StringComparison.Ordinal))
                        {
                            XmlSerializer        serializer  = new XmlSerializer(typeof(ViddlerResponseError));
                            ViddlerResponseError errorObject = (ViddlerResponseError)serializer.Deserialize(stream);
                            throw new ViddlerRequestException(errorObject, null);
                        }
                        else
                        {
                            XmlDocument responseXml = new XmlDocument();
                            responseXml.PreserveWhitespace = true;
                            responseXml.Load(stream);
                            throw new System.InvalidOperationException(responseXml.OuterXml);
                        }
                    }
                }
            }

            return(responseObject);
        }
Пример #5
0
        /// <summary>
        /// Remote API method execution.
        /// </summary>
        internal DataType ExecuteHttpRequest <ContractType, DataType>(StringDictionary parameters, string fileName, Stream fileStream, Data.UploadEndPoint endPoint)
        {
            ViddlerMethodAttribute methodAttribute = ViddlerHelper.GetMethodAttribute(typeof(ContractType));

            DataType responseObject = default(DataType);

            try
            {
                if (methodAttribute == null)
                {
                    throw new System.InvalidOperationException(string.Concat("ViddlerMethodAttribute missing for type \"", typeof(ContractType).ToString(), "\"."));
                }

                if (this.BeginRequest != null)
                {
                    this.BeginRequest(this, new ViddlerRequestEventArgs(typeof(ContractType), parameters, (fileStream != null)));
                }

                if (methodAttribute.IsSessionRequired && !this.IsAuthenticated)
                {
                    throw new System.InvalidOperationException("The current method requires authenticated user.");
                }
                if (fileStream != null && !fileStream.CanSeek)
                {
                    throw new System.ArgumentException("The file stream does not support seeking.", "fileStream");
                }

                switch (methodAttribute.RequestType)
                {
                case ViddlerRequestType.Post:
                {
                    responseObject = this.ExecutePostHttpRequest <ContractType, DataType>(methodAttribute, parameters);
                    break;
                }

                case ViddlerRequestType.Multipart:
                {
                    responseObject = this.ExecuteMultipartHttpRequest <ContractType, DataType>(methodAttribute, parameters, fileName, fileStream, endPoint);
                    break;
                }

                default:
                {
                    responseObject = this.ExecuteGetHttpRequest <ContractType, DataType>(methodAttribute, parameters);
                    break;
                }
                }

                if (this.EndRequest != null)
                {
                    this.EndRequest(this, new ViddlerRequestEventArgs(typeof(ContractType), parameters, (fileStream != null)));
                }
            }
            catch (Exception exception)
            {
                if (this.Error != null)
                {
                    this.Error(this, new ViddlerRequestErrorEventArgs(typeof(ContractType), parameters, (fileStream != null), exception));
                }
                else
                {
                    throw;
                }
            }

            return(responseObject);
        }