/// <summary>
        /// Puts given payload in an operation for a changeset.
        /// </summary>
        /// <typeparam name="T"> Must be a PayloadTestDescriptor.</typeparam>
        /// <param name="payload">Payload to be put into changeset operation.</param>
        /// <param name="verb">Verb associated with payload.</param>
        /// <param name="baseUri">Baseuri for operation.</param>
        /// <param name="requestManager">RequestManager to build the request</param>
        /// <param name="contentType">The (optional) content type to be used for the operation content.</param>
        /// <returns>IHttpRequest containing payload with specified verb and uri</returns>
        public static ODataRequest InRequestOperation <T>(
            this T payload,
            HttpVerb verb,
            ODataUri baseUri,
            IODataRequestManager requestManager,
            string contentType = null) where T : PayloadTestDescriptor
        {
            ExceptionUtilities.CheckArgumentNotNull(payload, "payload");
            ExceptionUtilities.CheckArgumentNotNull(verb, "verb");
            ExceptionUtilities.CheckArgumentNotNull(baseUri, "baseUri");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");

            var headers = new Dictionary <string, string> {
                { "GivenPayloadRequestHeader", "PayloadHeaderValue" }
            };

            var request = requestManager.BuildRequest(baseUri, verb, headers);

            if (payload.PayloadElement != null)
            {
                if (string.IsNullOrEmpty(contentType))
                {
                    contentType = payload.PayloadElement.GetDefaultContentType();
                }

                contentType = HttpUtilities.BuildContentType(contentType, Encoding.UTF8.WebName, null);
                request.Headers.Add(Microsoft.OData.Core.ODataConstants.ContentTypeHeader, contentType);
                request.Body = requestManager.BuildBody(contentType, baseUri, payload.PayloadElement);
            }

            return(request);
        }
        /// <summary>
        /// Puts payload in a batch response.
        /// </summary>
        /// <typeparam name="T">T must be a PayloadTestDescriptor.</typeparam>
        /// <param name="originalPayload">Payload to be inserted into batch.</param>
        /// <param name="statusCode">Status code associated with payload</param>
        /// <param name="random">Use of random makes this method non deterministic</param>
        /// <param name="requestManager">Used to construct the response payload.</param>
        /// <param name="inChangeset">Specifies whether this is in a changeset or an operation.</param>
        /// <param name="operationsBefore">Number of operations/changesets to go before payload.</param>
        /// <param name="operationsAfter">Number of operations/changesets to go after payload.</param>
        /// <param name="version">Maximum version for extra generated payloads</param>
        /// <returns>Test descriptor for the new BatchResponsePayload.</returns>
        public static T InBatchResponse <T>(
            this T originalPayload,
            int statusCode,
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            bool inChangeset     = false,
            int operationsBefore = 0,
            int operationsAfter  = 0,
            ODataVersion version = ODataVersion.V4
            ) where T : PayloadTestDescriptor
        {
            ExceptionUtilities.CheckArgumentNotNull(originalPayload, "originalPayload");
            ExceptionUtilities.CheckArgumentNotNull(statusCode, "statusCode");
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            var payload = (T)originalPayload.Clone();

            var headers = new Dictionary <string, string> {
                { "ResponseHeader", "ResponseValue" }
            };
            var baseUri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org/service.svc")));

            IMimePart[] extraoperations = BatchUtils.ExtraResponseChangesets(random, (EdmModel)payload.PayloadEdmModel, version);  // add extraChangesets methods
            extraoperations.Concat(BatchUtils.ExtraResponseOperations(random, (EdmModel)payload.PayloadEdmModel, version));

            //Work out the operations and changesets to go before the payload
            var parts = Enumerable.Range(0, operationsBefore).Select(i => random.ChooseFrom(extraoperations));

            if (!inChangeset)
            {
                extraoperations.ConcatSingle(payload.InResponseOperation(statusCode, requestManager));
            }
            else
            {
                extraoperations.ConcatSingle(payload.InResponseChangeset(statusCode, random, requestManager, random.NextFromRange(0, 2), random.NextFromRange(0, 2), version));
            }

            parts.Concat(Enumerable.Range(0, operationsAfter).Select(i => random.ChooseFrom(extraoperations)));

            var batchResponse = new BatchResponsePayload();

            foreach (var part in parts)
            {
                HttpResponseData operation = part as HttpResponseData;
                if (operation != null)
                {
                    batchResponse.Add(operation.AsBatchFragment());
                }

                BatchResponseChangeset changeset = part as BatchResponseChangeset;
                if (changeset != null)
                {
                    batchResponse.Add(changeset);
                }
            }

            //payload.PayloadEdmModel.Fixup();
            payload.PayloadElement = batchResponse;
            return(payload);
        }
Beispiel #3
0
        /// <summary>
        /// Generates extra request changesets.
        /// </summary>
        /// <param name="random">For generating arbitrary changesets.</param>
        /// <param name="requestManager">For building changesets.</param>
        /// <param name="model">For adding any generated types to.</param>
        /// <param name="baseUri">Base uri for the changesets.</param>
        /// <param name="version">Maximum version of any generated types.</param>
        /// <returns>An array of request changesets.</returns>
        public static BatchRequestChangeset[] ExtraRequestChangesets(
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            EdmModel model,
            ODataUri baseUri,
            ODataVersion version = ODataVersion.V4
            )
        {
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            ExceptionUtilities.CheckArgumentNotNull(baseUri, "baseUri");

            var headers = new Dictionary <string, string> {
                { "RequestHeader", "RequestHeaderValue" }
            };
            string mergeContentType = HttpUtilities.BuildContentType(MimeTypes.ApplicationXml, Encoding.UTF8.WebName, null);

            var requests = ExtraRequestChangesetOperations(random, requestManager, model, baseUri, version);

            List <BatchRequestChangeset> changesets = new List <BatchRequestChangeset>();

            for (int x = 0; x < 5; ++x)
            {
                IEnumerable <IHttpRequest> operations = Enumerable.Range(0, random.Next(10)).Select(i => random.ChooseFrom(requests));
                changesets.Add(BatchPayloadBuilder.RequestChangeset("changeset_" + Guid.NewGuid().ToString(), "", operations.ToArray()));
            }

            return(changesets.ToArray());
        }
        /// <summary>
        /// Puts the specified <paramref name="payload"/> into a changeset.
        /// </summary>
        /// <param name="payload">The payload to be used as content for the expanded link.</param>
        /// <param name="verb">The verb associated with the payload.</param>
        /// <param name="random">Use of random makes this method non deterministic.</param>
        /// <param name="requestManager">Used to construct requests</param>
        /// <param name="operationsBefore">Number of extra operations before payload.</param>
        /// <param name="operationsAfter">Number of extra operations after payload.</param>
        /// <param name="version">Highest version of allowed features</param>
        /// <returns>An entry payload with an expanded link that contains the specified <paramref name="payload"/>.</returns>
        public static BatchRequestChangeset InRequestChangeset <T>(
            this T payload,
            HttpVerb verb,
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            int operationsBefore = 0,
            int operationsAfter  = 0,
            ODataVersion version = ODataVersion.V4
            ) where T : PayloadTestDescriptor
        {
            ExceptionUtilities.CheckArgumentNotNull(payload, "payload");
            ExceptionUtilities.CheckArgumentNotNull(verb, "verb");
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");

            var baseUri         = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org/service.svc")));
            var extraOperations = BatchUtils.ExtraRequestChangesetOperations(random, requestManager, (EdmModel)payload.PayloadEdmModel, baseUri, version);

            // Build the list of all properties
            IEnumerable <IHttpRequest> operations = Enumerable.Range(0, operationsBefore).Select(i => random.ChooseFrom(extraOperations));

            operations.ConcatSingle(payload.InRequestOperation(verb, baseUri, requestManager));
            operations = operations.Concat(Enumerable.Range(0, operationsAfter).Select(i => extraOperations[extraOperations.Length - 1 - (i % extraOperations.Length)]));

            var changeset = BatchPayloadBuilder.RequestChangeset("changeset_" + Guid.NewGuid().ToString(), Encoding.UTF8.WebName, operations.ToArray());

            return(changeset);
        }
Beispiel #5
0
        /// <summary>
        /// Generates extra operations to go into a request changeset
        /// </summary>
        /// <param name="random">For generating the payloads to go in the extra operations</param>
        /// <param name="requestManager">For building the operations</param>
        /// <param name="model">To add any new types to.</param>
        /// <param name="baseUri">Base uri for the extra operations.</param>
        /// <param name="version">Maximum version for </param>
        /// <returns>An array of extra request operations.</returns>
        public static IHttpRequest[] ExtraRequestChangesetOperations(
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            EdmModel model,
            ODataUri baseUri,
            ODataVersion version = ODataVersion.V4)
        {
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            ExceptionUtilities.CheckArgumentNotNull(baseUri, "baseUri");
            var headers = new Dictionary <string, string> {
                { "RequestHeader", "RequestHeaderValue" }
            };
            string mergeContentType = HttpUtilities.BuildContentType(MimeTypes.ApplicationXml, Encoding.UTF8.WebName, null);

            List <IHttpRequest> requests = new List <IHttpRequest>();
            ODataRequest        request  = null;

            for (int i = 0; i < 4; i++)
            {
                request      = requestManager.BuildRequest(baseUri, HttpVerb.Post, headers);
                request.Body = requestManager.BuildBody(mergeContentType, baseUri, RandomPayloadBuilder.GetRandomPayload(random, model, version));
                requests.Add(request);
                request      = requestManager.BuildRequest(baseUri, HttpVerb.Put, headers);
                request.Body = requestManager.BuildBody(mergeContentType, baseUri, RandomPayloadBuilder.GetRandomPayload(random, model, version));
                requests.Add(request);
                request      = requestManager.BuildRequest(baseUri, HttpVerb.Patch, headers);
                request.Body = requestManager.BuildBody(mergeContentType, baseUri, RandomPayloadBuilder.GetRandomPayload(random, model, version));
                requests.Add(request);
                request = requestManager.BuildRequest(baseUri, HttpVerb.Delete, headers);
                requests.Add(request);
            }

            return(requests.ToArray());
        }
Beispiel #6
0
        /// <summary>
        /// Generates extra operations to go into a request changeset
        /// </summary>
        /// <param name="random">For generating the payloads to go in the extra operations</param>
        /// <param name="requestManager">For building the operations</param>
        /// <param name="model">To add any new types to.</param>
        /// <param name="baseUri">Base uri for the extra operations.</param>
        /// <param name="version">Maximum version for </param>
        /// <returns>An array of extra request operations.</returns>
        public static IHttpRequest[] ExtraRequestChangesetOperations(
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            EdmModel model,
            ODataUri baseUri,
            ODataVersion version = ODataVersion.V4)
        {
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            ExceptionUtilities.CheckArgumentNotNull(baseUri, "baseUri");
            var headers = new Dictionary<string, string> { { "RequestHeader", "RequestHeaderValue" } };
            string mergeContentType = HttpUtilities.BuildContentType(MimeTypes.ApplicationXml, Encoding.UTF8.WebName, null);

            List<IHttpRequest> requests = new List<IHttpRequest>();
            ODataRequest request = null;
            for (int i = 0; i < 4; i++)
            {
                request = requestManager.BuildRequest(baseUri, HttpVerb.Post, headers);
                request.Body = requestManager.BuildBody(mergeContentType, baseUri, RandomPayloadBuilder.GetRandomPayload(random, model, version));
                requests.Add(request);
                request = requestManager.BuildRequest(baseUri, HttpVerb.Put, headers);
                request.Body = requestManager.BuildBody(mergeContentType, baseUri, RandomPayloadBuilder.GetRandomPayload(random, model, version));
                requests.Add(request);
                request = requestManager.BuildRequest(baseUri, HttpVerb.Patch, headers);
                request.Body = requestManager.BuildBody(mergeContentType, baseUri, RandomPayloadBuilder.GetRandomPayload(random, model, version));
                requests.Add(request);
                request = requestManager.BuildRequest(baseUri, HttpVerb.Delete, headers);
                requests.Add(request);
            }

            return requests.ToArray();
        }
        /// <summary>
        /// Puts payload in a batch request.
        /// </summary>
        /// <typeparam name="T">T must be a PayloadTestDescriptor.</typeparam>
        /// <param name="originalPayload">Payload to put into batch.</param>
        /// <param name="verb">HttpVerb associated with payload.</param>
        /// <param name="random">Use of random makes this method non deterministic.</param>
        /// <param name="requestManager">Used to construct requests.</param>
        /// <param name="operationsBefore">Number of operations/changesets to go before payload.</param>
        /// <param name="operationsAfter">Number of operations/changesets to go after payload.</param>
        /// <param name="version">Maximum version for extra payloads</param>
        /// <returns>The test descriptor for the new BatchRequestPayload</returns>
        public static T InBatchRequest <T>(
            this T originalPayload,
            HttpVerb verb,
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            int operationsBefore = 0,
            int operationsAfter  = 0,
            ODataVersion version = ODataVersion.V4
            ) where T : PayloadTestDescriptor
        {
            ExceptionUtilities.CheckArgumentNotNull(originalPayload, "originalPayload");
            ExceptionUtilities.CheckArgumentNotNull(verb, "verb");
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            var payload = (T)originalPayload.Clone();

            var baseUri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org/service.svc")));

            IMimePart[] extraOperations = BatchUtils.ExtraRequestChangesets(random, requestManager, (EdmModel)payload.PayloadEdmModel, baseUri, version);  // add extraChangesets methods
            extraOperations.Concat(BatchUtils.ExtraRequestChangesets(random, requestManager, (EdmModel)payload.PayloadEdmModel, baseUri, version));

            //Work out the operations and changesets to go before the payload
            var parts = Enumerable.Range(0, operationsBefore).Select(i => random.ChooseFrom(extraOperations));

            if (verb != HttpVerb.Get)
            {
                extraOperations.ConcatSingle(payload.InRequestOperation(HttpVerb.Get, baseUri, requestManager));
            }
            else
            {
                extraOperations.ConcatSingle(payload.InRequestChangeset(verb, random, requestManager, random.NextFromRange(0, 2), random.NextFromRange(0, 2), version));
            }

            parts.Concat(Enumerable.Range(0, operationsAfter).Select(i => random.ChooseFrom(extraOperations)));

            var batchRequest = new BatchRequestPayload();

            foreach (var part in parts)
            {
                IHttpRequest operation = part as IHttpRequest;
                if (operation != null)
                {
                    batchRequest.Add(operation.AsBatchFragment());
                }
                BatchRequestChangeset changeset = part as BatchRequestChangeset;
                if (changeset != null)
                {
                    batchRequest.Add(changeset);
                }
            }

            //payload.PayloadEdmModel.Fixup();
            payload.PayloadElement = batchRequest;
            return(payload);
        }
        /// <summary>
        /// Returns the query option values with a strict sorting
        /// </summary>
        /// <param name="uri">The current uri</param>
        /// <returns>The uri's query options after sorting</returns>
        protected override IEnumerable<KeyValuePair<string, string>> GetSortedQueryOptions(ODataUri uri)
        {
            List<KeyValuePair<string, string>> queryOptions = new List<KeyValuePair<string, string>>();

            // NOTE: this is set up partly to match the order the product uses for next-links. We may need to make this more customizable.
            queryOptions.AddRange(uri.CustomQueryOptions);

            if (uri.Filter != null)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.Filter, uri.Filter));
            }

            if (uri.ExpandSegments.Count > 0)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.Expand, this.ConcatenateSegments(uri.ExpandSegments)));
            }

            if (uri.OrderBy != null)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.OrderBy, uri.OrderBy));
            }

            if (uri.InlineCount != null)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.InlineCount, uri.InlineCount));
            }

            if (uri.SelectSegments.Count > 0)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.Select, this.ConcatenateSegments(uri.SelectSegments)));
            }

            if (uri.Top.HasValue)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.Top, uri.Top.Value.ToString(CultureInfo.InvariantCulture)));
            }

            if (uri.Skip.HasValue)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.Skip, uri.Skip.Value.ToString(CultureInfo.InvariantCulture)));
            }

            if (uri.SkipToken != null)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.SkipToken, uri.SkipToken));
            }

            if (uri.Format != null)
            {
                queryOptions.Add(new KeyValuePair<string, string>(QueryOptions.Format, uri.Format));
            }

            return queryOptions;
        }
Beispiel #9
0
            /// <summary>
            /// Converts an ODataBatchOperation to the corresponding IMimePart.
            /// </summary>
            /// <param name="operation">The operation to convert.</param>
            /// <returns>The converted operation.</returns>
            private IMimePart ConvertBatchOperation(ODataBatchOperation operation)
            {
                ODataPayloadElement payloadElement = operation.Payload == null ? null : this.Visit(operation.Payload);

                if (this.response)
                {
                    ODataBatchResponseOperation responseOperation = (ODataBatchResponseOperation)operation;
                    HttpResponseData            httpResponse      = new HttpResponseData
                    {
                        StatusCode = (HttpStatusCode)responseOperation.StatusCode,
                    };

                    if (responseOperation.Headers != null)
                    {
                        foreach (var kvp in responseOperation.Headers)
                        {
                            httpResponse.Headers.Add(kvp.Key, kvp.Value);
                        }
                    }
                    ;
                    return(new ODataResponse(httpResponse)
                    {
                        RootElement = payloadElement
                    });
                }

                ODataBatchRequestOperation requestOperation = (ODataBatchRequestOperation)operation;

                // NOTE: this is abusing the ODataUriBuilder but is sufficient for our purposes
                // We use Unrecognized because the request URI may be relative (in the case of a reference)
                ODataUri     requestUri = new ODataUri(ODataUriBuilder.Unrecognized(requestOperation.Url.OriginalString));
                ODataRequest request    = this.requestManager.BuildRequest(
                    requestUri,
                    (HttpVerb)Enum.Parse(typeof(HttpVerb), requestOperation.HttpMethod, /*ignoreCase*/ true),
                    requestOperation.Headers);

                if (payloadElement != null)
                {
                    string contentType;
                    if (!request.Headers.TryGetValue(Microsoft.OData.ODataConstants.ContentTypeHeader, out contentType))
                    {
                        throw new InvalidOperationException("ContentType header not found.");
                    }
                    request.Body = this.requestManager.BuildBody(contentType, requestUri, payloadElement);
                }

                return(request);
            }
        /// <summary>
        /// Gets the expected options for the given content type and version
        /// </summary>
        /// <param name="contentType">The content type of the payload</param>
        /// <param name="version">The current version</param>
        /// <param name="payloadUri">The payload URI</param>
        /// <returns>The payload options for the given content type and version</returns>
        public ODataPayloadOptions GetExpectedPayloadOptions(string contentType, DataServiceProtocolVersion version, ODataUri payloadUri)
        {
            ExceptionUtilities.CheckArgumentNotNull(contentType, "contentType");
            ExceptionUtilities.Assert(version != DataServiceProtocolVersion.Unspecified, "Version cannot be unspecified");
            
            var expected = expectedPayloadOptions;
            
            if (contentType.StartsWith(MimeTypes.ApplicationJsonODataLightNonStreaming, System.StringComparison.Ordinal) ||
                     contentType.StartsWith(MimeTypes.ApplicationJsonODataLightStreaming, System.StringComparison.Ordinal))
            {
                expected = ODataPayloadOptions.IncludeTypeNames
                           | ODataPayloadOptions.IncludeMediaResourceSourceLinks
                           | ODataPayloadOptions.IncludeMediaResourceEditLinks
                           | ODataPayloadOptions.IncludeNamedMediaResourceSourceLinks
                           | ODataPayloadOptions.IncludeNamedMediaResourceEditLinks
                           | ODataPayloadOptions.IncludeEntityIdentifier
                           | ODataPayloadOptions.ConventionallyProducedNamedStreamSelfLink;

                var selectedPropertyNames = ODataUtilities.GetSelectedPropertyNamesFromUri(payloadUri, this.UriConverter).ToList();
                if (selectedPropertyNames.Any())
                {
                    EntitySet payloadEntitySet = null;
                    EntityType payloadEntityType = null;
                    if (payloadUri.TryGetExpectedEntitySetAndType(out payloadEntitySet, out payloadEntityType) &&
                        !ODataUtilities.ContainsAllIdentityPropertyNames(selectedPropertyNames, payloadEntityType))
                    {
                        // JSON Light projections without identity do not contain enough metadata to deduce 
                        // id and link values.
                        expected = ODataPayloadOptions.IncludeTypeNames;
                    }
                }
            }
            else if (version < DataServiceProtocolVersion.V4)
            {
                // Type names for null values are only supported in V1 and V2.
                expected = expected | ODataPayloadOptions.IncludeTypeNamesForNullValues;
            }

            return expected;
        }
        /// <summary>
        /// Returns the strategy to use for serializing/deserialzing the given content type
        /// </summary>
        /// <param name="contentType">The content type</param>
        /// <param name="uri">The request uri</param>
        /// <returns>A serialization strategy</returns>
        public virtual IProtocolFormatStrategy GetStrategy(string contentType, ODataUri uri)
        {
            if (uri != null)
            {
                // if its a named stream or an MLE, handle the returned payload as a binary stream
                if (uri.IsNamedStream() || uri.IsMediaResource())
                {
                    return this.BinaryValueStrategy;
                }

                // if its a raw $count request, we need to use a different strategy
                if (uri.IsCount() && IsPlainTextMimeType(contentType))
                {
                    return this.CountStrategy;
                }
            }

            if (IsXmlMimeType(contentType))
            {
                return this.XmlStrategy;
            }
            
            if (IsJsonMimeType(contentType))
            {
                return this.JsonStrategy;
            }

            if (IsTextBasedMimeType(contentType))
            {
                return this.TextValueStrategy;
            }

            if (IsHtmlFormMimeType(contentType))
            {
                return this.HtmlFormStrategy;
            }

            return this.BinaryValueStrategy;
        }
        /// <summary>
        /// Validates the data in the response payload based on the expected query value
        /// </summary>
        /// <param name="requestUri">The request uri</param>
        /// <param name="response">The response</param>
        /// <param name="expected">The expected query value</param>
        /// <param name="maxProtocolVersion">The max protocol version of the service</param>
        public void ValidateResponsePayload(ODataUri requestUri, ODataResponse response, QueryValue expected, DataServiceProtocolVersion maxProtocolVersion)
        {
            ExceptionUtilities.CheckObjectNotNull(requestUri, "requestUri");
            ExceptionUtilities.CheckObjectNotNull(response, "response");
            ExceptionUtilities.CheckObjectNotNull(expected, "expected");

            var expectedVersion = response.GetDataServiceVersion();
            this.Validator.ExpectedProtocolVersion = expectedVersion;
            this.Validator.ExpectedPayloadOptions = ODataPayloadOptions.None;

            string contentType;
            if (response.Headers.TryGetValue(HttpHeaders.ContentType, out contentType))
            {
                var strategy = this.FormatSelector.GetStrategy(contentType, requestUri);
                ExceptionUtilities.CheckObjectNotNull(strategy, "Could not get strategy for content type '{0}'", contentType);
                this.Validator.PrimitiveValueComparer = strategy.GetPrimitiveComparer();

                this.Validator.ExpectedPayloadOptions = this.ProtocolImplementationDetails.GetExpectedPayloadOptions(contentType, expectedVersion, requestUri);
            }

            this.ValidateAndPrintInfoOnError(requestUri, response.RootElement, expected);
        }
Beispiel #13
0
        /// <summary>
        /// Returns whether or not the uri refers to an entity set (with or without an EntityType Segment) or collection navigation property
        /// </summary>
        /// <param name="uri">The uri to extend</param>
        /// <returns>whether or not the uri refers to an entity set or collection navigation property</returns>
        public static bool IsEntitySet(this ODataUri uri)
        {
            if (uri.Segments.Count == 0)
            {
                return(false);
            }

            if (uri.IsEntityReferenceLink())
            {
                return(false);
            }

            if (uri.LastSegment.SegmentType == ODataUriSegmentType.EntitySet)
            {
                return(true);
            }

            if (uri.LastSegment.SegmentType == ODataUriSegmentType.NavigationProperty)
            {
                return(((NavigationSegment)uri.LastSegment).NavigationProperty.ToAssociationEnd.Multiplicity == EndMultiplicity.Many);
            }

            if (uri.LastSegment.SegmentType == ODataUriSegmentType.EntityType)
            {
                return(new ODataUri(uri.Segments.Take(uri.Segments.Count - 1)).IsEntitySet());
            }

            if (uri.LastSegment.SegmentType == ODataUriSegmentType.Function)
            {
                var collectionType = ((FunctionSegment)uri.LastSegment).Function.ReturnType as CollectionDataType;
                if (collectionType != null)
                {
                    return(collectionType.ElementDataType is EntityDataType);
                }
            }

            return(false);
        }
Beispiel #14
0
        internal static ODataPayloadElementType GetExpectedLinkPayloadType(this ODataUri linkUri)
        {
            ExceptionUtilities.CheckArgumentNotNull(linkUri, "linkUri");

            NavigationSegment lastNavigation = null;
            bool keyAfterLastNavigation      = false;
            bool hasLinks = false;

            foreach (var segment in linkUri.Segments)
            {
                if (segment.SegmentType == ODataUriSegmentType.NavigationProperty)
                {
                    lastNavigation         = (NavigationSegment)segment;
                    keyAfterLastNavigation = false;
                }
                else if (segment.SegmentType == ODataUriSegmentType.Key)
                {
                    keyAfterLastNavigation = true;
                }
                else if (segment.SegmentType == ODataUriSegmentType.EntityReferenceLinks)
                {
                    hasLinks = true;
                }
            }

            ExceptionUtilities.Assert(hasLinks, "Uri did not contain the '$ref' segment");
            ExceptionUtilities.CheckObjectNotNull(lastNavigation, "Uri did not contain any navigation properties");

            if (lastNavigation.NavigationProperty.ToAssociationEnd.Multiplicity == EndMultiplicity.Many && !keyAfterLastNavigation)
            {
                return(ODataPayloadElementType.LinkCollection);
            }
            else
            {
                return(ODataPayloadElementType.DeferredLink);
            }
        }
        /// <summary>
        /// Annotates the given payload based on the metadata in the given uri
        /// </summary>
        /// <param name="rootElement">The payload to annotate with metadata information</param>
        /// <param name="uri">The uri that corresponds to the given payload</param>
        public void ResolveMetadata(ODataPayloadElement rootElement, ODataUri uri)
        {
            ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement");
            ExceptionUtilities.CheckArgumentNotNull(uri, "uri");

            this.InitializeMetadataStack(uri);
            this.InitialStackSize = this.MetadataStack.Count;

            rootElement.Add(new ExpectedPayloadElementTypeAnnotation() { ExpectedType = uri.GetExpectedPayloadType() });

            // if the uri did not contain any metadata, do nothing
            if (this.InitialStackSize > 0)
            {
                // if this is the result of service operation or action, the root element needs to have the function itself and its return type
                var serviceOperation = this.MetadataStack.OfType<Function>().FirstOrDefault();
                if (serviceOperation != null)
                {
                    rootElement.AddAnnotationIfNotExist(new FunctionAnnotation() { Function = serviceOperation });
                    rootElement.AddAnnotationIfNotExist(new DataTypeAnnotation() { DataType = serviceOperation.ReturnType });
                }

                this.Recurse(rootElement);
            }
        }
            /// <summary>
            /// Initializes a new instance of the <see cref="NextLinkValidatingVisitor"/> class.
            /// </summary>
            /// <param name="requestUri">The request URI.</param>
            /// <param name="payloadOptions">The payload options.</param>
            /// <param name="parent">The parent verifier.</param>
            public NextLinkValidatingVisitor(ODataUri requestUri, ODataPayloadOptions payloadOptions, NextLinkResponseVerifier parent)
            {
                ExceptionUtilities.CheckArgumentNotNull(requestUri, "requestUri");
                ExceptionUtilities.CheckArgumentNotNull(parent, "parent");
                this.requestUri = requestUri;
                this.payloadOptions = payloadOptions;
                this.parent = parent;

                this.queryValueStack.Push(this.parent.UriEvaluator.Evaluate(requestUri, true, true));
            }
Beispiel #17
0
 /// <summary>
 /// Returns whether or not the uri ends with a primitive or complex property segment
 /// </summary>
 /// <param name="uri">The uri to extend</param>
 /// <returns>whether or not the uri ends with a primitive or complex property segment</returns>
 public static bool IsProperty(this ODataUri uri)
 {
     return(uri.Segments.Count > 0 && uri.LastSegment.IsProperty());
 }
Beispiel #18
0
 /// <summary>
 /// Returns whether or not the uri ends with a '$count' segment
 /// </summary>
 /// <param name="uri">The uri to extend</param>
 /// <returns>whether or not the uri ends with a '$count' segment</returns>
 public static bool IsCount(this ODataUri uri)
 {
     return(uri.Segments.Count > 0 && uri.LastSegment.SegmentType == ODataUriSegmentType.Count);
 }
Beispiel #19
0
        /// <summary>
        /// Determines whether ODataUri has an InlineCount or not
        /// </summary>
        /// <param name="uri">OData Uri to look at</param>
        /// <returns>True or false if there is an inlinecount or not</returns>
        public static bool IncludesInlineCountAllPages(this ODataUri uri)
        {
            string value;

            return(uri.TryGetInlineCountValue(out value) && value == QueryOptions.InlineCountAllPages);
        }
Beispiel #20
0
        private static void SetExpectedEntitySetAndTypeFromUri(ODataPayloadContext payloadContext, ODataUri uri)
        {
            EntitySet  entitySet  = null;
            EntityType entityType = null;

            uri.TryGetExpectedEntitySetAndType(out entitySet, out entityType);
            payloadContext.ExpectedEntitySet  = entitySet;
            payloadContext.ExpectedEntityType = entityType;
        }
        internal static string DetermineAcceptType(ODataUri uri, string defaultAcceptType)
        {
            if (uri.IsNamedStream() || uri.IsMediaResource())
            {
                return MimeTypes.Any;
            }

            if (uri.IsCount())
            {
                return MimeTypes.TextPlain;
            }

            if (uri.IsPropertyValue())
            {
                string propertyAcceptType = MimeTypes.Any;
                var propertySegment = uri.Segments[uri.Segments.Count - 2] as PropertySegment;
                ExceptionUtilities.CheckObjectNotNull(propertySegment, "Cannot get Property segment from uri");
                var mimeTypeAnnotation = propertySegment.Property.Annotations.OfType<MimeTypeAnnotation>().SingleOrDefault();
                if (mimeTypeAnnotation != null)
                {
                    propertyAcceptType = mimeTypeAnnotation.MimeTypeValue;
                }

                return propertyAcceptType;
            }

            return defaultAcceptType;
        }
Beispiel #22
0
 /// <summary>
 /// Extracts the names of properties specified in the $select option, if any.
 /// </summary>
 /// <param name="uri">The URI to parse.</param>
 /// <param name="uriToStringConverter">The IODataUriToStringConverter implementation.</param>
 /// <returns>The list of property names.</returns>
 public static IEnumerable <string> GetSelectedPropertyNamesFromUri(ODataUri uri, IODataUriToStringConverter uriToStringConverter)
 {
     return(uri.SelectSegments.Select(s => uriToStringConverter.ConcatenateSegments(s.Where(s2 => !(s2 is EntityTypeSegment)))));
 }
        internal MimePartData<IHttpRequest> BuildRequestFromPart(MimePartData<byte[]> mimePart, Encoding encoding)
        {
            var requestData = CreateRequest(mimePart.Body, encoding);

            var odataUri = new ODataUri(new UnrecognizedSegment(requestData.Uri.OriginalString));
            var odataRequest = this.RequestManager.BuildRequest(odataUri, requestData.Verb, requestData.Headers);

            string contentType;
            if (requestData.TryGetHeaderValueIgnoreHeaderCase(HttpHeaders.ContentType, out contentType))
            {
                var formatStrategy = this.FormatSelector.GetStrategy(contentType, odataUri);
                var deserializer = formatStrategy.GetDeserializer();
                var rootElement = deserializer.DeserializeFromBinary(requestData.Body, ODataPayloadContext.BuildPayloadContextFromRequest(odataRequest));
                odataRequest.Body = new ODataPayloadBody(requestData.Body, rootElement);
            }
            else if (requestData.Body != null)
            {
                odataRequest.Body = new ODataPayloadBody(requestData.Body, new PrimitiveValue(null, requestData.Body));
            }

            var rebuiltPart = new MimePartData<IHttpRequest>();
            rebuiltPart.Headers.AddRange(mimePart.Headers);
            rebuiltPart.Body = odataRequest;

            return rebuiltPart;
        }
        public void BatchReaderMixedEncodingTest()
        {
            EdmModel model = new EdmModel();
            EdmEntityType personType = model.EntityType("Person")
                .KeyProperty("Id", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference)
                .Property("Name", EdmPrimitiveTypeKind.String, isNullable: true);
            model.Fixup();

            EdmEntitySet personSet = model.EntitySet("Person", personType);

            EntityInstance personInstance = PayloadBuilder.Entity("TestModel.Person")
                .Property("Id", PayloadBuilder.PrimitiveValue(1))
                .Property("Name", PayloadBuilder.PrimitiveValue("Mr Foo Baz"));

            ODataUriSegment root = ODataUriBuilder.Root(new Uri("http://www.odata.org"));
            ODataUri testUri = new ODataUri(root, ODataUriBuilder.EntitySet(personSet));


            Encoding[] encodings = new Encoding[] 
            { 
                Encoding.UTF8, 
                Encoding.BigEndianUnicode, 
                Encoding.Unicode 
            };

            IEnumerable<BatchReaderMixedEncodingTestCase> testCases =
                encodings.SelectMany(batchEncoding =>
                    encodings.Select(changesetEncoding =>
                        new BatchReaderMixedEncodingTestCase
                        {
                            BatchEncoding = batchEncoding,
                            Changesets = new[]
                            {
                                new BatchReaderMixedEncodingChangeset
                                {
                                    ChangesetEncoding = changesetEncoding,
                                    Operations = new[]
                                    {
                                       new BatchReaderMixedEncodingOperation
                                       {
                                           OperationEncoding = Encoding.Unicode,
                                           PayloadFormat = ODataFormat.Atom,
                                       },
                                       new BatchReaderMixedEncodingOperation
                                       {
                                           // Uses changeset's encoding
                                           PayloadFormat = ODataFormat.Atom,
                                       },
                                    },
                                },
                                new BatchReaderMixedEncodingChangeset
                                {
                                    Operations = new[]
                                    {
                                        new BatchReaderMixedEncodingOperation
                                        {
                                            // Uses batch's encoding
                                            OperationEncoding = batchEncoding,
                                            PayloadFormat = ODataFormat.Atom,
                                        },
                                    },
                                },
                            },
                        }
                    ));

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.ReaderTestConfigurationProvider.DefaultFormatConfigurations,
                (testCase, testConfiguration) =>
                {
                    var testPayload = personInstance.DeepCopy();
                    if (!testConfiguration.IsRequest)
                    {
                        testPayload.AddAnnotation(new PayloadFormatVersionAnnotation() { Response = true, ResponseWrapper = true });
                    }

                    var testDescriptor = this.CreateTestDescriptor(testCase, testPayload, testUri, testConfiguration.IsRequest);
                    testDescriptor.PayloadEdmModel = model;
                    testDescriptor.RunTest(testConfiguration);
                });
        }
        /// <summary>
        /// Generates the raw test message with mixed encodings defined by the test case, as well as the expected ODataPayloadElement.
        /// </summary>
        /// <param name="testCase">The test case defining the structure and encodings of the batch payload.</param>
        /// <param name="payload">The payload to use for all generated batch operations.</param>
        /// <param name="payloadUri">The URI to use for all generated batch operations.</param>
        /// <param name="isRequest">If true, generates a batch request, otherwise a batch response.</param>
        /// <returns>The test descriptor for this test case/configuration.</returns>
        private BatchReaderMixedEncodingTestDescriptor CreateTestDescriptor(BatchReaderMixedEncodingTestCase testCase, ODataPayloadElement payload, ODataUri payloadUri, bool isRequest)
        {
            ExceptionUtilities.Assert(testCase.BatchEncoding != null, "Batch encoding has not been specified.");

            string batchBoundary = "batch_" + Guid.NewGuid().ToString();
            string payloadUriString = this.UriConverter.ConvertToString(payloadUri);

            var batchPayload = isRequest ? (ODataPayloadElement)new BatchRequestPayload() : (ODataPayloadElement)new BatchResponsePayload();
            batchPayload.AddAnnotation(new BatchBoundaryAnnotation(batchBoundary));

            var rawMessage = new List<byte>();

            // TODO: Batch reader does not support multi codepoint encodings
            Encoding unsupportedEncoding = AsUnsupportedEncoding(testCase.BatchEncoding);

            foreach (var changeset in testCase.Changesets)
            {
                string changesetBoundary = "change_" + Guid.NewGuid().ToString();
                Encoding changesetEncoding = changeset.ChangesetEncoding ?? testCase.BatchEncoding;

                // TODO: Batch reader does not support multi codepoint encodings
                unsupportedEncoding = unsupportedEncoding ?? AsUnsupportedEncoding(changesetEncoding);

                string changesetContentType = HttpUtilities.BuildContentType(
                    MimeTypes.MultipartMixed,
                    changeset.ChangesetEncoding == null ? string.Empty : changeset.ChangesetEncoding.WebName,
                    changesetBoundary);

                rawMessage.AddRange(
                    WriteMessagePart(
                        testCase.BatchEncoding,
                        (writer) =>
                        {
                            writer.Write("--");
                            writer.WriteLine(batchBoundary);
                            writer.WriteLine(HttpHeaders.ContentType + ": " + changesetContentType);
                            writer.WriteLine();
                        }));

                var mimeParts = new List<IMimePart>();
                int contentId = 0;

                foreach (var operation in changeset.Operations)
                {
                    ExceptionUtilities.Assert(operation.PayloadFormat == ODataFormat.Atom || operation.PayloadFormat == ODataFormat.Json, "Payload format must be ATOM or JSON.");
                    string formatType = MimeTypes.ApplicationAtomXml + ";type=entry";
                    Encoding payloadEncoding = operation.OperationEncoding ?? changesetEncoding;
                    string payloadContentType = HttpUtilities.BuildContentType(
                        formatType,
                        operation.OperationEncoding == null ? string.Empty : operation.OperationEncoding.WebName,
                        string.Empty);

                    string httpStatus = isRequest ? "POST " + payloadUriString + " HTTP/1.1" : "HTTP/1.1 201 Created";

                    rawMessage.AddRange(
                        WriteMessagePart(
                            changesetEncoding,
                            (writer) =>
                            {
                                writer.WriteLine();
                                writer.Write("--");
                                writer.WriteLine(changesetBoundary);
                                writer.WriteLine(HttpHeaders.ContentType + ": application/http");
                                writer.WriteLine(HttpHeaders.ContentTransferEncoding + ": binary");
                                writer.WriteLine(HttpHeaders.ContentId + ": " + (++contentId).ToString());
                                writer.WriteLine();
                                writer.WriteLine(httpStatus);
                                writer.WriteLine(HttpHeaders.ContentType + ": " + payloadContentType);
                                writer.WriteLine();
                            }));

                    IPayloadSerializer payloadSerializer =
                        operation.PayloadFormat == ODataFormat.Atom ?
                        (IPayloadSerializer)new XmlPayloadSerializer(this.PayloadElementToXmlConverter) :
                        (IPayloadSerializer)new JsonPayloadSerializer(this.PayloadElementToJsonConverter.ConvertToJson);

                    byte[] payloadBytes = payloadSerializer.SerializeToBinary(payload, payloadEncoding.WebName);
                    rawMessage.AddRange(payloadBytes.Skip(payloadEncoding.GetPreamble().Length));

                    if (isRequest)
                    {
                        var request = this.RequestManager.BuildRequest(payloadUri, HttpVerb.Post, new Dictionary<string, string> { { HttpHeaders.ContentType, payloadContentType } });
                        request.Body = new ODataPayloadBody(payloadBytes, payload);
                        mimeParts.Add(request);
                    }
                    else
                    {
                        var httpResponseData = new HttpResponseData { StatusCode = HttpStatusCode.Created, };
                        httpResponseData.Headers.Add(HttpHeaders.ContentType, payloadContentType);
                        var response = new ODataResponse(httpResponseData) { Body = payloadBytes, RootElement = payload };
                        mimeParts.Add(response);
                    }
                }

                rawMessage.AddRange(
                    WriteMessagePart(
                        changesetEncoding,
                        (writer) =>
                        {
                            writer.WriteLine();
                            writer.Write("--");
                            writer.Write(changesetBoundary);
                            writer.WriteLine("--");
                        }));

                if (isRequest)
                {
                    ((BatchRequestPayload)batchPayload).Add(BatchPayloadBuilder.RequestChangeset(changesetBoundary, changesetEncoding.WebName, mimeParts.ToArray()));
                }
                else
                {
                    ((BatchResponsePayload)batchPayload).Add(BatchPayloadBuilder.ResponseChangeset(changesetBoundary, changesetEncoding.WebName, mimeParts.ToArray()));
                }
            }

            rawMessage.AddRange(
                WriteMessagePart(
                    testCase.BatchEncoding,
                    (writer) =>
                    {
                        writer.WriteLine();
                        writer.Write("--");
                        writer.Write(batchBoundary);
                        writer.WriteLine("--");
                    }));

            return new BatchReaderMixedEncodingTestDescriptor(this.PayloadReaderSettings)
            {
                BatchContentTypeHeader = HttpUtilities.BuildContentType(MimeTypes.MultipartMixed, testCase.BatchEncoding.WebName, batchBoundary),
                RawMessage = rawMessage.ToArray(),
                PayloadElement = batchPayload,
                ExpectedException = unsupportedEncoding == null ? null : ODataExpectedExceptions.ODataException("ODataBatchReaderStream_MultiByteEncodingsNotSupported", unsupportedEncoding.WebName)
            };
        }
        /// <summary>
        /// Verifies the delete succeeded
        /// </summary>
        /// <param name="request">The request to verify</param>
        /// <param name="response">The response to verify</param>
        public override void Verify(ODataRequest request, ODataResponse response)
        {
            base.Verify(request, response);

            var originalUri = request.Uri;

            var entityUri = originalUri.ScopeToEntity();

            var beforeSync = this.Evaluator.Evaluate(entityUri, false, false) as QueryStructuralValue;
            ExceptionUtilities.CheckObjectNotNull(beforeSync, "Could not get entity before syncing");
            ExceptionUtilities.Assert(!beforeSync.IsNull, "Entity was null before syncing");

            var afterSync = this.SynchronizeAndEvaluate(entityUri, beforeSync, originalUri.IsEntity());

            QueryValue currentValue = afterSync;
            string message = null;

            if (originalUri.IsEntity())
            {
                // DELETE Customers(1)
                message = "Entity was not deleted";
            }
            else if (originalUri.IsPropertyValue())
            {
                // DELETE Customers(1)/Name/$value
                message = "Property value was not null";

                // drill down by each property in the uri after the entity portion
                foreach (var propertySegment in originalUri.Segments.Skip(entityUri.Segments.Count).OfType<PropertySegment>())
                {
                    currentValue = ((QueryStructuralValue)currentValue).GetValue(propertySegment.Property.Name);
                }
            }
            else if (originalUri.IsEntityReferenceLink())
            {
                // TODO: verify back-links?
                var navigation = originalUri.Segments.OfType<NavigationSegment>().Last();

                if (navigation.NavigationProperty.ToAssociationEnd.Multiplicity == EndMultiplicity.Many)
                {
                    // DELETE Customers(1)/Orders/$ref?$id=Orders(1)
                    message = "Collection link was not deleted";

                    var linkUri = new ODataUri(entityUri.Segments.Concat(navigation, originalUri.Segments.OfType<KeyExpressionSegment>().Last()));
                    currentValue = this.Evaluator.Evaluate(linkUri, false, false);
                }
                else
                {
                    // DELETE Customers(1)/BestFriend/$ref
                    message = "Reference link was not deleted";

                    currentValue = ((QueryStructuralValue)afterSync).GetValue(navigation.NavigationProperty.Name);
                }
            }

            // at this point, the current value should be null if the delete was successful
            ExceptionUtilities.CheckObjectNotNull(message, "Uri did not represent an entity, value, or link: '{0}'", request.GetRequestUri());
            this.Assert(currentValue.IsNull, message, request, response);

            if (originalUri.IsEntity())
            {
                this.RequeryEntityAndVerifyStatusCode(request, response, entityUri);

                if (entityUri.Segments.OfType<NavigationSegment>().Any())
                {
                    // convert the uri into a top-level access
                    entityUri = GetTopLevelUri(beforeSync);
                    entityUri.Segments.Insert(0, originalUri.Segments.OfType<ServiceRootSegment>().Single());

                    this.RequeryEntityAndVerifyStatusCode(request, response, entityUri);
                }
            }
        }
        private void RequeryEntityAndVerifyStatusCode(ODataRequest request, ODataResponse response, ODataUri entityUri)
        {
            var getVerificationRequest = this.RequestManager.BuildRequest(entityUri, HttpVerb.Get, new HttpHeaderCollection());
            var getVerificationResponse = this.RequestManager.GetResponse(getVerificationRequest);

            var expectedStatusCode = HttpStatusCode.NotFound;
            if (entityUri.LastSegment.SegmentType == ODataUriSegmentType.NavigationProperty)
            {
                var navigation = (NavigationSegment)entityUri.LastSegment;
                if (navigation.NavigationProperty.ToAssociationEnd.Multiplicity != EndMultiplicity.Many)
                {
                    expectedStatusCode = HttpStatusCode.NoContent;
                }
            }

            string message = null;
            bool succeeded = getVerificationResponse.StatusCode == expectedStatusCode;
            if (!succeeded)
            {
                message = @"Re-querying the deleted entity did not result in correct status code
Expected: {0}
Actual:   {1}";
                message = string.Format(CultureInfo.InvariantCulture, message, expectedStatusCode, getVerificationResponse.StatusCode);
                this.ReportFailure(request, response);
            }

            this.Assert(succeeded, message, getVerificationRequest, getVerificationResponse);
        }
        private QueryValue SynchronizeAndEvaluate(ODataUri entityUri, QueryStructuralValue beforeSync, bool synchronizeEntireSet)
        {
            var entityType = beforeSync.Type as QueryEntityType;
            ExceptionUtilities.CheckObjectNotNull(entityType, "Structural value was not an entity type");

            // if an entity was deleted, synchronize the entire set. Otherwise just synchronize the entity
            if (synchronizeEntireSet)
            {
                SyncHelpers.ExecuteActionAndWait(c => this.Synchronizer.SynchronizeEntireEntitySet(c, entityType.EntitySet.Name));
            }
            else
            {
                SyncHelpers.ExecuteActionAndWait(c => this.Synchronizer.SynchronizeEntity(c, beforeSync));
            }

            return this.Evaluator.Evaluate(entityUri, false, false);
        }
        private IHttpRequest GenerateRequestOperation(ODataResponse batchResponseOperation, EntityModelSchema model)
        {
            ExceptionUtilities.CheckArgumentNotNull(batchResponseOperation, "batchResponseOperation");
            ExceptionUtilities.CheckArgumentNotNull(model, "model");
            var headers = new Dictionary<string, string> { { "GivenPayloadRequestHeader", "PayloadHeaderValue" } };
            
            string mergeContentType = HttpUtilities.BuildContentType(MimeTypes.ApplicationXml, Encoding.UTF8.WebName, null);
            ODataUri uri = null;
            HttpVerb verb = HttpVerb.Get;
            if (batchResponseOperation.RootElement != null)
            {
                var complexInstanceCollection = batchResponseOperation.RootElement as ComplexInstanceCollection;
                if (complexInstanceCollection != null)
                {
                    var function = batchResponseOperation.RootElement.GetAnnotation<FunctionAnnotation>();
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.ServiceOperation(function.Function));
                }

                var complexMultivalue = batchResponseOperation.RootElement as ComplexMultiValueProperty;
                if (complexMultivalue != null)
                {
                    var entityType = complexMultivalue.GetAnnotation<EntityModelTypeAnnotation>().EntityModelType as EntityDataType;
                    var entitySet = model.GetEntitySet(entityType.Definition.Name);
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.EntitySet(entitySet), ODataUriBuilder.Property(entityType.Definition, complexMultivalue.Name));
                }

                var complexProperty = batchResponseOperation.RootElement as ComplexProperty;
                if (complexProperty != null)
                {
                    var type = complexProperty.GetAnnotation<EntityModelTypeAnnotation>();
                    var complexDataType = type.EntityModelType as ComplexDataType;
                    // Using first because we don't need a specific entity just one that contains this type. If there is more than one the first works fine.
                    var entityType = model.EntityTypes.Where(et => et.Properties.Where(p => p.Name == complexProperty.Name).Count() == 1).First();
                    var complexType = model.ComplexTypes.Where(ct => complexDataType.Definition.Name == ct.Name).Single();
                    var complexPropertyName = entityType.AllProperties.Where(p => 
                        {
                            var complex = p.PropertyType as ComplexDataType;
                            if (complex == null)
                            {
                                return false;
                            }

                            return complex.Definition.Name == complexDataType.Definition.Name;

                        }).Single();
                    
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.Property(entityType, complexPropertyName.Name));
                }

                var deferredLink = batchResponseOperation.RootElement as DeferredLink;
                if (deferredLink != null)
                {
                    var navigationProperty = deferredLink.GetAnnotation<NavigationPropertyAnnotation>();
                    var entityType = model.EntityTypes.Where(et => et.Properties.Where(p => p.Name == navigationProperty.Property.Name).Count() == 1).First();
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.Property(entityType, navigationProperty.Property.Name));
                }

                var linkCollection = batchResponseOperation.RootElement as LinkCollection;
                if (linkCollection != null)
                {
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), SystemSegment.EntityReferenceLinks);
                }

                var entityInstance = batchResponseOperation.RootElement as EntityInstance;
                if (entityInstance != null)
                {
                    var type = entityInstance.GetAnnotation<EntityModelTypeAnnotation>().EntityModelType as EntityDataType;
                    var entitySetType = model.GetEntitySet(type.Definition.Name);
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.EntitySet(entitySetType));
                }

                var entitySetInstance = batchResponseOperation.RootElement as EntitySetInstance;
                if (entitySetInstance != null)
                {
                    var entitySetType = model.GetEntitySet(entityInstance.FullTypeName);
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.EntitySet(entitySetType));
                }

                var primitiveCollection = batchResponseOperation.RootElement as PrimitiveCollection;
                if (primitiveCollection != null)
                {
                    var function = batchResponseOperation.RootElement.GetAnnotation<FunctionAnnotation>();
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.ServiceOperation(function.Function));
                }

                var primitiveMultiValueProperty = batchResponseOperation.RootElement as PrimitiveMultiValueProperty;
                if (primitiveMultiValueProperty != null)
                {
                    var type = primitiveMultiValueProperty.GetAnnotation<EntityModelTypeAnnotation>();
                    var entityType = type.EntityModelType as EntityDataType;

                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.EntitySet(model.GetEntitySet(entityType.Definition.Name)), ODataUriBuilder.Property(entityType.Definition, primitiveMultiValueProperty.Name));
                }

                var primitiveProperty = batchResponseOperation.RootElement as PrimitiveProperty;
                if (primitiveProperty != null)
                {
                    var type = complexProperty.GetAnnotation<EntityModelTypeAnnotation>();
                    var entityType = type.EntityModelType as EntityDataType;

                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.Property(entityType.Definition, primitiveProperty.Name));
                }

                var primitiveValue = batchResponseOperation.RootElement as PrimitiveValue;
                if (primitiveValue != null)
                {
                    var primitiveType = primitiveValue.GetAnnotation<DataTypeAnnotation>();
                    var entityType = primitiveValue.GetAnnotation<EntityModelTypeAnnotation>().EntityModelType as EntityDataType;
                    var propertyName = entityType.Definition.Properties.Where(p=> p.PropertyType == primitiveType.DataType).First().Name;
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.Property(entityType.Definition, propertyName), SystemSegment.Value);
                }

                var odataError = batchResponseOperation.RootElement as ODataErrorPayload;
                if (odataError != null)
                {
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")));
                }
            }
            else
            {
                verb = HttpVerb.Put;
                uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")));
            }

            ExceptionUtilities.Assert(uri != null, "The request URI has not been defined.");
            var request = this.RequestManager.BuildRequest(uri, verb, headers);
            return request;   
        }
        private static bool HasETagOnRetrieve(ODataUri uri)
        {
            if (uri.ExpandSegments.Any())
            {
                return false;
            }

            if (uri.IsEntity())
            {
                return true;
            }

            if (uri.IsProperty())
            {
                return true;
            }

            if (uri.IsPropertyValue() || uri.IsMediaResource())
            {
                // this covers media-resources as well
                return true;
            }

            if (uri.IsNamedStream())
            {
                return true;
            }

            return false;
        }
        /// <summary>
        /// Generates the next link for an expanded feed.
        /// </summary>
        /// <param name="containingEntity">The containing entity.</param>
        /// <param name="navigation">The expanded navigation property.</param>
        /// <param name="lastEntityValue">The last entity value.</param>
        /// <returns>
        /// The expected next link
        /// </returns>
        public string GenerateExpandedNextLink(EntityInstance containingEntity, NavigationPropertyInstance navigation, QueryStructuralValue lastEntityValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(containingEntity, "containingEntity");
            ExceptionUtilities.CheckArgumentNotNull(navigation, "navigation");
            ExceptionUtilities.CheckArgumentNotNull(lastEntityValue, "lastEntityValue");

            var navigationUriString = ((ExpandedLink)navigation.Value).UriString;
            if (string.IsNullOrEmpty(navigationUriString))
            {
                navigationUriString = UriHelpers.ConcatenateUriSegments(containingEntity.EditLink, navigation.Name);
            }

            var skipTokenValues = new List<object>();
            foreach (var keyProperty in lastEntityValue.Type.Properties.Where(p => p.IsPrimaryKey))
            {
                skipTokenValues.Add(lastEntityValue.GetScalarValue(keyProperty.Name).Value);
            }

            var skiptoken = this.BuildSkipTokenFromValues(skipTokenValues);

            var nextLinkUri = new ODataUri(new UnrecognizedSegment(navigationUriString));
            nextLinkUri.SkipToken = skiptoken;

            return this.UriToStringConverter.ConvertToString(nextLinkUri);
        }
        private DataServiceProtocolVersion CalculateExpectedClientMinRequestVersion(ODataUri odataUri, out ExpectedClientErrorBaseline errorIfTooLow)
        {
            ExceptionUtilities.CheckArgumentNotNull(odataUri, "odataUri");

            DataServiceProtocolVersion expectedVersion = DataServiceProtocolVersion.V4;
            errorIfTooLow = null;

            // Uri specific processing
            if (odataUri.HasAnyOrAllInFilter())
            {
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4);
                string anyOrAll = string.Empty;

                if (odataUri.Filter.Contains("/any("))
                {
                    anyOrAll = "Any";
                }
                else
                {
                    anyOrAll = "All";
                }

                var errorInformation = new ExpectedErrorMessage("ALinq_MethodNotSupportedForMaxDataServiceVersionLessThanX", anyOrAll, expectedVersion.ConvertToHeaderFormat());
                errorIfTooLow = new ExpectedClientErrorBaseline(typeof(NotSupportedException), false, errorInformation);
            }

            if (odataUri.HasSignificantTypeSegmentInPath())
            {
                // TODO: this seems like it should be inferred from the query, not the uri
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4);
                var errorInformation = new ExpectedErrorMessage("ALinq_MethodNotSupportedForMaxDataServiceVersionLessThanX", "OfType", expectedVersion.ConvertToHeaderFormat());
                errorIfTooLow = new ExpectedClientErrorBaseline(typeof(NotSupportedException), false, errorInformation);
            }
            else if (odataUri.HasTypeSegmentInExpandOrSelect())
            {
                // TODO: this seems like it should be inferred from the query, not the uri
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4);
                var errorInformation = new ExpectedErrorMessage("ALinq_TypeAsNotSupportedForMaxDataServiceVersionLessThan3");
                errorIfTooLow = new ExpectedClientErrorBaseline(typeof(NotSupportedException), false, errorInformation);
            }
            
            return expectedVersion;
        }
        internal static HttpStatusCode GetExpectedStatusCode(ODataUri uri, IODataUriEvaluator evaluator)
        {
            bool specialStatusCodeIfNull = false;

            specialStatusCodeIfNull |= uri.IsNamedStream();
            specialStatusCodeIfNull |= uri.IsMediaResource();
            specialStatusCodeIfNull |= uri.IsEntity();
            specialStatusCodeIfNull |= uri.IsEntityReferenceLink();
            specialStatusCodeIfNull |= uri.IsPropertyValue();
            
            bool uriIsValue = uri.IsNamedStream() || uri.IsMediaResource();

            // For an action it is evaluated specially via the actionresponse verifier, skip eval here
            if (!uri.IsAction() && specialStatusCodeIfNull && evaluator.Evaluate(uri).IsNull)
            {
                if (uriIsValue)
                {
                    return HttpStatusCode.NoContent;
                }
                else
                {
                    return HttpStatusCode.NotFound;
                }
            }

            return HttpStatusCode.OK;
        }
        private void InitializeMetadataStack(ODataUri uri)
        {
            this.MetadataStack.Clear();
            EntitySet currentSet = null;
            foreach (var segment in uri.Segments)
            {
                var setSegment = segment as EntitySetSegment;
                if (setSegment != null)
                {
                    this.MetadataStack.Push(setSegment.EntitySet);
                    currentSet = setSegment.EntitySet;
                    continue;
                }

                var navigationSegment = segment as NavigationSegment;
                if (navigationSegment != null)
                {
                    this.MetadataStack.Push(navigationSegment.NavigationProperty);
                    this.MetadataStack.Push(this.CurrentEntitySet.GetRelatedEntitySet(navigationSegment.NavigationProperty));
                    currentSet = currentSet.GetRelatedEntitySet(navigationSegment.NavigationProperty);
                    continue;
                }

                var propertySegment = segment as PropertySegment;
                if (propertySegment != null)
                {
                    this.MetadataStack.Push(propertySegment.Property);
                    continue;
                }

                var functionSegment = segment as FunctionSegment;
                if (functionSegment != null)
                {
                    EntitySet returningEntitySet;
                    if (this.InitializeFunctionMetadata(functionSegment.Function, currentSet, out returningEntitySet))
                    {
                        currentSet = returningEntitySet;
                    }

                    continue;
                }

                // special segment types
                if (segment.SegmentType == ODataUriSegmentType.Count)
                {
                    this.MetadataStack.Push(DataTypes.Integer);
                }
                else if (segment.SegmentType == ODataUriSegmentType.Value)
                {
                    var property = this.MetadataStack.Peek() as MemberProperty;
                    if (property != null)
                    {
                        this.MetadataStack.Push(property.PropertyType);    
                    }
                }
            }
        }
Beispiel #35
0
        public void BatchReaderMixedEncodingTest()
        {
            EdmModel      model      = new EdmModel();
            EdmEntityType personType = model.EntityType("Person")
                                       .KeyProperty("Id", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference)
                                       .Property("Name", EdmPrimitiveTypeKind.String, isNullable: true);

            model.Fixup();

            EdmEntitySet personSet = model.EntitySet("Person", personType);

            EntityInstance personInstance = PayloadBuilder.Entity("TestModel.Person")
                                            .Property("Id", PayloadBuilder.PrimitiveValue(1))
                                            .Property("Name", PayloadBuilder.PrimitiveValue("Mr Foo Baz"));

            ODataUriSegment root    = ODataUriBuilder.Root(new Uri("http://www.odata.org"));
            ODataUri        testUri = new ODataUri(root, ODataUriBuilder.EntitySet(personSet));


            Encoding[] encodings = new Encoding[]
            {
                Encoding.UTF8,
                Encoding.BigEndianUnicode,
                Encoding.Unicode
            };

            IEnumerable <BatchReaderMixedEncodingTestCase> testCases =
                encodings.SelectMany(batchEncoding =>
                                     encodings.Select(changesetEncoding =>
                                                      new BatchReaderMixedEncodingTestCase
            {
                BatchEncoding = batchEncoding,
                Changesets    = new[]
                {
                    new BatchReaderMixedEncodingChangeset
                    {
                        ChangesetEncoding = changesetEncoding,
                        Operations        = new[]
                        {
                            new BatchReaderMixedEncodingOperation
                            {
                                OperationEncoding = Encoding.Unicode,
                                PayloadFormat     = ODataFormat.Atom,
                            },
                            new BatchReaderMixedEncodingOperation
                            {
                                // Uses changeset's encoding
                                PayloadFormat = ODataFormat.Atom,
                            },
                        },
                    },
                    new BatchReaderMixedEncodingChangeset
                    {
                        Operations = new[]
                        {
                            new BatchReaderMixedEncodingOperation
                            {
                                // Uses batch's encoding
                                OperationEncoding = batchEncoding,
                                PayloadFormat     = ODataFormat.Atom,
                            },
                        },
                    },
                },
            }
                                                      ));

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.ReaderTestConfigurationProvider.DefaultFormatConfigurations,
                (testCase, testConfiguration) =>
            {
                var testPayload = personInstance.DeepCopy();
                if (!testConfiguration.IsRequest)
                {
                    testPayload.AddAnnotation(new PayloadFormatVersionAnnotation()
                    {
                        Response = true, ResponseWrapper = true
                    });
                }

                var testDescriptor             = this.CreateTestDescriptor(testCase, testPayload, testUri, testConfiguration.IsRequest);
                testDescriptor.PayloadEdmModel = model;
                testDescriptor.RunTest(testConfiguration);
            });
        }
        private IEnumerable<PayloadReaderTestDescriptor> CreateCrossReferenceTestDescriptors(CrossReferenceTestCase testCase, ReaderTestConfiguration testConfiguration)
        {
            ExceptionUtilities.CheckArgumentNotNull(testCase, "testCase");

            var emptyPayload = new OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = new EdmModel().Fixup()
            };

            IEnumerable<OData.Common.PayloadTestDescriptor> operationPayloads = new[] { emptyPayload };

            // One of the operations in the test case may specify a reference link value to use to generate payloads
            string payloadReferenceLink = testCase.ChangeSets.SelectMany(cset => cset.Operations).Select(o => o.PayloadCrossReferenceLink).SingleOrDefault(s => !string.IsNullOrEmpty(s));
            if (payloadReferenceLink != null)
            {
                EdmModel testModel = Test.OData.Utils.Metadata.TestModels.BuildTestModel();
                operationPayloads =
                    GeneratePayloadElementsWithCrossReferenceLinks(payloadReferenceLink, testConfiguration).Select(
                        p => new OData.Common.PayloadTestDescriptor
                        {
                            PayloadElement = p,
                            PayloadEdmModel = testModel,
                        });
            }

            var testDescriptors = new List<PayloadReaderTestDescriptor>();
            foreach (var payload in operationPayloads)
            {
                IEnumerable<IMimePart> requestChangesets = testCase.ChangeSets.Select(
                    c => (IMimePart)BatchUtils.GetRequestChangeset(
                        c.Operations.Select(o =>
                            {
                                // check whether we need to inject a payload into this operation
                                var operationPayload = string.IsNullOrEmpty(o.PayloadCrossReferenceLink) ? emptyPayload : payload;

                                ODataUri operationUri = new ODataUri(new[] { ODataUriBuilder.Unrecognized(o.Uri.OriginalString) });
                                var requestOperation = operationPayload.InRequestOperation(HttpVerb.Post, operationUri, this.RequestManager);
                                requestOperation.Headers.Add(HttpHeaders.ContentId, o.ContentId);

                                return (IMimePart)requestOperation;
                            }).ToArray(),
                        this.RequestManager));

                var testDescriptor = new PayloadReaderTestDescriptor(this.PayloadReaderSettings)
                {
                    DebugDescription = testCase.DebugDescription,
                    PayloadElement = PayloadBuilder.BatchRequestPayload(requestChangesets.ToArray()).AddAnnotation(new BatchBoundaryAnnotation("batch_foo")),
                    ExpectedException = testCase.ExpectedException,
                    SkipTestConfiguration = (testConfig) => !testConfig.IsRequest,
                };

                testDescriptors.Add(testDescriptor);
            }

            return testDescriptors;
        }
Beispiel #37
0
 /// <summary>
 /// Returns whether or not the uri contains a '$ref' segment
 /// </summary>
 /// <param name="uri">The uri to extend</param>
 /// <returns>whether or not the uri contains a '$ref' segment</returns>
 public static bool IsEntityReferenceLink(this ODataUri uri)
 {
     return(uri.Segments.Any(s => s.SegmentType == ODataUriSegmentType.EntityReferenceLinks));
 }
        private ODataUri GenerateEntityIdUri(EntitySet entitySet, EntityType entityType, IEnumerable<NamedValue> keyValues)
        {
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            // null checks performed by ODataUriBuilder
            var conventionalId = new ODataUri();
            conventionalId.Segments.Add(new ServiceRootSegment(this.Service.ServiceUri));
            conventionalId.Segments.Add(ODataUriBuilder.EntitySet(entitySet));
            conventionalId.Segments.Add(ODataUriBuilder.Key(entityType, keyValues));
            return conventionalId;
        }
Beispiel #39
0
 /// <summary>
 /// Returns whether or not the uri ends with a '$value' segment
 /// </summary>
 /// <param name="uri">The uri to extend</param>
 /// <returns>whether or not the uri ends with a '$value' segment</returns>
 public static bool IsPropertyValue(this ODataUri uri)
 {
     return(uri.Segments.Count > 1 && uri.LastSegment.SegmentType == ODataUriSegmentType.Value && uri.Segments[uri.Segments.Count - 2].IsProperty());
 }
Beispiel #40
0
 private static bool CheckLastSegment <TSegment>(this ODataUri uri, Func <TSegment, bool> check) where TSegment : ODataUriSegment
 {
     return(uri.LastSegment.CheckSegment(check));
 }
Beispiel #41
0
 /// <summary>
 /// Helper method for converting an OData uri directly to a system Uri
 /// </summary>
 /// <param name="converter">The uri-to-string converter to extend</param>
 /// <param name="uri">The uri to convert</param>
 /// <returns>The system uri for the given OData uri</returns>
 public static Uri ConvertToUri(this IODataUriToStringConverter converter, ODataUri uri)
 {
     ExceptionUtilities.CheckArgumentNotNull(converter, "converter");
     ExceptionUtilities.CheckArgumentNotNull(uri, "uri");
     return(new Uri(converter.ConvertToString(uri), UriKind.RelativeOrAbsolute));
 }
        internal static ODataUri ConstructODataUriWithoutActionInformation(IEnumerable<EntitySet> entitySets, ODataUri uri)
        {
            var segmentsToInclude = new List<ODataUriSegment>();
            ServiceOperationAnnotation serviceOperationAnnotation = null;
            string setName = null;
            foreach (var segment in uri.Segments)
            {
                var functionSegment = segment as FunctionSegment;
                if (functionSegment != null && functionSegment.Function.IsAction())
                {
                    serviceOperationAnnotation = functionSegment.Function.Annotations.OfType<ServiceOperationAnnotation>().Single();
                    var toggleBooleanAnnotation = functionSegment.Function.Annotations.OfType<ToggleBoolPropertyValueActionAnnotation>().SingleOrDefault();

                    if (toggleBooleanAnnotation != null)
                    {
                        setName = toggleBooleanAnnotation.SourceEntitySet;
                    }

                    break;
                }

                segmentsToInclude.Add(segment);
            }

            if (!serviceOperationAnnotation.BindingKind.IsBound())
            {
                ExceptionUtilities.CheckObjectNotNull(setName, "Cannot find the set name that the action starts from");
                var sourceEntitySet = entitySets.Single(es => es.Name == setName);
                segmentsToInclude.Add(new EntitySetSegment(sourceEntitySet));
            }

            var actionlessODataUri = new ODataUri(segmentsToInclude);
            actionlessODataUri.CustomQueryOptions = uri.CustomQueryOptions;
            actionlessODataUri.Filter = uri.Filter;
            actionlessODataUri.InlineCount = uri.InlineCount;
            actionlessODataUri.OrderBy = uri.OrderBy;
            actionlessODataUri.Skip = uri.Skip;
            actionlessODataUri.SkipToken = uri.SkipToken;
            actionlessODataUri.Top = uri.Top;
            EntitySet expectedEntitySet = null;

            ExceptionUtilities.Assert(actionlessODataUri.TryGetExpectedEntitySet(out expectedEntitySet), "Expected entity set not found");

            // expand all navigations for actionlessODataUri so that we do not need to send additional request when calculating expected action result
            foreach (NavigationProperty navigation in expectedEntitySet.EntityType.NavigationProperties)
            {
                actionlessODataUri.ExpandSegments.Add(new List<ODataUriSegment>() { new NavigationSegment(navigation) });
            }

            return actionlessODataUri;
        }
Beispiel #43
0
        /// <summary>
        /// Uses the content type and uri to get a deserializer, and asserts that the root element is of the expected type
        /// </summary>
        /// <typeparam name="TElement">The expected root element type</typeparam>
        /// <param name="selector">The protocol format selector</param>
        /// <param name="uri">The uri to use for getting a format strategy</param>
        /// <param name="contentType">The content type to use for getting a format strategy</param>
        /// <param name="body">The body to deserialize</param>
        /// <returns>The root element of the body</returns>
        public static TElement DeserializeAndCast <TElement>(this IProtocolFormatStrategySelector selector, ODataUri uri, string contentType, byte[] body) where TElement : ODataPayloadElement
        {
            ExceptionUtilities.CheckArgumentNotNull(selector, "selector");
            ExceptionUtilities.CheckStringArgumentIsNotNullOrEmpty(contentType, "contentType");
            ExceptionUtilities.CheckArgumentNotNull(body, "body");

            // TODO: force uri to be non-null
            var strategy = selector.GetStrategy(contentType, uri);

            ExceptionUtilities.CheckObjectNotNull(strategy, "Could not find protocol strategy for content-type '{0}'.", contentType);

            var deserializer = strategy.GetDeserializer();

            ExceptionUtilities.CheckObjectNotNull(deserializer, "Strategy returned null deserializer");

            string charset = HttpUtilities.GetContentTypeCharsetOrNull(contentType);

            var rootElement = deserializer.DeserializeFromBinary(body, new ODataPayloadContext {
                EncodingName = charset
            });

            ExceptionUtilities.CheckObjectNotNull(rootElement, "Deserializer returned null element");

            var afterCast = rootElement as TElement;

            ExceptionUtilities.CheckObjectNotNull(afterCast, "Root element was of unexpected type '{0}'. Expected '{1}'", rootElement.ElementType, typeof(TElement).Name);

            return(afterCast);
        }
        /// <summary>
        /// Find out whether to expect action descriptor with projection in request uri
        /// </summary>
        /// <param name="requestUri">The request uri</param>
        /// <param name="action">The action</param>
        /// <param name="isTopLevelElement">Whether the entity being verified is top level payload element</param>
        /// <returns>Whether to expect action descriptor</returns>
        private bool ExpectActionWithProjection(ODataUri requestUri, Function action, bool isTopLevelElement)
        {
            ODataUriSegmentPathCollection selectSegments = requestUri.SelectSegments;
            ODataUriSegmentPathCollection expandSegments = requestUri.ExpandSegments;

            // handle single level $select path, expect action descriptor if $select=ActionName or $select=Container.*
            foreach (var selectSegmentPath in selectSegments.Where(ss => ss.Count == 1))
            {
                ODataUriSegment selectSegment = selectSegmentPath.Single();

                if (isTopLevelElement && this.FuctionMatchWithSelectFunctionSegment(action, selectSegment))
                {
                    return true;
                }

                if (this.IsSelectAllFunctionSegment(selectSegment))
                {
                    return true;
                }
            }

            // handle multiple level $select path, expect action descriptor for $expand=Rating if: $select=Rating or $select=Rating/ActionName or $Select=Rating/Container.*
            foreach (var expandSegmentPath in expandSegments)
            {
                List<ODataUriSegment> expandSegmentList = expandSegmentPath.ToList();
                foreach (var selectSegmentPath in selectSegments.Where(ss => ss.Count == expandSegmentPath.Count || ss.Count == expandSegmentPath.Count + 1))
                {
                    List<ODataUriSegment> selectSegmentList = selectSegmentPath.ToList();
                    if (this.FunctionMatchWithExpandSegmentList(selectSegmentList, expandSegmentList, action))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
Beispiel #45
0
 /// <summary>
 /// Returns whether or not the uri refers to the root of the service
 /// </summary>
 /// <param name="uri">The uri to extend</param>
 /// <returns>whether or not the uri refers to the root of the service</returns>
 public static bool IsServiceDocument(this ODataUri uri)
 {
     return(uri.Segments.Count == 1 && uri.LastSegment.SegmentType == ODataUriSegmentType.ServiceRoot);
 }
Beispiel #46
0
        /// <summary>
        /// Generates extra request operations
        /// </summary>
        /// <param name="requestManager">RequestManager to build the operations.</param>
        /// <param name="baseUri">Base uri for the operations</param>
        /// <returns>An array of request operations.</returns>
        public static IMimePart[] ExtraRequestOperations(IODataRequestManager requestManager, ODataUri baseUri)
        {
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            ExceptionUtilities.CheckArgumentNotNull(baseUri, "baseUri");

            var headers = new Dictionary <string, string> {
                { "RequestHeader", "RequestHeaderValue" }
            };
            string mergeContentType      = HttpUtilities.BuildContentType(MimeTypes.ApplicationXml, Encoding.UTF8.WebName, null);
            List <IHttpRequest> requests = new List <IHttpRequest>();

            requests.Add(requestManager.BuildRequest(baseUri, HttpVerb.Get, headers));
            var segments = baseUri.Segments;

            ODataUriSegment[] segmentstoadd =
            {
                ODataUriBuilder.EntitySet(new EntitySet("Set1")),
                ODataUriBuilder.EntityType(new EntityType("EntityType")),
                ODataUriBuilder.EntitySet(new EntitySet("Set2")),
                ODataUriBuilder.EntityType(new EntityType("EntityType2")),
            };

            foreach (var segment in segmentstoadd)
            {
                requests.Add(requestManager.BuildRequest(new ODataUri(segments.ConcatSingle(segment)), HttpVerb.Get, headers));
            }

            return(requests.ToArray());
        }
 /// <summary>
 /// Processes the given uri and produces an expected value according to the conventions of an OData server implementation
 /// </summary>
 /// <param name="evaluator">The evaluator</param>
 /// <param name="uri">The uri to process</param>
 /// <returns>The value resulting from processing the uri</returns>
 public static QueryValue Evaluate(this IODataUriEvaluator evaluator, ODataUri uri)
 {
     ExceptionUtilities.CheckArgumentNotNull(evaluator, "evaluator");
     return evaluator.Evaluate(uri, true, true);
 }
        /// <summary>
        /// Calculates the protocol version based on the ODataUri provided
        /// </summary>
        /// <param name="uri">OData Uri to analyze</param>
        /// <param name="contentType">Content Type</param>
        /// <param name="maxProtocolVersion">The max protocol version</param>
        /// <param name="dataServiceVersion">The data service version of the request</param>
        /// <param name="maxDataServiceVersion">The max data service version of the request</param>
        /// <returns>Data Service Protocol Version</returns>
        public DataServiceProtocolVersion CalculateProtocolVersion(ODataUri uri, string contentType, DataServiceProtocolVersion maxProtocolVersion, DataServiceProtocolVersion dataServiceVersion, DataServiceProtocolVersion maxDataServiceVersion)
        {
            ExceptionUtilities.CheckArgumentNotNull(uri, "uri");
            ExceptionUtilities.Assert(maxProtocolVersion != DataServiceProtocolVersion.Unspecified, "Max protocol version cannot be unspecified");

            if (uri.IsMetadata())
            {
                throw new TaupoNotSupportedException("Context uri should be processed by Entity Model Version Calculator instead");
            }

            DataServiceProtocolVersion expectedVersion = DataServiceProtocolVersion.V4;

            if (uri.IncludesInlineCountAllPages())
            {
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4);
            }

            if (uri.IsCount())
            {
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4);
            }
            else if (uri.IsEntityReferenceLink() || uri.IsNamedStream() || uri.IsPropertyValue())
            {
                // If the uri points to a Link, $value or a named stream their response DSV's are V1 because their payloads are understood by V1
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4);
            }
            else if (uri.HasOpenProperties())
            {
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, VersionHelper.GetMinimumVersion(maxProtocolVersion, maxDataServiceVersion));
            }
            else if (uri.IsProperty())
            {
                var propertySegment = (PropertySegment)uri.LastSegment;
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, VersionHelper.CalculateProtocolVersion(propertySegment.Property));
            }
            else if (uri.IsAction())
            {
                var action = (FunctionSegment)uri.LastSegment;
                if (action.Function.ReturnType != null)
                {
                    var collectionReturnType = action.Function.ReturnType as CollectionDataType;

                    // If its a collection this doesn't bump things to V3 as this is normal behavior from ServiceOperations V1, so only determining version based on non data type
                    DataType versionType = action.Function.ReturnType;
                    
                    var entityVersionType = action.Function.ReturnType as EntityDataType;
                    if (collectionReturnType != null)
                    {
                        entityVersionType = collectionReturnType.ElementDataType as EntityDataType;
                        if (entityVersionType != null)
                        {
                            versionType = entityVersionType;
                        }
                    }

                    // Bump if its an open type
                    if (entityVersionType != null && entityVersionType.Definition.IsOpen)
                    {
                        expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, VersionHelper.GetMinimumVersion(maxProtocolVersion, maxDataServiceVersion));
                    }

                    expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, VersionHelper.CalculateDataTypeVersion(versionType));
                }
            }
            else
            {
                ExceptionUtilities.CheckArgumentNotNull(contentType, "contentType");
                List<DataServiceProtocolVersion> dataServiceProtocolVersions = uri.GetAllEntitySetsIncludingExpands().Select(es => es.CalculateEntitySetProtocolVersion(contentType, VersionCalculationType.Response, maxProtocolVersion, maxDataServiceVersion)).ToList();
                dataServiceProtocolVersions.Add(expectedVersion);
                expectedVersion = VersionHelper.GetMaximumVersion(dataServiceProtocolVersions.ToArray());
            }

            // determine if the uri MIGHT result in there being a next link, and increase version if so
            expectedVersion = VersionHelper.IncreaseVersionIfTrue(ResponseMightIncludeNextLink(uri), expectedVersion, DataServiceProtocolVersion.V4);

            return expectedVersion;
        }
        private string CalculateExpectedETagForEntityOrStream(ODataUri uri, QueryStructuralValue entity)
        {
            if (uri.IsMediaResource())
            {
                return entity.GetDefaultStreamValue().GetExpectedETag();
            }

            if (uri.IsNamedStream())
            {
                var streamSegment = uri.Segments.OfType<NamedStreamSegment>().Last();
                return entity.GetStreamValue(streamSegment.Name).GetExpectedETag();
            }

            return this.LiteralConverter.ConstructWeakETag(entity);
        }
Beispiel #50
0
 /// <summary>
 /// Returns whether or not the uri refers to a function call
 /// </summary>
 /// <param name="uri">The uri to extend</param>
 /// <returns>whether or not the uri refers to a function call</returns>
 public static bool IsFunction(this ODataUri uri)
 {
     return(uri.CheckLastSegment <FunctionSegment>(f => f.Function.IsFunction()) ||
            uri.CheckLastTwoSegments <FunctionSegment, ParametersExpressionSegment>(f => f.Function.IsFunction(), p => true));
 }
        /// <summary>
        /// Generates the expected next link for a top-level feed
        /// </summary>
        /// <param name="requestUri">The request URI.</param>
        /// <param name="pageSize">The page size.</param>
        /// <param name="lastEntityValue">The last entity value.</param>
        /// <returns>
        /// The expected next link
        /// </returns>
        public string GenerateNextLink(ODataUri requestUri, int pageSize, QueryStructuralValue lastEntityValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(requestUri, "requestUri");
            ExceptionUtilities.CheckArgumentNotNull(lastEntityValue, "lastEntityValue");
            
            var queryBasedUri = requestUri as QueryBasedODataUri;
            ExceptionUtilities.CheckObjectNotNull(queryBasedUri, "Only uris which were generated from queries are supported");
            
            var skipTokenValues = new List<object>();
            foreach (var keySelector in queryBasedUri.OrderByExpressions.SelectMany(o => o.KeySelectors))
            {
                skipTokenValues.Add(this.EvaluateLambdaForEntity(lastEntityValue, keySelector));
            }

            foreach (var keyProperty in lastEntityValue.Type.Properties.Where(p => p.IsPrimaryKey))
            {
                skipTokenValues.Add(lastEntityValue.GetScalarValue(keyProperty.Name).Value);
            }

            var skiptoken = this.BuildSkipTokenFromValues(skipTokenValues);

            // copy request uri segments exactly
            var nextLinkUri = new ODataUri(requestUri.Segments);

            // copy over $orderby, $filter, $expand, $select, and $inlinecount
            nextLinkUri.OrderBy = ModifyQueryOptionToMatchProduct(requestUri.OrderBy);
            nextLinkUri.Filter = ModifyQueryOptionToMatchProduct(requestUri.Filter);
            nextLinkUri.ExpandSegments = requestUri.ExpandSegments;
            nextLinkUri.SelectSegments = requestUri.SelectSegments;

            string inlineCountValue;
            if (requestUri.TryGetInlineCountValue(out inlineCountValue))
            {
                nextLinkUri.InlineCount = inlineCountValue;
            }

            // add the $skiptoken generated above
            nextLinkUri.SkipToken = skiptoken;

            // generate a new $top value
            if (requestUri.Top.HasValue)
            {
                var top = requestUri.Top.Value - pageSize;
                if (top > 0)
                {
                    nextLinkUri.Top = top;
                }
            }

            if (requestUri.IsServiceOperation())
            {
                var functionSegment = requestUri.Segments.OfType<FunctionSegment>().Last();
                foreach (var paramName in functionSegment.Function.Parameters.Select(p => p.Name))
                {
                    string paramValue;
                    if (requestUri.CustomQueryOptions.TryGetValue(paramName, out paramValue))
                    {
                        nextLinkUri.CustomQueryOptions[paramName] = paramValue;
                    }
                }
            }

            return this.UriToStringConverter.ConvertToString(nextLinkUri);
        }
Beispiel #52
0
 /// <summary>
 /// Returns whether or not the uri refers to a named stream
 /// </summary>
 /// <param name="uri">The uri to extend</param>
 /// <returns>whether or not the uri refers to a named stream</returns>
 public static bool IsNamedStream(this ODataUri uri)
 {
     return(uri.Segments.Count > 0 && uri.LastSegment.SegmentType == ODataUriSegmentType.NamedStream);
 }
        internal static bool ResponseMightIncludeNextLink(ODataUri uri)
        {
            var payloadsWithNextLinks = new[] { ODataPayloadElementType.EntitySetInstance, ODataPayloadElementType.LinkCollection };
            var expectedPayloadType = uri.GetExpectedPayloadType();
            if (!payloadsWithNextLinks.Contains(expectedPayloadType))
            {
                return false;
            }

            EntitySet expectedSet;
            ExceptionUtilities.Assert(uri.TryGetExpectedEntitySet(out expectedSet), "Could not get expected entity set");

            var pageSize = expectedSet.GetEffectivePageSize();
            if (!pageSize.HasValue)
            {
                return false;
            }

            // if the value of $top is less than 1 page size, no next link will be included
            return !uri.Top.HasValue || uri.Top.Value > pageSize.Value;
        }
Beispiel #54
0
        /// <summary>
        /// Returns whether or not the uri contains one or more open properties
        /// </summary>
        /// <param name="uri">The uri to extend</param>
        /// <returns>whether or not the uri contains one or more open properties</returns>
        public static bool HasOpenProperties(this ODataUri uri)
        {
            EntitySet           currentSet  = null;
            NamedStructuralType currentType = null;

            foreach (var segment in uri.Segments)
            {
                var setSegment = segment as EntitySetSegment;
                if (setSegment != null)
                {
                    currentSet  = setSegment.EntitySet;
                    currentType = currentSet.EntityType;
                    continue;
                }

                var serviceOperationSegment = segment as FunctionSegment;
                if (serviceOperationSegment != null)
                {
                    EntitySet svcOpEntitySet;
                    if (serviceOperationSegment.Function.TryGetExpectedEntitySet(currentSet, out svcOpEntitySet))
                    {
                        currentSet  = svcOpEntitySet;
                        currentType = currentSet.EntityType;
                        continue;
                    }
                }

                var navigationSegment = segment as NavigationSegment;
                if (navigationSegment != null)
                {
                    ExceptionUtilities.CheckObjectNotNull(currentSet, "Cannot have navigation before a root set or function");
                    currentSet  = currentSet.GetRelatedEntitySet(navigationSegment.NavigationProperty);
                    currentType = currentSet.EntityType;
                    continue;
                }

                var typeSegment = segment as EntityTypeSegment;
                if (typeSegment != null)
                {
                    currentType = typeSegment.EntityType;
                    continue;
                }

                var propertySegment = segment as PropertySegment;
                if (propertySegment != null)
                {
                    ExceptionUtilities.CheckObjectNotNull(currentType, "Cannot have property before a root set or function");
                    if (currentType.IsOpen && !propertySegment.Property.IsMetadataDeclaredProperty())
                    {
                        return(true);
                    }
                }

                var unrecognizedSegment = segment as UnrecognizedSegment;
                if (unrecognizedSegment != null && currentType != null)
                {
                    ExceptionUtilities.CheckObjectNotNull(currentType, "Cannot have property before a root set or function");
                    if (currentType.IsOpen)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        internal static void SetupProtocolRequest(QueryExpression expression, IODataRequestManager requestManager, IQueryToODataPayloadConverter queryToPayloadConverter, ODataUri uri, HttpHeaderCollection headers, string actionContentType, out Contracts.OData.ODataRequest request)
        {
            HttpVerb requestVerb = HttpVerb.Get;
            if (uri.IsAction())
            {
                requestVerb = HttpVerb.Post;
            }

            if (uri.IsWebInvokeServiceOperation())
            {
                requestVerb = HttpVerb.Post;
            }

            request = requestManager.BuildRequest(uri, requestVerb, headers);
            if (uri.IsAction())
            {
                var procedurePayload = queryToPayloadConverter.ComputePayload(expression) as ComplexInstance;

                if (procedurePayload != null)
                {
                    request.Headers.Add(HttpHeaders.ContentType, actionContentType);

                    FixupAddingResultWrappers(actionContentType, procedurePayload);

                    // TODO: Need to understand if product allow an Html form even if no parameters specified
                    request.Body = requestManager.BuildBody(actionContentType, uri, procedurePayload);
                }
            }
        }
Beispiel #56
0
        /// <summary>
        /// Gets the metadata for the set expected for the given uri. If it would return an entity or single property, it will return the set the entity belongs to
        /// </summary>
        /// <param name="uri">The uri to get the set for</param>
        /// <param name="expectedEntitySet">The expected entity set if appropriate, otherwise null</param>
        /// <returns>Whether an expected entity set could be inferred</returns>
        public static bool TryGetExpectedEntitySet(this ODataUri uri, out EntitySet expectedEntitySet)
        {
            EntityType entityType;

            return(uri.TryGetExpectedEntitySetAndType(out expectedEntitySet, out entityType));
        }
Beispiel #57
0
        /// <summary>
        /// Generates the raw test message with mixed encodings defined by the test case, as well as the expected ODataPayloadElement.
        /// </summary>
        /// <param name="testCase">The test case defining the structure and encodings of the batch payload.</param>
        /// <param name="payload">The payload to use for all generated batch operations.</param>
        /// <param name="payloadUri">The URI to use for all generated batch operations.</param>
        /// <param name="isRequest">If true, generates a batch request, otherwise a batch response.</param>
        /// <returns>The test descriptor for this test case/configuration.</returns>
        private BatchReaderMixedEncodingTestDescriptor CreateTestDescriptor(BatchReaderMixedEncodingTestCase testCase, ODataPayloadElement payload, ODataUri payloadUri, bool isRequest)
        {
            ExceptionUtilities.Assert(testCase.BatchEncoding != null, "Batch encoding has not been specified.");

            string batchBoundary    = "batch_" + Guid.NewGuid().ToString();
            string payloadUriString = this.UriConverter.ConvertToString(payloadUri);

            var batchPayload = isRequest ? (ODataPayloadElement) new BatchRequestPayload() : (ODataPayloadElement) new BatchResponsePayload();

            batchPayload.AddAnnotation(new BatchBoundaryAnnotation(batchBoundary));

            var rawMessage = new List <byte>();

            // TODO: Batch reader does not support multi codepoint encodings
            Encoding unsupportedEncoding = AsUnsupportedEncoding(testCase.BatchEncoding);

            foreach (var changeset in testCase.Changesets)
            {
                string   changesetBoundary = "change_" + Guid.NewGuid().ToString();
                Encoding changesetEncoding = changeset.ChangesetEncoding ?? testCase.BatchEncoding;

                // TODO: Batch reader does not support multi codepoint encodings
                unsupportedEncoding = unsupportedEncoding ?? AsUnsupportedEncoding(changesetEncoding);

                string changesetContentType = HttpUtilities.BuildContentType(
                    MimeTypes.MultipartMixed,
                    changeset.ChangesetEncoding == null ? string.Empty : changeset.ChangesetEncoding.WebName,
                    changesetBoundary);

                rawMessage.AddRange(
                    WriteMessagePart(
                        testCase.BatchEncoding,
                        (writer) =>
                {
                    writer.Write("--");
                    writer.WriteLine(batchBoundary);
                    writer.WriteLine(HttpHeaders.ContentType + ": " + changesetContentType);
                    writer.WriteLine();
                }));

                var mimeParts = new List <IMimePart>();
                int contentId = 0;

                foreach (var operation in changeset.Operations)
                {
                    ExceptionUtilities.Assert(operation.PayloadFormat == ODataFormat.Atom || operation.PayloadFormat == ODataFormat.Json, "Payload format must be ATOM or JSON.");
                    string   formatType         = MimeTypes.ApplicationAtomXml + ";type=entry";
                    Encoding payloadEncoding    = operation.OperationEncoding ?? changesetEncoding;
                    string   payloadContentType = HttpUtilities.BuildContentType(
                        formatType,
                        operation.OperationEncoding == null ? string.Empty : operation.OperationEncoding.WebName,
                        string.Empty);

                    string httpStatus = isRequest ? "POST " + payloadUriString + " HTTP/1.1" : "HTTP/1.1 201 Created";

                    rawMessage.AddRange(
                        WriteMessagePart(
                            changesetEncoding,
                            (writer) =>
                    {
                        writer.WriteLine();
                        writer.Write("--");
                        writer.WriteLine(changesetBoundary);
                        writer.WriteLine(HttpHeaders.ContentType + ": application/http");
                        writer.WriteLine(HttpHeaders.ContentTransferEncoding + ": binary");
                        writer.WriteLine(HttpHeaders.ContentId + ": " + (++contentId).ToString());
                        writer.WriteLine();
                        writer.WriteLine(httpStatus);
                        writer.WriteLine(HttpHeaders.ContentType + ": " + payloadContentType);
                        writer.WriteLine();
                    }));

                    IPayloadSerializer payloadSerializer =
                        operation.PayloadFormat == ODataFormat.Atom ?
                        (IPayloadSerializer) new XmlPayloadSerializer(this.PayloadElementToXmlConverter) :
                        (IPayloadSerializer) new JsonPayloadSerializer(this.PayloadElementToJsonConverter.ConvertToJson);

                    byte[] payloadBytes = payloadSerializer.SerializeToBinary(payload, payloadEncoding.WebName);
                    rawMessage.AddRange(payloadBytes.Skip(payloadEncoding.GetPreamble().Length));

                    if (isRequest)
                    {
                        var request = this.RequestManager.BuildRequest(payloadUri, HttpVerb.Post, new Dictionary <string, string> {
                            { HttpHeaders.ContentType, payloadContentType }
                        });
                        request.Body = new ODataPayloadBody(payloadBytes, payload);
                        mimeParts.Add(request);
                    }
                    else
                    {
                        var httpResponseData = new HttpResponseData {
                            StatusCode = HttpStatusCode.Created,
                        };
                        httpResponseData.Headers.Add(HttpHeaders.ContentType, payloadContentType);
                        var response = new ODataResponse(httpResponseData)
                        {
                            Body = payloadBytes, RootElement = payload
                        };
                        mimeParts.Add(response);
                    }
                }

                rawMessage.AddRange(
                    WriteMessagePart(
                        changesetEncoding,
                        (writer) =>
                {
                    writer.WriteLine();
                    writer.Write("--");
                    writer.Write(changesetBoundary);
                    writer.WriteLine("--");
                }));

                if (isRequest)
                {
                    ((BatchRequestPayload)batchPayload).Add(BatchPayloadBuilder.RequestChangeset(changesetBoundary, changesetEncoding.WebName, mimeParts.ToArray()));
                }
                else
                {
                    ((BatchResponsePayload)batchPayload).Add(BatchPayloadBuilder.ResponseChangeset(changesetBoundary, changesetEncoding.WebName, mimeParts.ToArray()));
                }
            }

            rawMessage.AddRange(
                WriteMessagePart(
                    testCase.BatchEncoding,
                    (writer) =>
            {
                writer.WriteLine();
                writer.Write("--");
                writer.Write(batchBoundary);
                writer.WriteLine("--");
            }));

            return(new BatchReaderMixedEncodingTestDescriptor(this.PayloadReaderSettings)
            {
                BatchContentTypeHeader = HttpUtilities.BuildContentType(MimeTypes.MultipartMixed, testCase.BatchEncoding.WebName, batchBoundary),
                RawMessage = rawMessage.ToArray(),
                PayloadElement = batchPayload,
                ExpectedException = unsupportedEncoding == null ? null : ODataExpectedExceptions.ODataException("ODataBatchReaderStream_MultiByteEncodingsNotSupported", unsupportedEncoding.WebName)
            });
        }
Beispiel #58
0
        public static bool TryGetExpectedEntitySetAndType(this ODataUri uri, out EntitySet expectedEntitySet, out EntityType expectedEntityType)
        {
            EntitySet  expectedSet  = null;
            EntityType expectedType = null;

            foreach (var segment in uri.Segments)
            {
                var setSegment = segment as EntitySetSegment;
                if (setSegment != null)
                {
                    expectedSet  = setSegment.EntitySet;
                    expectedType = expectedSet.EntityType;
                    continue;
                }

                var navigationSegment = segment as NavigationSegment;
                if (navigationSegment != null)
                {
                    expectedSet  = expectedSet.GetRelatedEntitySet(navigationSegment.NavigationProperty);
                    expectedType = navigationSegment.NavigationProperty.ToAssociationEnd.EntityType;
                    continue;
                }

                var functionSegment = segment as FunctionSegment;
                if (functionSegment != null)
                {
                    EntitySet svcOpEntitySet;
                    if (!functionSegment.Function.TryGetExpectedEntitySet(expectedSet, out svcOpEntitySet))
                    {
                        expectedSet = null;
                        continue;
                    }

                    expectedSet = svcOpEntitySet;

                    EntityDataType entityDataType;
                    var            returnType           = functionSegment.Function.ReturnType;
                    var            collectionReturnType = returnType as CollectionDataType;
                    if (collectionReturnType != null)
                    {
                        entityDataType = collectionReturnType.ElementDataType as EntityDataType;
                    }
                    else
                    {
                        entityDataType = returnType as EntityDataType;
                    }

                    if (entityDataType != null)
                    {
                        expectedType = entityDataType.Definition;
                    }
                    else
                    {
                        expectedType = expectedSet.EntityType;
                    }

                    continue;
                }

                var typeSegment = segment as EntityTypeSegment;
                if (typeSegment != null)
                {
                    expectedType = typeSegment.EntityType;
                    continue;
                }
            }

            expectedEntitySet  = expectedSet;
            expectedEntityType = expectedType;
            return(expectedSet != null);
        }
Beispiel #59
0
 /// <summary>
 /// Returns whether or not the uri refers to a procedure call
 /// </summary>
 /// <param name="uri">The uri to extend</param>
 /// <returns>whether or not the uri refers to a procedure call</returns>
 public static bool IsAction(this ODataUri uri)
 {
     return(uri.CheckLastSegment <FunctionSegment>(f => f.Function.IsAction()));
 }
Beispiel #60
0
        /// <summary>
        /// Builds the ODataPayloadContext context from OODataUri.
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <returns>A OData Payload Context</returns>
        public static ODataPayloadContext BuildODataPayloadContextFromODataUri(ODataUri uri)
        {
            var payloadContext = new ODataPayloadContext();

            payloadContext.PayloadUri          = uri;
            payloadContext.ExpectedPayloadKind = uri.GetExpectedPayloadType();

            switch (payloadContext.ExpectedPayloadKind)
            {
            case ODataPayloadElementType.EntitySetInstance:
            case ODataPayloadElementType.EntityInstance:
                SetExpectedEntitySetAndTypeFromUri(payloadContext, uri);
                break;

            case ODataPayloadElementType.PrimitiveProperty:
            case ODataPayloadElementType.PrimitiveMultiValueProperty:
            case ODataPayloadElementType.ComplexProperty:
            case ODataPayloadElementType.ComplexMultiValueProperty:
            case ODataPayloadElementType.EmptyCollectionProperty:
                var propertySegment = uri.Segments.OfType <PropertySegment>().LastOrDefault();
                if (propertySegment != null)
                {
                    payloadContext.ExpectedMemberProperty = propertySegment.Property;
                    SetExpectedEntitySetAndTypeFromUri(payloadContext, uri);

                    var parentPropertySegment = uri.Segments.GetSecondToLastOrDefault <PropertySegment>();
                    if (parentPropertySegment != null)
                    {
                        var collectionDataType = parentPropertySegment.Property.PropertyType as CollectionDataType;
                        if (collectionDataType != null)
                        {
                            var elementComplexDataType = collectionDataType.ElementDataType as ComplexDataType;
                            ExceptionUtilities.CheckObjectNotNull(elementComplexDataType, "Expected non complex DataType");
                            payloadContext.ExpectedPropertyDeclaringParentType = elementComplexDataType.Definition;
                        }
                        else
                        {
                            var complexDataType = parentPropertySegment.Property.PropertyType as ComplexDataType;
                            ExceptionUtilities.CheckObjectNotNull(complexDataType, "Expected non null complex DataType");
                            payloadContext.ExpectedPropertyDeclaringParentType = complexDataType.Definition;
                        }
                    }
                    else
                    {
                        payloadContext.ExpectedPropertyDeclaringParentType = payloadContext.ExpectedEntityType;
                    }
                }
                else
                {
                    ExceptionUtilities.Assert(
                        uri.IsFunction() || uri.IsServiceOperation() || uri.IsAction(),
                        "Property uri contains no property segments and is not a function/service operation/action.");
                    var functionSegment = uri.Segments.Last() as FunctionSegment ?? uri.Segments[uri.Segments.Count - 2] as FunctionSegment;
                    ExceptionUtilities.CheckObjectNotNull(functionSegment, "Failed to find function segment in finction/service operation uri");
                    payloadContext.ExpectedFunction = functionSegment.Function;
                }

                break;

            case ODataPayloadElementType.DeferredLink:
            case ODataPayloadElementType.LinkCollection:
                var navigationSegment = uri.Segments.OfType <NavigationSegment>().Last();
                ExceptionUtilities.CheckObjectNotNull(navigationSegment, "No navigation segments found for expected navigation property uri");
                payloadContext.ExpectedNavigationProperty = navigationSegment.NavigationProperty;
                SetExpectedEntitySetAndTypeFromUri(payloadContext, uri);
                break;
            }

            return(payloadContext);
        }