public override Task <CosmosResponseMessage> SendAsync(CosmosRequestMessage request, CancellationToken cancellationToken)
            {
                if (this.UpdateRequestMessage != null)
                {
                    this.UpdateRequestMessage(request);
                }

                return(base.SendAsync(request, cancellationToken));
            }
示例#2
0
 private static void QueryPlanRequestEnricher(
     CosmosRequestMessage requestMessage)
 {
     requestMessage.Headers.Add(HttpConstants.HttpHeaders.ContentType, RuntimeConstants.MediaTypes.QueryJson);
     requestMessage.Headers.Add(HttpConstants.HttpHeaders.IsQueryPlanRequest, bool.TrueString);
     requestMessage.Headers.Add(HttpConstants.HttpHeaders.SupportedQueryFeatures, SupportedQueryFeaturesString);
     requestMessage.Headers.Add(HttpConstants.HttpHeaders.QueryVersion, new Version(major: 1, minor: 0).ToString());
     requestMessage.UseGatewayMode = true;
 }
示例#3
0
        public void IsDocumentFeed_ForChangeFeed()
        {
            CosmosRequestMessage request = new CosmosRequestMessage();

            request.OperationType       = OperationType.ReadFeed;
            request.ResourceType        = ResourceType.Document;
            request.PartitionKeyRangeId = "something";
            Assert.IsFalse(request.IsDocumentFeedOperation);
        }
示例#4
0
        public override Task <CosmosResponseMessage> SendAsync(CosmosRequestMessage request, CancellationToken cancellationToken)
        {
            CosmosResponseMessage httpResponse = null;

            if (request.Properties.TryGetValue(PreProcessingTestHandler.StatusCodeName, out object statusCodeOut))
            {
                httpResponse = new CosmosResponseMessage((HttpStatusCode)statusCodeOut);
            }

            return(Task.FromResult(httpResponse));
        }
示例#5
0
        /// <summary>
        /// Fill the CosmosRequestMessage headers with the set properties
        /// </summary>
        /// <param name="request">The <see cref="CosmosRequestMessage"/></param>
        public override void FillRequestOptions(CosmosRequestMessage request)
        {
            if (this.EnableScriptLogging)
            {
                request.Headers.Add(Documents.HttpConstants.HttpHeaders.EnableLogging, bool.TrueString);
            }

            RequestOptions.SetSessionToken(request, this.SessionToken);
            RequestOptions.SetConsistencyLevel(request, this.ConsistencyLevel);

            base.FillRequestOptions(request);
        }
示例#6
0
        public override Task <CosmosResponseMessage> SendAsync(
            CosmosRequestMessage request,
            CancellationToken cancellationToken)
        {
            CosmosRequestOptions promotedRequestOptions = request.RequestOptions;

            if (promotedRequestOptions != null)
            {
                // Fill request options
                promotedRequestOptions.FillRequestOptions(request);

                // Validate the request consistency compatibility with account consistency
                // Type based access context for requested consistency preferred for performance
                ConsistencyLevel?consistencyLevel = null;
                if (promotedRequestOptions is CosmosItemRequestOptions)
                {
                    consistencyLevel = (promotedRequestOptions as CosmosItemRequestOptions).ConsistencyLevel;
                }
                else if (promotedRequestOptions is CosmosQueryRequestOptions)
                {
                    consistencyLevel = (promotedRequestOptions as CosmosQueryRequestOptions).ConsistencyLevel;
                }
                else if (promotedRequestOptions is CosmosStoredProcedureRequestOptions)
                {
                    consistencyLevel = (promotedRequestOptions as CosmosStoredProcedureRequestOptions).ConsistencyLevel;
                }

                if (consistencyLevel.HasValue)
                {
                    if (!ValidationHelpers.ValidateConsistencyLevel(this.client.AccountConsistencyLevel, consistencyLevel.Value))
                    {
                        throw new ArgumentException(string.Format(
                                                        CultureInfo.CurrentUICulture,
                                                        RMResources.InvalidConsistencyLevel,
                                                        consistencyLevel.Value.ToString(),
                                                        this.client.AccountConsistencyLevel));
                    }
                }
            }

            return(this.client.DocumentClient.EnsureValidClientAsync()
                   .ContinueWith(task => request.AssertPartitioningDetailsAsync(client, cancellationToken))
                   .ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    throw task.Exception;
                }

                return base.SendAsync(request, cancellationToken);
            })
                   .Unwrap());
        }
        public override async Task <CosmosResponseMessage> SendAsync(
            CosmosRequestMessage request,
            CancellationToken cancellationToken)
        {
            var response = await base.SendAsync(request, cancellationToken);

            if (response.StatusCode == System.Net.HttpStatusCode.PreconditionFailed)
            {
                response.Headers.Set("x-ms-substatus", "999");
            }

            return(response);
        }
示例#8
0
        public void IsDocumentFeed_ForOtherOperations()
        {
            CosmosRequestMessage request = new CosmosRequestMessage();

            request.OperationType = OperationType.Upsert;
            request.ResourceType  = ResourceType.Document;
            Assert.IsFalse(request.IsDocumentFeedOperation);

            CosmosRequestMessage request2 = new CosmosRequestMessage();

            request2.OperationType = OperationType.ReadFeed;
            request2.ResourceType  = ResourceType.Database;
            Assert.IsFalse(request2.IsDocumentFeedOperation);
        }
示例#9
0
        public override async Task <CosmosResponseMessage> SendAsync(
            CosmosRequestMessage request,
            CancellationToken cancellationToken)
        {
            using (Microsoft.ApplicationInsights.Extensibility.IOperationHolder <RequestTelemetry> operation = this.telemetryClient.StartOperation <RequestTelemetry>("CosmosDBRequest"))
            {
                this.telemetryClient.TrackTrace($"{request.Method.Method} - {request.RequestUri.ToString()}");
                CosmosResponseMessage response = await base.SendAsync(request, cancellationToken);

                operation.Telemetry.ResponseCode = ((int)response.StatusCode).ToString();
                operation.Telemetry.Success      = response.IsSuccessStatusCode;

                this.telemetryClient.StopOperation(operation);
                return(response);
            }
        }
        public override Task <CosmosResponseMessage> SendAsync(
            CosmosRequestMessage request,
            CancellationToken cancellationToken)
        {
            CosmosRequestHandler targetHandler = null;

            if (request.IsPartitionedFeedOperation)
            {
                targetHandler = documentFeedHandler;
            }
            else
            {
                targetHandler = pointOperationHandler;
            }

            return(targetHandler.SendAsync(request, cancellationToken));
        }
示例#11
0
        public override Task <CosmosResponseMessage> SendAsync(
            CosmosRequestMessage request,
            CancellationToken cancellationToken)
        {
            CosmosRequestHandler targetHandler = null;

            if (request.OperationType == OperationType.ReadFeed && request.ResourceType == ResourceType.Document)
            {
                targetHandler = doucumentFeedHandler;
            }
            else
            {
                targetHandler = pointOperationHandler;
            }

            return(targetHandler.SendAsync(request, cancellationToken));
        }
        public override async Task <CosmosResponseMessage> SendAsync(
            CosmosRequestMessage request,
            CancellationToken cancellationToken)
        {
            IDocumentClientRetryPolicy retryPolicyInstance = await this.GetRetryPolicy(request);

            try
            {
                return(await RetryHandler.ExecuteHttpRequestAsync(
                           callbackMethod : () =>
                {
                    return base.SendAsync(request, cancellationToken);
                },
                           callShouldRetry : (cosmosResponseMessage, token) =>
                {
                    return retryPolicyInstance.ShouldRetryAsync(cosmosResponseMessage, cancellationToken);
                },
                           callShouldRetryException : (exception, token) =>
                {
                    return retryPolicyInstance.ShouldRetryAsync(exception, cancellationToken);
                },
                           cancellationToken : cancellationToken));
            }
            catch (DocumentClientException ex)
            {
                return(ex.ToCosmosResponseMessage(request));
            }
            catch (AggregateException ex)
            {
                // TODO: because the SDK underneath this path uses ContinueWith or task.Result we need to catch AggregateExceptions here
                // in order to ensure that underlying DocumentClientExceptions get propagated up correctly. Once all ContinueWith and .Result
                // is removed this catch can be safely removed.
                AggregateException innerExceptions    = ex.Flatten();
                Exception          docClientException = innerExceptions.InnerExceptions.FirstOrDefault(innerEx => innerEx is DocumentClientException);
                if (docClientException != null)
                {
                    return(((DocumentClientException)docClientException).ToCosmosResponseMessage(request));
                }

                throw;
            }
        }
        public async Task RetryHandlerHttpClientExceptionRefreshesLocations()
        {
            DocumentClient dc     = new MockDocumentClient(RetryHandlerTests.TestUri, "test");
            CosmosClient   client = new CosmosClient(new CosmosClientConfiguration(RetryHandlerTests.TestUri.OriginalString, Guid.NewGuid().ToString()), dc);

            Mock <IDocumentClientRetryPolicy> mockClientRetryPolicy = new Mock <IDocumentClientRetryPolicy>();

            mockClientRetryPolicy.Setup(m => m.ShouldRetryAsync(It.IsAny <Exception>(), It.IsAny <CancellationToken>()))
            .Returns <Exception, CancellationToken>((ex, tooken) => Task.FromResult(ShouldRetryResult.RetryAfter(TimeSpan.FromMilliseconds(1))));

            Mock <IRetryPolicyFactory> mockRetryPolicy = new Mock <IRetryPolicyFactory>();

            mockRetryPolicy.Setup(m => m.GetRequestPolicy())
            .Returns(() => mockClientRetryPolicy.Object);

            RetryHandler retryHandler         = new RetryHandler(mockRetryPolicy.Object);
            int          handlerCalls         = 0;
            int          expectedHandlerCalls = 2;
            TestHandler  testHandler          = new TestHandler((request, response) => {
                handlerCalls++;
                if (handlerCalls == expectedHandlerCalls)
                {
                    return(TestHandler.ReturnSuccess());
                }

                throw new HttpRequestException("DNS or some other network issue");
            });

            retryHandler.InnerHandler = testHandler;
            RequestInvokerHandler invoker = new RequestInvokerHandler(client);

            invoker.InnerHandler = retryHandler;
            CosmosRequestMessage requestMessage = new CosmosRequestMessage(HttpMethod.Get, new System.Uri("https://dummy.documents.azure.com:443/dbs"));

            requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]");
            requestMessage.ResourceType  = ResourceType.Document;
            requestMessage.OperationType = OperationType.Read;
            await invoker.SendAsync(requestMessage, new CancellationToken());

            Assert.AreEqual(expectedHandlerCalls, handlerCalls);
        }
        public async Task PartitionKeyRangeGoneRetryHandlerOnSuccess()
        {
            CosmosClient client = MockDocumentClient.CreateMockCosmosClient();

            PartitionKeyRangeGoneRetryHandler retryHandler = new PartitionKeyRangeGoneRetryHandler(client);
            int         handlerCalls         = 0;
            int         expectedHandlerCalls = 1;
            TestHandler testHandler          = new TestHandler((request, cancellationToken) => {
                handlerCalls++;
                return(TestHandler.ReturnSuccess());
            });

            retryHandler.InnerHandler = testHandler;
            RequestInvokerHandler invoker = new RequestInvokerHandler(client);

            invoker.InnerHandler = retryHandler;
            CosmosRequestMessage requestMessage = new CosmosRequestMessage(HttpMethod.Get, new Uri("https://dummy.documents.azure.com:443/dbs"));
            await invoker.SendAsync(requestMessage, new CancellationToken());

            Assert.AreEqual(expectedHandlerCalls, handlerCalls);
        }
        public void ValidateSetItemRequestOptions()
        {
            CosmosItemRequestOptions options = new CosmosItemRequestOptions();

            options.PreTriggers = new List <string>()
            {
                "preTrigger"
            };
            options.PostTriggers = new List <string>()
            {
                "postTrigger"
            };

            CosmosRequestMessage httpRequest = new CosmosRequestMessage(
                HttpMethod.Post,
                new Uri("/dbs/testdb/colls/testcontainer/docs/testId", UriKind.Relative));

            options.FillRequestOptions(httpRequest);

            Assert.IsTrue(httpRequest.Headers.TryGetValue(HttpConstants.HttpHeaders.PreTriggerInclude, out string preTriggerHeader));
            Assert.IsTrue(httpRequest.Headers.TryGetValue(HttpConstants.HttpHeaders.PostTriggerInclude, out string postTriggerHeader));
        }
        public async Task VerifySendUsesOringianlContinuationOnDocumentClientExceptionAfterRetry()
        {
            Mock <PartitionRoutingHelper> partitionRoutingHelperMock = this.GetPartitionRoutingHelperMock();

            //throw a DocumentClientException
            partitionRoutingHelperMock.Setup(m => m.TryAddPartitionKeyRangeToContinuationTokenAsync(
                                                 It.IsAny <INameValueCollection>(),
                                                 It.IsAny <List <Range <string> > >(),
                                                 It.IsAny <IRoutingMapProvider>(),
                                                 It.Is <string>(x => x == CollectionId),
                                                 It.IsAny <ResolvedRangeInfo>(),
                                                 It.IsAny <RntbdConstants.RntdbEnumerationDirection>()
                                                 )).ThrowsAsync(new DocumentClientException("error", HttpStatusCode.ServiceUnavailable, SubStatusCodes.Unknown));

            PartitionKeyRangeHandler partitionKeyRangeHandler = new PartitionKeyRangeHandler(MockCosmosUtil.CreateMockCosmosClient(), partitionRoutingHelperMock.Object);

            TestHandler testHandler = new TestHandler(async(request, cancellationToken) => {
                CosmosResponseMessage successResponse = await TestHandler.ReturnSuccess();
                successResponse.Headers.Remove(HttpConstants.HttpHeaders.Continuation); //Clobber original continuation
                return(successResponse);
            });

            partitionKeyRangeHandler.InnerHandler = testHandler;

            //Pass valid collections path because it is required by DocumentServiceRequest's constructor. This can't be mocked because ToDocumentServiceRequest() is an extension method
            CosmosRequestMessage initialRequest = new CosmosRequestMessage(HttpMethod.Get, new Uri($"{Paths.DatabasesPathSegment}/test/{Paths.CollectionsPathSegment}/test", UriKind.Relative));

            initialRequest.OperationType = OperationType.ReadFeed;
            initialRequest.Headers.Add(HttpConstants.HttpHeaders.Continuation, Continuation);
            CosmosResponseMessage response = await partitionKeyRangeHandler.SendAsync(initialRequest, CancellationToken.None);

            Assert.IsFalse(response.IsSuccessStatusCode);
            Assert.AreEqual(System.Net.HttpStatusCode.ServiceUnavailable, response.StatusCode);
            //Check if original continuation was restored
            Assert.AreEqual(Continuation, response.Headers.GetValues(HttpConstants.HttpHeaders.Continuation).First());
            Assert.AreEqual(Continuation, initialRequest.Headers.GetValues(HttpConstants.HttpHeaders.Continuation).First());
        }
        public async Task RequestOptionsHandlerCanHandleRequestOptions()
        {
            const string         PropertyKey   = "propkey";
            const string         Condition     = "*";
            object               propertyValue = Encoding.UTF8.GetBytes("test");
            CosmosRequestOptions options       = new CosmosItemRequestOptions
            {
                Properties = new Dictionary <string, object>(new List <KeyValuePair <string, object> > {
                    new KeyValuePair <string, object>(PropertyKey, propertyValue)
                }),
                AccessCondition = new AccessCondition
                {
                    Type      = AccessConditionType.IfMatch,
                    Condition = Condition
                }
            };

            TestHandler testHandler = new TestHandler((request, cancellationToken) => {
                Assert.AreEqual(propertyValue, request.Properties[PropertyKey]);
                Assert.AreEqual(Condition, request.Headers.GetValues(HttpConstants.HttpHeaders.IfMatch).First());
                return(TestHandler.ReturnSuccess());
            });

            CosmosClient client = MockDocumentClient.CreateMockCosmosClient();

            RequestInvokerHandler invoker = new RequestInvokerHandler(client);

            invoker.InnerHandler = testHandler;
            CosmosRequestMessage requestMessage = new CosmosRequestMessage(HttpMethod.Get, new System.Uri("https://dummy.documents.azure.com:443/dbs"));

            requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]");
            requestMessage.ResourceType   = ResourceType.Document;
            requestMessage.OperationType  = OperationType.Read;
            requestMessage.RequestOptions = options;

            await invoker.SendAsync(requestMessage, new CancellationToken());
        }
示例#18
0
        internal static CosmosResponseMessage AggregateExceptionConverter(AggregateException aggregateException, CosmosRequestMessage request)
        {
            AggregateException      innerExceptions    = aggregateException.Flatten();
            DocumentClientException docClientException = (DocumentClientException)innerExceptions.InnerExceptions.FirstOrDefault(innerEx => innerEx is DocumentClientException);

            if (docClientException != null)
            {
                return(docClientException.ToCosmosResponseMessage(request));
            }

            Exception       exception       = innerExceptions.InnerExceptions.FirstOrDefault(innerEx => innerEx is CosmosException);
            CosmosException cosmosException = exception as CosmosException;

            if (cosmosException != null)
            {
                return(new CosmosResponseMessage(
                           headers: cosmosException.Headers,
                           requestMessage: request,
                           errorMessage: cosmosException.Message,
                           statusCode: cosmosException.StatusCode,
                           error: cosmosException.Error));
            }

            return(null);
        }
示例#19
0
 internal override async Task <IDocumentClientRetryPolicy> GetRetryPolicyAsync(CosmosRequestMessage request)
 {
     return(new InvalidPartitionExceptionRetryPolicy(await client.DocumentClient.GetCollectionCacheAsync(), null));
 }
 internal abstract Task <IDocumentClientRetryPolicy> GetRetryPolicy(CosmosRequestMessage request);
        public override async Task <CosmosResponseMessage> SendAsync(
            CosmosRequestMessage request,
            CancellationToken cancellationToken)
        {
            CosmosResponseMessage response = null;
            string originalContinuation    = request.Headers.Continuation;

            try
            {
                RntdbEnumerationDirection rntdbEnumerationDirection = RntdbEnumerationDirection.Forward;
                object direction;
                if (request.Properties.TryGetValue(HttpConstants.HttpHeaders.EnumerationDirection, out direction))
                {
                    rntdbEnumerationDirection = (byte)RntdbEnumerationDirection.Reverse == (byte)direction ? RntdbEnumerationDirection.Reverse : RntdbEnumerationDirection.Forward;
                }

                request.Headers.Remove(HttpConstants.HttpHeaders.IsContinuationExpected);
                request.Headers.Add(HttpConstants.HttpHeaders.IsContinuationExpected, bool.TrueString);

                object startEpk;
                object endEpk;
                if (!request.Properties.TryGetValue(HandlerConstants.StartEpkString, out startEpk))
                {
                    startEpk = PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey;
                }
                if (!request.Properties.TryGetValue(HandlerConstants.EndEpkString, out endEpk))
                {
                    endEpk = PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey;
                }
                startEpk = startEpk ?? PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey;
                endEpk   = endEpk ?? PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey;

                List <Range <string> > providedRanges = new List <Range <string> > {
                    new Range <string>(
                        (string)startEpk,
                        (string)endEpk,
                        isMinInclusive: true,
                        isMaxInclusive: false)
                };

                DocumentServiceRequest serviceRequest = request.ToDocumentServiceRequest();

                PartitionKeyRangeCache routingMapProvider = await this.client.DocumentClient.GetPartitionKeyRangeCacheAsync();

                CollectionCache collectionCache = await this.client.DocumentClient.GetCollectionCacheAsync();

                CosmosContainerSettings collectionFromCache =
                    await collectionCache.ResolveCollectionAsync(serviceRequest, CancellationToken.None);

                List <CompositeContinuationToken> suppliedTokens;
                //direction is not expected to change  between continuations.
                Range <string> rangeFromContinuationToken =
                    this.partitionRoutingHelper.ExtractPartitionKeyRangeFromContinuationToken(serviceRequest.Headers, out suppliedTokens);

                ResolvedRangeInfo resolvedRangeInfo =
                    await this.partitionRoutingHelper.TryGetTargetRangeFromContinuationTokenRange(
                        providedPartitionKeyRanges : providedRanges,
                        routingMapProvider : routingMapProvider,
                        collectionRid : collectionFromCache.ResourceId,
                        rangeFromContinuationToken : rangeFromContinuationToken,
                        suppliedTokens : suppliedTokens,
                        direction : rntdbEnumerationDirection);

                if (serviceRequest.IsNameBased && resolvedRangeInfo.ResolvedRange == null && resolvedRangeInfo.ContinuationTokens == null)
                {
                    serviceRequest.ForceNameCacheRefresh = true;
                    collectionFromCache = await collectionCache.ResolveCollectionAsync(serviceRequest, CancellationToken.None);

                    resolvedRangeInfo = await this.partitionRoutingHelper.TryGetTargetRangeFromContinuationTokenRange(
                        providedPartitionKeyRanges : providedRanges,
                        routingMapProvider : routingMapProvider,
                        collectionRid : collectionFromCache.ResourceId,
                        rangeFromContinuationToken : rangeFromContinuationToken,
                        suppliedTokens : suppliedTokens,
                        direction : rntdbEnumerationDirection);
                }

                if (resolvedRangeInfo.ResolvedRange == null && resolvedRangeInfo.ContinuationTokens == null)
                {
                    return(((DocumentClientException)
                            new NotFoundException(
                                $"{DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)}: Was not able to get queryRoutingInfo even after resolve collection async with force name cache refresh to the following collectionRid: {collectionFromCache.ResourceId} with the supplied tokens: {JsonConvert.SerializeObject(suppliedTokens)}")
                            ).ToCosmosResponseMessage(request));
                }

                serviceRequest.RouteTo(new PartitionKeyRangeIdentity(collectionFromCache.ResourceId, resolvedRangeInfo.ResolvedRange.Id));

                response = await base.SendAsync(request, cancellationToken);

                if (!response.IsSuccessStatusCode)
                {
                    this.SetOriginalContinuationToken(request, response, originalContinuation);
                }
                else
                {
                    if (!await this.partitionRoutingHelper.TryAddPartitionKeyRangeToContinuationTokenAsync(
                            response.Headers.CosmosMessageHeaders,
                            providedPartitionKeyRanges: providedRanges,
                            routingMapProvider: routingMapProvider,
                            collectionRid: collectionFromCache.ResourceId,
                            resolvedRangeInfo: resolvedRangeInfo,
                            direction: rntdbEnumerationDirection))
                    {
                        return(((DocumentClientException)
                                new NotFoundException(
                                    $"{DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)}: Call to TryAddPartitionKeyRangeToContinuationTokenAsync failed to the following collectionRid: {collectionFromCache.ResourceId} with the supplied tokens: {JsonConvert.SerializeObject(suppliedTokens)}")
                                ).ToCosmosResponseMessage(request));
                    }
                }

                return(response);
            }
            catch (DocumentClientException ex)
            {
                CosmosResponseMessage errorResponse = ex.ToCosmosResponseMessage(request);
                this.SetOriginalContinuationToken(request, errorResponse, originalContinuation);
                return(errorResponse);
            }
            catch (AggregateException ex)
            {
                this.SetOriginalContinuationToken(request, response, originalContinuation);

                // TODO: because the SDK underneath this path uses ContinueWith or task.Result we need to catch AggregateExceptions here
                // in order to ensure that underlying DocumentClientExceptions get propagated up correctly. Once all ContinueWith and .Result
                // is removed this catch can be safely removed.
                AggregateException innerExceptions    = ex.Flatten();
                Exception          docClientException = innerExceptions.InnerExceptions.FirstOrDefault(innerEx => innerEx is DocumentClientException);
                if (docClientException != null)
                {
                    return(((DocumentClientException)docClientException).ToCosmosResponseMessage(request));
                }

                throw;
            }
        }
 internal override async Task <IDocumentClientRetryPolicy> GetRetryPolicyAsync(CosmosRequestMessage request)
 {
     return(new PartitionKeyRangeGoneRetryPolicy(
                await client.DocumentClient.GetCollectionCacheAsync(),
                await client.DocumentClient.GetPartitionKeyRangeCacheAsync(),
                PathsHelper.GetCollectionPath(request.RequestUri.ToString()),
                null));
 }