Esempio n. 1
0
        private HttpHelper PrepareRequest(HttpMethod httpMethod, string path, object parameters, Type resultType, out Stream input, out bool containsEtag, out IList <int> batchEtags, string uriOverride = "")
        {
            input        = null;
            containsEtag = false;
            batchEtags   = null;

            IDictionary <string, FacebookMediaObject> mediaObjects;
            IDictionary <string, FacebookMediaStream> mediaStreams;
            IDictionary <string, object> parametersWithoutMediaObjects = ToDictionary(parameters, out mediaObjects, out mediaStreams) ?? new Dictionary <string, object>();

            if (!parametersWithoutMediaObjects.ContainsKey("access_token") && !string.IsNullOrEmpty(AccessToken))
            {
                parametersWithoutMediaObjects["access_token"] = AccessToken;
            }
            if (!parametersWithoutMediaObjects.ContainsKey("return_ssl_resources") && IsSecureConnection)
            {
                parametersWithoutMediaObjects["return_ssl_resources"] = true;
            }

            string etag = null;

            if (parametersWithoutMediaObjects.ContainsKey(ETagKey))
            {
                etag = (string)parametersWithoutMediaObjects[ETagKey];
                parametersWithoutMediaObjects.Remove(ETagKey);
                containsEtag = true;
            }

            Uri  uri;
            bool isLegacyRestApi = false;

            path = ParseUrlQueryString(path, parametersWithoutMediaObjects, false, out uri, out isLegacyRestApi);

            if (parametersWithoutMediaObjects.ContainsKey("format"))
            {
                parametersWithoutMediaObjects["format"] = "json-strings";
            }

            string restMethod = null;

            if (parametersWithoutMediaObjects.ContainsKey("method"))
            {
                restMethod = (string)parametersWithoutMediaObjects["method"];
                if (restMethod.Equals("DELETE", StringComparison.OrdinalIgnoreCase))
                {
                    throw new ArgumentException("Parameter cannot contain method=delete. Use Delete or DeleteAsync or DeleteTaskAsync methods instead.", "parameters");
                }
                parametersWithoutMediaObjects.Remove("method");
                isLegacyRestApi = true;
            }
            else if (isLegacyRestApi)
            {
                throw new ArgumentException("Parameters should contain rest 'method' name", "parameters");
            }

            UriBuilder uriBuilder;

            if (uri == null)
            {
                uriBuilder = new UriBuilder {
                    Scheme = "https"
                };

                if (isLegacyRestApi)
                {
                    if (string.IsNullOrEmpty(restMethod))
                    {
                        throw new InvalidOperationException("Legacy rest api 'method' in parameters is null or empty.");
                    }
                    path = string.Concat("method/", restMethod);
                    parametersWithoutMediaObjects["format"] = "json-strings";
                    if (restMethod.Equals("video.upload"))
                    {
                        uriBuilder.Host = UseFacebookBeta ? "api-video.beta.facebook.com" : "api-video.facebook.com";
                    }
                    else if (LegacyRestApiReadOnlyCalls.Contains(restMethod))
                    {
                        uriBuilder.Host = UseFacebookBeta ? "api-read.beta.facebook.com" : "api-read.facebook.com";
                    }
                    else
                    {
                        uriBuilder.Host = UseFacebookBeta ? "api.beta.facebook.com" : "api.facebook.com";
                    }
                }
                else
                {
                    if (parametersWithoutMediaObjects.ContainsKey("batch"))
                    {
                        var processBatchResponse = !parametersWithoutMediaObjects.ContainsKey("_process_batch_response_") ||
                                                   (bool)parametersWithoutMediaObjects["_process_batch_response_"];

                        if (processBatchResponse)
                        {
                            batchEtags = new List <int>();
                            var batch = parametersWithoutMediaObjects["batch"] as IList <object>;
                            if (batch != null)
                            {
                                int i;
                                for (i = 0; i < batch.Count; i++)
                                {
                                    var batchParameter = batch[i] as IDictionary <string, object>;
                                    if (batchParameter != null)
                                    {
                                        IDictionary <string, object> headers = null;
                                        if (batchParameter.ContainsKey("headers"))
                                        {
                                            headers = (IDictionary <string, object>)batchParameter["headers"];
                                        }

                                        bool containsBatchEtag = batchParameter.ContainsKey(ETagKey);
                                        if (containsBatchEtag)
                                        {
                                            if (string.IsNullOrEmpty((string)batchParameter[ETagKey]))
                                            {
                                                batchEtags.Add(i);
                                                batchParameter.Remove(ETagKey);
                                                continue;
                                            }
                                            else if (headers == null)
                                            {
                                                headers = new Dictionary <string, object>();
                                                batchParameter["headers"] = headers;
                                            }
                                        }

                                        if (containsBatchEtag)
                                        {
                                            if (!headers.ContainsKey("If-None-Match"))
                                            {
                                                headers["If-None-Match"] = string.Concat('"', batchParameter[ETagKey], '"');
                                            }
                                            batchParameter.Remove(ETagKey);
                                            batchEtags.Add(i);
                                        }
                                        else
                                        {
                                            if (headers != null && headers.ContainsKey("If-None-Match"))
                                            {
                                                batchEtags.Add(i);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    path = path ?? string.Empty;

                    if (httpMethod == HttpMethod.Post && path.EndsWith("/videos", StringComparison.OrdinalIgnoreCase))
                    {
                        uriBuilder.Host = UseFacebookBeta ? "graph-video.beta.facebook.com" : "graph-video.facebook.com";
                    }
                    else
                    {
                        uriBuilder.Host = UseFacebookBeta ? "graph.beta.facebook.com" : "graph.facebook.com";
                    }
                }
            }
            else
            {
                uriBuilder = new UriBuilder {
                    Host = uri.Host, Scheme = uri.Scheme
                };
            }

            uriBuilder.Path = path;

            string contentType   = null;
            long?  contentLength = null;
            var    queryString   = new StringBuilder();

            SerializeParameters(parametersWithoutMediaObjects);

            if (parametersWithoutMediaObjects.ContainsKey("access_token"))
            {
                var accessToken = parametersWithoutMediaObjects["access_token"] as string;
                if (!string.IsNullOrEmpty(accessToken) && accessToken != "null")
                {
                    queryString.AppendFormat("access_token={0}&", accessToken);
                }

                parametersWithoutMediaObjects.Remove("access_token");
            }

            if (httpMethod != HttpMethod.Post)
            {
                if (containsEtag && httpMethod != HttpMethod.Get)
                {
                    throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} is only supported for http get method.", ETagKey), "httpMethod");
                }

                // for GET,DELETE
                if (mediaObjects.Count > 0 && mediaStreams.Count > 0)
                {
                    throw new InvalidOperationException("Attachments (FacebookMediaObject/FacebookMediaStream) are valid only in POST requests.");
                }

#if SILVERLIGHT && !WINDOWS_PHONE
                if (httpMethod == HttpMethod.Delete)
                {
                    queryString.Append("method=delete&");
                }
#endif
                foreach (var kvp in parametersWithoutMediaObjects)
                {
                    queryString.AppendFormat("{0}={1}&", HttpHelper.UrlEncode(kvp.Key), HttpHelper.UrlEncode(BuildHttpQuery(kvp.Value, HttpHelper.UrlEncode)));
                }
            }
            else
            {
                if (mediaObjects.Count == 0 && mediaStreams.Count == 0)
                {
                    contentType = "application/x-www-form-urlencoded";
                    var sb = new StringBuilder();
                    foreach (var kvp in parametersWithoutMediaObjects)
                    {
                        sb.AppendFormat("{0}={1}&", HttpHelper.UrlEncode(kvp.Key), HttpHelper.UrlEncode(BuildHttpQuery(kvp.Value, HttpHelper.UrlEncode)));
                    }
                    if (sb.Length > 0)
                    {
                        sb.Length--;
                    }
                    input = sb.Length == 0 ? null : new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString()));
                }
                else
                {
                    string boundary = Boundary == null
                                          ? DateTime.UtcNow.Ticks.ToString("x", CultureInfo.InvariantCulture) // for unit testing
                                          : Boundary();

                    contentType = string.Concat("multipart/form-data; boundary=", boundary);

                    var streams = new List <Stream>();
                    var indexOfDisposableStreams = new List <int>();

                    // Build up the post message header
                    var sb = new StringBuilder();

                    foreach (var kvp in parametersWithoutMediaObjects)
                    {
                        sb.Append(MultiPartFormPrefix).Append(boundary).Append(MultiPartNewLine);
                        sb.Append("Content-Disposition: form-data; name=\"").Append(kvp.Key).Append("\"");
                        sb.Append(MultiPartNewLine).Append(MultiPartNewLine);
                        sb.Append(BuildHttpQuery(kvp.Value, HttpHelper.UrlEncode));
                        sb.Append(MultiPartNewLine);
                    }

                    indexOfDisposableStreams.Add(streams.Count);
                    streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString())));

                    foreach (var facebookMediaObject in mediaObjects)
                    {
                        var sbMediaObject = new StringBuilder();
                        var mediaObject   = facebookMediaObject.Value;

                        if (mediaObject.ContentType == null || mediaObject.GetValue() == null || string.IsNullOrEmpty(mediaObject.FileName))
                        {
                            throw new InvalidOperationException(AttachmentMustHavePropertiesSetError);
                        }

                        sbMediaObject.Append(MultiPartFormPrefix).Append(boundary).Append(MultiPartNewLine);
                        sbMediaObject.Append("Content-Disposition: form-data; name=\"").Append(facebookMediaObject.Key).Append("\"; filename=\"").Append(mediaObject.FileName).Append("\"").Append(MultiPartNewLine);
                        sbMediaObject.Append("Content-Type: ").Append(mediaObject.ContentType).Append(MultiPartNewLine).Append(MultiPartNewLine);

                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(sbMediaObject.ToString())));

                        byte[] fileData = mediaObject.GetValue();

                        if (fileData == null)
                        {
                            throw new InvalidOperationException(AttachmentValueIsNull);
                        }

                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(fileData));
                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(MultiPartNewLine)));
                    }

                    foreach (var facebookMediaStream in mediaStreams)
                    {
                        var sbMediaStream = new StringBuilder();
                        var mediaStream   = facebookMediaStream.Value;

                        if (mediaStream.ContentType == null || mediaStream.GetValue() == null || string.IsNullOrEmpty(mediaStream.FileName))
                        {
                            throw new InvalidOperationException(AttachmentMustHavePropertiesSetError);
                        }

                        sbMediaStream.Append(MultiPartFormPrefix).Append(boundary).Append(MultiPartNewLine);
                        sbMediaStream.Append("Content-Disposition: form-data; name=\"").Append(facebookMediaStream.Key).Append("\"; filename=\"").Append(mediaStream.FileName).Append("\"").Append(MultiPartNewLine);
                        sbMediaStream.Append("Content-Type: ").Append(mediaStream.ContentType).Append(MultiPartNewLine).Append(MultiPartNewLine);

                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(sbMediaStream.ToString())));

                        var stream = mediaStream.GetValue();

                        if (stream == null)
                        {
                            throw new InvalidOperationException(AttachmentValueIsNull);
                        }

                        streams.Add(stream);

                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(MultiPartNewLine)));
                    }

                    indexOfDisposableStreams.Add(streams.Count);
                    streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(string.Concat(MultiPartNewLine, MultiPartFormPrefix, boundary, MultiPartFormPrefix, MultiPartNewLine))));
                    input = new CombinationStream(streams, indexOfDisposableStreams);
                }

                contentLength = input == null ? 0 : input.Length;
            }

            if (queryString.Length > 0)
            {
                queryString.Length--;
            }

            uriBuilder.Query = queryString.ToString();
            Uri finalUri = uriBuilder.Uri;
            if (uriOverride != "")
            {
                finalUri = new Uri(uriOverride);
            }
            var request = HttpWebRequestFactory == null
                                                         ? new HttpWebRequestWrapper((HttpWebRequest)WebRequest.Create(finalUri))
                             : HttpWebRequestFactory(uriBuilder.Uri);

            switch (httpMethod)
            {
            case HttpMethod.Get:
                request.Method = "GET";
                break;

            case HttpMethod.Delete:
#if !(SILVERLIGHT && !WINDOWS_PHONE)
                request.Method = "DELETE";
                request.TrySetContentLength(0);
                break;
#endif
            case HttpMethod.Post:
                request.Method = "POST";
                break;

            default:
                throw new ArgumentOutOfRangeException("httpMethod");
            }

            request.ContentType = contentType;

            if (!string.IsNullOrEmpty(etag))
            {
                request.Headers[HttpRequestHeader.IfNoneMatch] = string.Concat('"', etag, '"');
            }

#if !(SILVERLIGHT || NETFX_CORE)
            request.AutomaticDecompression    = DecompressionMethods.GZip | DecompressionMethods.Deflate;
            request.AllowWriteStreamBuffering = false;
#endif
#if NETFX_CORE
            request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip,deflate";
#endif

            if (contentLength.HasValue)
            {
                request.TrySetContentLength(contentLength.Value);
            }

            request.TrySetUserAgent("Facebook C# SDK");

            return(new HttpHelper(request));
        }
        private HttpHelper PrepareRequest(HttpMethod httpMethod, string path, object parameters, Type resultType, out Stream input, out bool containsEtag, out IList<int> batchEtags)
        {
            input = null;
            containsEtag = false;
            batchEtags = null;

            IDictionary<string, FacebookMediaObject> mediaObjects;
            IDictionary<string, FacebookMediaStream> mediaStreams;
            IDictionary<string, object> parametersWithoutMediaObjects = ToDictionary(parameters, out mediaObjects, out mediaStreams) ?? new Dictionary<string, object>();

            if (!parametersWithoutMediaObjects.ContainsKey("access_token") && !string.IsNullOrEmpty(AccessToken))
                parametersWithoutMediaObjects["access_token"] = AccessToken;
            if (!parametersWithoutMediaObjects.ContainsKey("return_ssl_resources") && IsSecureConnection)
                parametersWithoutMediaObjects["return_ssl_resources"] = true;

            string etag = null;
            if (parametersWithoutMediaObjects.ContainsKey(ETagKey))
            {
                etag = (string)parametersWithoutMediaObjects[ETagKey];
                parametersWithoutMediaObjects.Remove(ETagKey);
                containsEtag = true;
            }

            Uri uri;
            bool isLegacyRestApi = false;
            path = ParseUrlQueryString(path, parametersWithoutMediaObjects, false, out uri, out isLegacyRestApi);

            if (parametersWithoutMediaObjects.ContainsKey("format"))
                parametersWithoutMediaObjects["format"] = "json-strings";

            string restMethod = null;
            if (parametersWithoutMediaObjects.ContainsKey("method"))
            {
                restMethod = (string)parametersWithoutMediaObjects["method"];
                if (restMethod.Equals("DELETE", StringComparison.OrdinalIgnoreCase))
                    throw new ArgumentException("Parameter cannot contain method=delete. Use Delete or DeleteAsync or DeleteTaskAsync methods instead.", "parameters");
                parametersWithoutMediaObjects.Remove("method");
                isLegacyRestApi = true;
            }
            else if (isLegacyRestApi)
            {
                throw new ArgumentException("Parameters should contain rest 'method' name", "parameters");
            }

            UriBuilder uriBuilder;
            if (uri == null)
            {
                uriBuilder = new UriBuilder { Scheme = "https" };

                if (isLegacyRestApi)
                {
                    if (string.IsNullOrEmpty(restMethod))
                        throw new InvalidOperationException("Legacy rest api 'method' in parameters is null or empty.");
                    path = string.Concat("method/", restMethod);
                    parametersWithoutMediaObjects["format"] = "json-strings";
                    if (restMethod.Equals("video.upload"))
                        uriBuilder.Host = UseFacebookBeta ? "api-video.beta.facebook.com" : "api-video.facebook.com";
                    else if (LegacyRestApiReadOnlyCalls.Contains(restMethod))
                        uriBuilder.Host = UseFacebookBeta ? "api-read.beta.facebook.com" : "api-read.facebook.com";
                    else
                        uriBuilder.Host = UseFacebookBeta ? "api.beta.facebook.com" : "api.facebook.com";
                }
                else
                {
                    if (parametersWithoutMediaObjects.ContainsKey("batch"))
                    {
                        var processBatchResponse = !parametersWithoutMediaObjects.ContainsKey("_process_batch_response_") ||
                                               (bool)parametersWithoutMediaObjects["_process_batch_response_"];

                        if (processBatchResponse)
                        {
                            batchEtags = new List<int>();
                            var batch = parametersWithoutMediaObjects["batch"] as IList<object>;
                            if (batch != null)
                            {
                                int i;
                                for (i = 0; i < batch.Count; i++)
                                {
                                    var batchParameter = batch[i] as IDictionary<string, object>;
                                    if (batchParameter != null)
                                    {
                                        IDictionary<string, object> headers = null;
                                        if (batchParameter.ContainsKey("headers"))
                                            headers = (IDictionary<string, object>)batchParameter["headers"];

                                        bool containsBatchEtag = batchParameter.ContainsKey(ETagKey);
                                        if (containsBatchEtag)
                                        {
                                            if (string.IsNullOrEmpty((string)batchParameter[ETagKey]))
                                            {
                                                batchEtags.Add(i);
                                                batchParameter.Remove(ETagKey);
                                                continue;
                                            }
                                            else if (headers == null)
                                            {
                                                headers = new Dictionary<string, object>();
                                                batchParameter["headers"] = headers;
                                            }
                                        }

                                        if (containsBatchEtag)
                                        {
                                            if (!headers.ContainsKey("If-None-Match"))
                                                headers["If-None-Match"] = string.Concat('"', batchParameter[ETagKey], '"');
                                            batchParameter.Remove(ETagKey);
                                            batchEtags.Add(i);
                                        }
                                        else
                                        {
                                            if (headers != null && headers.ContainsKey("If-None-Match"))
                                                batchEtags.Add(i);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else if (string.IsNullOrEmpty(path))
                    {
                        throw new ArgumentNullException("path");
                    }

                    if (httpMethod == HttpMethod.Post && path.EndsWith("/videos"))
                        uriBuilder.Host = UseFacebookBeta ? "graph-video.beta.facebook.com" : "graph-video.facebook.com";
                    else
                        uriBuilder.Host = UseFacebookBeta ? "graph.beta.facebook.com" : "graph.facebook.com";
                }
            }
            else
            {
                uriBuilder = new UriBuilder { Host = uri.Host, Scheme = uri.Scheme };
            }

            uriBuilder.Path = path;

            string contentType = null;
            var queryString = new StringBuilder();

            SerializeParameters(parametersWithoutMediaObjects);

            if (parametersWithoutMediaObjects.ContainsKey("access_token"))
            {
                var accessToken = parametersWithoutMediaObjects["access_token"];
                if (accessToken != null && (!(accessToken is string) || (!string.IsNullOrEmpty((string)accessToken))))
                    queryString.AppendFormat("access_token={0}&", accessToken);

                parametersWithoutMediaObjects.Remove("access_token");
            }

            if (httpMethod != HttpMethod.Post)
            {
                if (containsEtag && httpMethod != HttpMethod.Get)
                    throw new ArgumentException(string.Format("{0} is only supported for http get method.", ETagKey), "httpMethod");

                // for GET,DELETE
                if (mediaObjects.Count > 0 && mediaStreams.Count > 0)
                    throw new InvalidOperationException("Attachments (FacebookMediaObject/FacebookMediaStream) are valid only in POST requests.");

            #if SILVERLIGHT && !WINDOWS_PHONE
                if (httpMethod == HttpMethod.Delete)
                    queryString.Append("method=delete&");
            #endif
                foreach (var kvp in parametersWithoutMediaObjects)
                    queryString.AppendFormat("{0}={1}&", HttpHelper.UrlEncode(kvp.Key), HttpHelper.UrlEncode(BuildHttpQuery(kvp.Value, HttpHelper.UrlEncode)));
            }
            else
            {
                if (mediaObjects.Count == 0 && mediaStreams.Count == 0)
                {
                    contentType = "application/x-www-form-urlencoded";
                    var sb = new StringBuilder();
                    foreach (var kvp in parametersWithoutMediaObjects)
                        sb.AppendFormat("{0}={1}&", HttpHelper.UrlEncode(kvp.Key), HttpHelper.UrlEncode(BuildHttpQuery(kvp.Value, HttpHelper.UrlEncode)));
                    if (sb.Length > 0)
                        sb.Length--;
                    input = sb.Length == 0 ? null : new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString()));
                }
                else
                {
                    string boundary = Boundary == null
                                          ? DateTime.UtcNow.Ticks.ToString("x", CultureInfo.InvariantCulture) // for unit testing
                                          : Boundary();

                    contentType = string.Concat("multipart/form-data; boundary=", boundary);

                    var streams = new List<Stream>();
                    var indexOfDisposableStreams = new List<int>();

                    // Build up the post message header
                    var sb = new StringBuilder();

                    foreach (var kvp in parametersWithoutMediaObjects)
                    {
                        sb.Append(MultiPartFormPrefix).Append(boundary).Append(MultiPartNewLine);
                        sb.Append("Content-Disposition: form-data; name=\"").Append(kvp.Key).Append("\"");
                        sb.Append(MultiPartNewLine).Append(MultiPartNewLine);
                        sb.Append(BuildHttpQuery(kvp.Value, HttpHelper.UrlEncode));
                        sb.Append(MultiPartNewLine);
                    }

                    indexOfDisposableStreams.Add(streams.Count);
                    streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString())));

                    foreach (var facebookMediaObject in mediaObjects)
                    {
                        var sbMediaObject = new StringBuilder();
                        var mediaObject = facebookMediaObject.Value;

                        if (mediaObject.ContentType == null || mediaObject.GetValue() == null || string.IsNullOrEmpty(mediaObject.FileName))
                            throw new InvalidOperationException(AttachmentMustHavePropertiesSetError);

                        sbMediaObject.Append(MultiPartFormPrefix).Append(boundary).Append(MultiPartNewLine);
                        sbMediaObject.Append("Content-Disposition: form-data; name=\"").Append(facebookMediaObject.Key).Append("\"; filename=\"").Append(mediaObject.FileName).Append("\"").Append(MultiPartNewLine);
                        sbMediaObject.Append("Content-Type: ").Append(mediaObject.ContentType).Append(MultiPartNewLine).Append(MultiPartNewLine);

                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(sbMediaObject.ToString())));

                        byte[] fileData = mediaObject.GetValue();

                        if (fileData == null)
                            throw new InvalidOperationException(AttachmentValueIsNull);

                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(fileData));
                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(MultiPartNewLine)));
                    }

                    foreach (var facebookMediaStream in mediaStreams)
                    {
                        var sbMediaStream = new StringBuilder();
                        var mediaStream = facebookMediaStream.Value;

                        if (mediaStream.ContentType == null || mediaStream.GetValue() == null || string.IsNullOrEmpty(mediaStream.FileName))
                            throw new InvalidOperationException(AttachmentMustHavePropertiesSetError);

                        sbMediaStream.Append(MultiPartFormPrefix).Append(boundary).Append(MultiPartNewLine);
                        sbMediaStream.Append("Content-Disposition: form-data; name=\"").Append(facebookMediaStream.Key).Append("\"; filename=\"").Append(mediaStream.FileName).Append("\"").Append(MultiPartNewLine);
                        sbMediaStream.Append("Content-Type: ").Append(mediaStream.ContentType).Append(MultiPartNewLine).Append(MultiPartNewLine);

                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(sbMediaStream.ToString())));

                        var stream = mediaStream.GetValue();

                        if (stream == null)
                            throw new InvalidOperationException(AttachmentValueIsNull);

                        streams.Add(stream);

                        indexOfDisposableStreams.Add(streams.Count);
                        streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(MultiPartNewLine)));
                    }

                    indexOfDisposableStreams.Add(streams.Count);
                    streams.Add(new MemoryStream(Encoding.UTF8.GetBytes(string.Concat(MultiPartNewLine, MultiPartFormPrefix, boundary, MultiPartFormPrefix, MultiPartNewLine))));
                    input = new CombinationStream(streams, indexOfDisposableStreams);
                }
            }

            if (queryString.Length > 0)
                queryString.Length--;

            uriBuilder.Query = queryString.ToString();

            var request = HttpWebRequestFactory == null
                             ? new HttpWebRequestWrapper((HttpWebRequest)WebRequest.Create(uriBuilder.Uri))
                             : HttpWebRequestFactory(uriBuilder.Uri);

            switch (httpMethod)
            {
                case HttpMethod.Get:
                    request.Method = "GET";
                    break;
                case HttpMethod.Delete:
            #if !(SILVERLIGHT && !WINDOWS_PHONE)
                    request.Method = "DELETE";
                    request.TrySetContentLength(0);
                    break;
            #endif
                case HttpMethod.Post:
                    request.Method = "POST";
                    break;
                default:
                    throw new ArgumentOutOfRangeException("httpMethod");
            }

            request.ContentType = contentType;

            if (!string.IsNullOrEmpty(etag))
                request.Headers[HttpRequestHeader.IfNoneMatch] = string.Concat('"', etag, '"');

            #if !(SILVERLIGHT || NETFX_CORE)
            request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
            request.AllowWriteStreamBuffering = false;
            #endif
            #if NETFX_CORE
            request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip,deflate";
            #endif

            if (input != null)
                request.TrySetContentLength(input.Length);

            request.TrySetUserAgent("Facebook C# SDK");

            return new HttpHelper(request);
        }