Facebook.FacebookClient.PrepareRequest C# (CSharp) Method

PrepareRequest() private method

private PrepareRequest ( HttpMethod httpMethod, string path, object parameters, Type resultType, Stream &input, bool &containsEtag, IList &batchEtags ) : HttpHelper
httpMethod HttpMethod
path string
parameters object
resultType Type
input Stream
containsEtag bool
batchEtags IList
return HttpHelper
        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;
            bool isAbsolutePath;
            path = ParseUrlQueryString(path, parametersWithoutMediaObjects, false, out uri, out isLegacyRestApi, out isAbsolutePath);

            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 };
            }

            if (isAbsolutePath || string.IsNullOrEmpty(Version))
            {
                uriBuilder.Path = path;
            }
            else
            {
                uriBuilder.Path = Version + "/" + 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();

            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");
            }

            if (!string.IsNullOrEmpty(contentType))
                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);
        }