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); }
/// <summary> /// Find out whether to use payload for client verification /// </summary> /// <param name="queryUri">The request uri</param> /// <returns>Whether to use payload for client verification</returns> private bool ShouldUsePayloadDrivenVerification(ODataUri queryUri) { if (queryUri.IsAction()) { return(true); } if (queryUri.IsServiceOperation()) { FunctionSegment functionSegment = queryUri.Segments.OfType <FunctionSegment>().Last(); return(!functionSegment.Function.Annotations.OfType <FunctionBodyAnnotation>().Single().IsRoot); } return(false); }
/// <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)); }