public HttpResponseMessage GetVersion([FromUri(Name = "versionId")] string versionIdString)
        {
            ValidateRequest(Request);

            ApiVersionId versionId = new ApiVersionId(versionIdString);

            JObject allVersions = JsonConvert.DeserializeObject <JObject>(IdentityServiceResources.ListApiVersionsResponse);

            ApiVersion[] versions = allVersions["versions"]["values"].ToObject <ApiVersion[]>();
            ApiVersion   version  = versions.FirstOrDefault(i => i.Id.Equals(versionId));

            if (version == null)
            {
                return(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
            else
            {
                HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);

                JObject responseObject = new JObject(new JProperty("version", JObject.FromObject(version)));
                response.Content = new StringContent(responseObject.ToString(Formatting.None), Encoding.UTF8, "application/json");

                return(response);
            }
        }
        /// <summary>
        /// Prepare and send an HTTP API call to obtain information about a particular version of the API available at
        /// the current endpoint for the service.
        /// </summary>
        /// <param name="service">The <see cref="IBaseIdentityService"/> instance.</param>
        /// <param name="apiVersionId">The unique ID of the API version.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
        /// <returns>
        /// A <seealso cref="Task"/> representing the asynchronous operation. When the task completes successfully, the
        /// <see cref="Task{TResult}.Result"/> property will contain an <see cref="ApiVersion"/> instance describing the
        /// specified version of the API.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <para>If <paramref name="service"/> is <see langword="null"/>.</para>
        /// <para>-or-</para>
        /// <para>If <paramref name="apiVersionId"/> is <see langword="null"/>.</para>
        /// </exception>
        /// <exception cref="HttpWebException">
        /// If an error occurred during an HTTP request while preparing or sending the HTTP API call.
        /// </exception>
        /// <seealso cref="BaseIdentityServiceExtensions.GetApiVersionAsync"/>
        /// <seealso href="http://developer.openstack.org/api-ref-identity-v2.html#identity-v2-versions">API versions (Identity API v2.0 - OpenStack Complete API Reference)</seealso>
        /// <seealso href="http://developer.openstack.org/api-ref-identity-v3.html#versions-identity-v3">API versions (Identity API v3 - OpenStack Complete API Reference)</seealso>
        public static Task<ApiVersion> GetApiVersionAsync(this IBaseIdentityService service, ApiVersionId apiVersionId, CancellationToken cancellationToken)
        {
            if (service == null)
                throw new ArgumentNullException("service");
            if (apiVersionId == null)
                throw new ArgumentNullException("apiVersionId");

            return TaskBlocks.Using(
                () => service.PrepareGetApiVersionAsync(apiVersionId, cancellationToken),
                task => task.Result.SendAsync(cancellationToken).Select(innerTask => innerTask.Result.Item2.Version));
        }
        /// <inheritdoc/>
        /// <remarks>
        /// <para>Rackspace sends back the <c>media-types</c> property value wrapped in an additional JSON object, as
        /// opposed to the array OpenStack uses. This method overrides the behavior of the base OpenStack client to
        /// replace the unexpected structure with the correct layout prior to deserialization.</para>
        /// <note type="note">
        /// <para>If required, the original response is available via the <see cref="HttpResponseMessage.Content"/>
        /// property of the response.</para>
        /// </note>
        /// </remarks>
        public override Task<GetApiVersionApiCall> PrepareGetApiVersionAsync(ApiVersionId apiVersionId, CancellationToken cancellationToken)
        {
            UriTemplate template = new UriTemplate("{version_id}");
            Dictionary<string, string> parameters = new Dictionary<string, string> { { "version_id", apiVersionId.Value } };

            Func<HttpResponseMessage, CancellationToken, Task<ApiVersionResponse>> deserializeResult =
                (responseMessage, innerCancellationToken) =>
                {
                    Uri originalUri = responseMessage.RequestMessage.RequestUri;

                    if (!HttpApiCall.IsAcceptable(responseMessage))
                        throw new HttpWebException(responseMessage);

                    return responseMessage.Content.ReadAsStringAsync()
                        .Select(
                            innerTask =>
                            {
                                if (string.IsNullOrEmpty(innerTask.Result))
                                    return null;

                                JObject responseObject = JsonConvert.DeserializeObject<JObject>(innerTask.Result);
                                if (responseObject == null)
                                    return null;

                                JObject versionObject = responseObject["version"] as JObject;
                                if (versionObject == null)
                                    return responseObject.ToObject<ApiVersionResponse>();

                                JToken mediaTypesToken = versionObject["media-types"];
                                if (mediaTypesToken is JArray)
                                    return responseObject.ToObject<ApiVersionResponse>();

                                JArray mediaTypesArray = mediaTypesToken["values"] as JArray;
                                if (mediaTypesArray == null)
                                    versionObject.Remove("media-types");
                                else
                                    versionObject["media-types"] = mediaTypesArray;

                                return responseObject.ToObject<ApiVersionResponse>();
                            });
                };

            return GetBaseUriAsync(cancellationToken)
                .Then(PrepareRequestAsyncFunc(HttpMethod.Get, template, parameters, cancellationToken))
                .Select(task => new GetApiVersionApiCall(CreateCustomApiCall(task.Result, HttpCompletionOption.ResponseContentRead, deserializeResult)));
        }
        public async Task TestGetApiVersion2()
        {
            using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
            {
                cancellationTokenSource.CancelAfter(TestTimeout(TimeSpan.FromSeconds(10)));

                using (IBaseIdentityService service = CreateService())
                {
                    ApiVersionId version2 = new ApiVersionId("v2.0");

                    // test using the simple extension method
                    ApiVersion version = await service.GetApiVersionAsync(version2, cancellationTokenSource.Token);

                    Assert.IsNotNull(version);
                    Assert.AreEqual(version2, version.Id);
                }
            }
        }
        public HttpResponseMessage GetVersion([FromUri(Name = "versionId")] string versionIdString)
        {
            ValidateRequest(Request);

            ApiVersionId versionId = new ApiVersionId(versionIdString);

            JObject allVersions = JsonConvert.DeserializeObject<JObject>(IdentityServiceResources.ListApiVersionsResponse);
            ApiVersion[] versions = allVersions["versions"]["values"].ToObject<ApiVersion[]>();
            ApiVersion version = versions.FirstOrDefault(i => i.Id.Equals(versionId));

            if (version == null)
            {
                return new HttpResponseMessage(HttpStatusCode.NotFound);
            }
            else
            {
                HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);

                JObject responseObject = new JObject(new JProperty("version", JObject.FromObject(version)));
                response.Content = new StringContent(responseObject.ToString(Formatting.None), Encoding.UTF8, "application/json");

                return response;
            }
        }
        /// <inheritdoc/>
        /// <remarks>
        /// <para>Rackspace sends back the <c>media-types</c> property value wrapped in an additional JSON object, as
        /// opposed to the array OpenStack uses. This method overrides the behavior of the base OpenStack client to
        /// replace the unexpected structure with the correct layout prior to deserialization.</para>
        /// <note type="note">
        /// <para>If required, the original response is available via the <see cref="HttpResponseMessage.Content"/>
        /// property of the response.</para>
        /// </note>
        /// </remarks>
        public override Task <GetApiVersionApiCall> PrepareGetApiVersionAsync(ApiVersionId apiVersionId, CancellationToken cancellationToken)
        {
            UriTemplate template = new UriTemplate("{version_id}");
            Dictionary <string, string> parameters = new Dictionary <string, string> {
                { "version_id", apiVersionId.Value }
            };

            Func <HttpResponseMessage, CancellationToken, Task <ApiVersionResponse> > deserializeResult =
                (responseMessage, innerCancellationToken) =>
            {
                Uri originalUri = responseMessage.RequestMessage.RequestUri;

                if (!HttpApiCall.IsAcceptable(responseMessage))
                {
                    throw new HttpWebException(responseMessage);
                }

                return(responseMessage.Content.ReadAsStringAsync()
                       .Select(
                           innerTask =>
                {
                    if (string.IsNullOrEmpty(innerTask.Result))
                    {
                        return null;
                    }

                    JObject responseObject = JsonConvert.DeserializeObject <JObject>(innerTask.Result);
                    if (responseObject == null)
                    {
                        return null;
                    }

                    JObject versionObject = responseObject["version"] as JObject;
                    if (versionObject == null)
                    {
                        return responseObject.ToObject <ApiVersionResponse>();
                    }

                    JToken mediaTypesToken = versionObject["media-types"];
                    if (mediaTypesToken is JArray)
                    {
                        return responseObject.ToObject <ApiVersionResponse>();
                    }

                    JArray mediaTypesArray = mediaTypesToken["values"] as JArray;
                    if (mediaTypesArray == null)
                    {
                        versionObject.Remove("media-types");
                    }
                    else
                    {
                        versionObject["media-types"] = mediaTypesArray;
                    }

                    return responseObject.ToObject <ApiVersionResponse>();
                }));
            };

            return(GetBaseUriAsync(cancellationToken)
                   .Then(PrepareRequestAsyncFunc(HttpMethod.Get, template, parameters, cancellationToken))
                   .Select(task => new GetApiVersionApiCall(CreateCustomApiCall(task.Result, HttpCompletionOption.ResponseContentRead, deserializeResult))));
        }
        public async Task TestGetApiVersion2()
        {
            using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
            {
                cancellationTokenSource.CancelAfter(TestTimeout(TimeSpan.FromSeconds(10)));

                using (IBaseIdentityService service = CreateService())
                {
                    ApiVersionId version2 = new ApiVersionId("v2.0");

                    // test using the simple extension method
                    ApiVersion version = await service.GetApiVersionAsync(version2, cancellationTokenSource.Token);
                    Assert.IsNotNull(version);
                    Assert.AreEqual(version2, version.Id);
                }
            }
        }