Beispiel #1
0
        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 #2
0
        internal static DataServiceProtocolVersion CalculateUriResponseMinProtocolVersion(ODataUri requestUri, string contentType, DataServiceProtocolVersion maxProtocolVersion, DataServiceProtocolVersion maxDataServiceVersion)
        {
            DataServiceProtocolVersion expectedVersion = DataServiceProtocolVersion.V4;

            if (requestUri.IncludesInlineCountAllPages())
            {
                expectedVersion = expectedVersion.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4);
            }

            if (requestUri.IsCount())
            {
                expectedVersion = expectedVersion.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4);
            }
            else if (requestUri.IsProperty())
            {
                var propertySegment = requestUri.LastSegment as PropertySegment;
                expectedVersion = expectedVersion.IncreaseVersionIfRequired(propertySegment.Property.CalculateProtocolVersion());
            }
            else if (!requestUri.IsNamedStream())
            {
                // Check service operations returning non-entity types
                if (requestUri.IsServiceOperation())
                {
                    var      serviceOpSegment = requestUri.Segments.OfType <FunctionSegment>().Single();
                    DataType returnType       = serviceOpSegment.Function.ReturnType;

                    // Service ops returning complex values or bags of complex values, where the complex type has bag properties, are v3
                    var collectionType = returnType as CollectionDataType;
                    if (collectionType != null)
                    {
                        // for service operations, the fact that a collection is returned does not mean it is a multivalue
                        // so we unwrap the element type before calculating the version
                        returnType = collectionType.ElementDataType;
                    }

                    expectedVersion = expectedVersion.IncreaseVersionIfRequired(returnType.CalculateDataTypeVersion());
                }

                // Check entity types
                List <DataServiceProtocolVersion> dataServiceProtocolVersions = new List <DataServiceProtocolVersion>();
                dataServiceProtocolVersions.Add(expectedVersion);

                if (!(requestUri.IsEntityReferenceLink() || requestUri.IsPropertyValue()))
                {
                    foreach (EntitySet entitySet in requestUri.GetAllEntitySetsIncludingExpands())
                    {
                        DataServiceProtocolVersion entitySetVersion = entitySet.CalculateEntitySetProtocolVersion(contentType, VersionCalculationType.Response, maxProtocolVersion, maxDataServiceVersion);
                        dataServiceProtocolVersions.Add(entitySetVersion);
                        if (entitySetVersion > maxDataServiceVersion)
                        {
                            return(VersionHelper.GetMaximumVersion(dataServiceProtocolVersions.ToArray()));
                        }
                    }
                }
            }

            return(expectedVersion);
        }
Beispiel #3
0
        internal static DataServiceProtocolVersion CalculateUriMinRequestProtocolVersion(ODataUri requestUri, string contentType, DataServiceProtocolVersion maxProtocolVersion, DataServiceProtocolVersion maxDataServiceVersion)
        {
            DataServiceProtocolVersion expectedVersion = DataServiceProtocolVersion.V4;

            string inlineCount;

            if (requestUri.TryGetInlineCountValue(out inlineCount))
            {
                expectedVersion = expectedVersion.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4);
            }

            if (requestUri.SelectSegments.Count > 0)
            {
                expectedVersion = expectedVersion.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4);
            }

            if (requestUri.HasAnyOrAllInFilter())
            {
                expectedVersion = expectedVersion.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4);
            }

            if (requestUri.IsCount())
            {
                expectedVersion = expectedVersion.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4);
            }
            else if (requestUri.IsProperty())
            {
                var propertySegment = requestUri.LastSegment as PropertySegment;
                expectedVersion = expectedVersion.IncreaseVersionIfRequired(propertySegment.Property.CalculateProtocolVersion());
            }
            else
            {
                EntitySet expectedEntitySet = null;
                if (requestUri.TryGetExpectedEntitySet(out expectedEntitySet))
                {
                    List <DataServiceProtocolVersion> dataServiceProtocolVersions = GetEntityTypes(expectedEntitySet).Select(et => et.CalculateEntityPropertyMappingProtocolVersion(VersionCalculationType.Request, contentType, maxProtocolVersion, maxDataServiceVersion)).ToList();
                    dataServiceProtocolVersions.Add(expectedVersion);
                    expectedVersion = VersionHelper.GetMaximumVersion(dataServiceProtocolVersions.ToArray());
                }
            }

            return(expectedVersion);
        }
        /// <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>
        /// 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);
        }
Beispiel #6
0
        /// <summary>
        /// Processes the given uri and produces an expected value according to the conventions of an OData server implementation
        /// </summary>
        /// <param name="uri">The uri to process</param>
        /// <param name="applySelectAndExpand">A value indicating whether or not $select and $expand should be applied to the query values</param>
        /// <param name="applyPaging">A value indicating whether server-driven paging should be applied to the query values</param>
        /// <returns>The value resulting from processing the uri</returns>
        public QueryValue Evaluate(ODataUri uri, bool applySelectAndExpand, bool applyPaging)
        {
            this.applyPagingInExpands = applyPaging;
            ExceptionUtilities.CheckArgumentNotNull(uri, "uri");
            ExceptionUtilities.CheckCollectionNotEmpty(uri.Segments, "uri.Segments");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            this.currentUri = uri;
            this.shouldLastSegmentBeSingleton = false;

            applyPaging &= uri.TryGetExpectedEntitySet(out this.expectedEntitySet);

            if (applyPaging)
            {
                // compute the expected page size for this request based on the existence of a universal page size or set-specific page size
                this.expectedPageSize = this.expectedEntitySet.GetEffectivePageSize();
            }
            else
            {
                this.expectedPageSize = null;
            }

            var query = this.BuildQueryFromSegments();

            ExceptionUtilities.CheckObjectNotNull(query, "Could not build query from uri '{0}'", uri);

            // we explicitly do not process expand or select here because they do not affect the number of rows returned or their ordering
            query = this.ProcessFilter(query);
            ExceptionUtilities.CheckObjectNotNull(query, "Could not build query from uri '{0}'", uri);

            if (uri.IsEntitySet())
            {
                // TODO: skip-token processing should happen before ordering
                query = this.ProcessOrderBy(query);
                ExceptionUtilities.CheckObjectNotNull(query, "Could not build query from uri '{0}'", uri);

                query = this.ProcessSkipAndTop(query);
                ExceptionUtilities.CheckObjectNotNull(query, "Could not build query from uri '{0}'", uri);
            }

            // handle $count requests
            if (uri.IsCount())
            {
                query = query.LongCount();
            }

            // need to resolve types since we constructed new QueryExpression tree
            var resolvedQuery = this.QueryResolver.Resolve(query);

            var value = this.Evaluator.Evaluate(resolvedQuery);

            ExceptionUtilities.CheckObjectNotNull(value, "Could not evaluate query '{0}'", query);
            ExceptionUtilities.Assert(value.EvaluationError == null, "Query evaluation produced an error: {0}", value.EvaluationError);

            // post-process the result to defer properties that were not expanded
            if (applySelectAndExpand)
            {
                value = this.ApplySelectAndExpand(uri, value);
            }

            // fixup for key expressions that should return singletons
            if (this.shouldLastSegmentBeSingleton)
            {
                value = EnsureLastSegmentIsSingletonOrNull(value);
            }

            this.currentUri        = null;
            this.expectedEntitySet = null;
            this.expectedPageSize  = null;

            return(value);
        }