예제 #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>
        /// 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);
        }
예제 #4
0
        /// <summary>
        /// Remote API method execution using HTTP "post" method with content type set to "multipart/form-data".
        /// </summary>
        private DataType ExecuteMultipartHttpRequest <ContractType, DataType>(ViddlerMethodAttribute methodAttribute, StringDictionary parameters, string fileName, Stream fileStream, Data.UploadEndPoint endPoint)
        {
            StringBuilder requestPath = new StringBuilder();

            if (endPoint != null && !string.IsNullOrEmpty(endPoint.Url))
            {
                requestPath.Append(endPoint.Url);
            }
            else
            {
                requestPath.Append((this.EnableSsl && methodAttribute.IsSecure) ? this.SecureBaseUrl : this.BaseUrl);
                requestPath.Append(methodAttribute.MethodName);
                requestPath.Append(".xml");
            }

            string boundary = string.Concat("-------------------------", DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture));

            byte[] boundaryBytes    = System.Text.Encoding.UTF8.GetBytes(string.Concat("\r\n--", boundary, "\r\n"));
            byte[] endBoundaryBytes = System.Text.Encoding.UTF8.GetBytes(string.Concat("\r\n--", boundary, "--\r\n"));

            List <byte> requestData = new List <byte>();

            // If we have endpoint uploadtoken that is ALL we send and we don't send session/apikey
            // If we send session/apikey and NOT uploadtoken, Viddler will do a prepareupload behind the scenes and use that uploadtoken.
            // This is why allow_replace fails w/out an uploadtoken because their prepareupload does NOT have allow_replace set.
            if (endPoint != null && !string.IsNullOrEmpty(endPoint.Token))
            {
                requestData.AddRange(boundaryBytes);
                requestData.AddRange(System.Text.Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "Content-Disposition: form-data; name=\"uploadtoken\"\r\n\r\n{0}", endPoint.Token)));
            }
            else
            {
                requestData.AddRange(boundaryBytes);
                requestData.AddRange(System.Text.Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "Content-Disposition: form-data; name=\"key\"\r\n\r\n{0}", this.ApiKey)));
                if (methodAttribute.IsSessionRequired)
                {
                    requestData.AddRange(boundaryBytes);
                    requestData.AddRange(System.Text.Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "Content-Disposition: form-data; name=\"sessionid\"\r\n\r\n{0}", this.SessionId)));
                }
            }

            if (parameters != null && parameters.Keys.Count > 0)
            {
                foreach (string key in parameters.Keys)
                {
                    //string queryData = string.Format(CultureInfo.InvariantCulture, "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", key, ViddlerHelper.EncodeRequestData(parameters[key]));
                    string queryData = string.Format(CultureInfo.InvariantCulture, "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", key, parameters[key]);
                    requestData.AddRange(boundaryBytes);
                    requestData.AddRange(System.Text.Encoding.UTF8.GetBytes(queryData));
                }
            }

            long fileSize = endBoundaryBytes.Length;

            if (fileStream != null)
            {
                fileStream.Position = 0;
                if (string.IsNullOrEmpty(fileName))
                {
                    fileName = DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture);
                }
                requestData.AddRange(boundaryBytes);
                requestData.AddRange(System.Text.Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"\r\nContent-Type: application/octet-stream\r\n\r\n", fileName)));
                fileSize += fileStream.Length;
            }

            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestPath.ToString());
                request.Method      = "POST";
                request.ContentType = string.Concat("multipart/form-data; boundary=", boundary);
                request.UserAgent   = string.Concat("Microsoft .NET, ", this.GetType().Assembly.FullName);
                request.AllowWriteStreamBuffering = false;
                request.Accept = "text/xml";
                request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
                request.KeepAlive        = true;
                request.Timeout          = int.MaxValue;
                request.ReadWriteTimeout = int.MaxValue;
                request.ContentLength    = requestData.Count + fileSize;

                Stream requestStream = request.GetRequestStream();
                bool   isCancel      = false;
                try
                {
                    requestStream.Write(requestData.ToArray(), 0, requestData.Count);
                    requestStream.Flush();
                    if (fileStream != null)
                    {
                        byte[] buffer    = new byte[32768];
                        int    bytesRead = 0;
                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                        {
                            requestStream.Write(buffer, 0, bytesRead);
                            requestStream.Flush();
                            if (this.Uploading != null)
                            {
                                ViddlerRequestUploadEventArgs uploadEventArgs = new ViddlerRequestUploadEventArgs(typeof(ContractType), fileStream.Length, fileStream.Position);
                                this.Uploading(this, uploadEventArgs);
                                if (uploadEventArgs.Cancel)
                                {
                                    isCancel = true;
                                    request.Abort();
                                    break;
                                }
                            }
                        }
                    }
                    if (!isCancel)
                    {
                        requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
                        requestStream.Flush();
                    }
                }
                finally
                {
                    if (!isCancel)
                    {
                        requestStream.Dispose();
                    }
                }
                if (isCancel)
                {
                    return(default(DataType));
                }
                else
                {
                    DataType responseObject = ViddlerService.HandleHttpResponse <ContractType, DataType>(request, methodAttribute, this.DumpFolder);
                    return(responseObject);
                }
            }
            catch (System.Net.WebException exception)
            {
                throw ViddlerService.HandleHttpError(exception);
            }
        }
예제 #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);
        }