/// <summary> /// Returns whether or not the uri refers to a WebInvoke service operation call /// </summary> /// <param name="uri">The uri to extend</param> /// <returns>whether or not the uri refers to a WebInvoke service operation call</returns> public static bool IsWebInvokeServiceOperation(this ODataUri uri) { if (uri.IsServiceOperation()) { ODataUriSegment functionSegment = uri.Segments.First(s => s is FunctionSegment); return(functionSegment.CheckSegment <FunctionSegment>(f => f.Function.Annotations.OfType <LegacyServiceOperationAnnotation>().Single().Method == Http.HttpVerb.Post)); } return(false); }
/// <summary> /// Gets the expected payload type for a request to the given uri /// </summary> /// <param name="requestUri">The request uri</param> /// <returns>The expected payload type</returns> public static ODataPayloadElementType GetExpectedPayloadType(this ODataUri requestUri) { if (requestUri.Segments.OfType <UnrecognizedSegment>().Any()) { return(ODataPayloadElementType.Unknown); } if (requestUri.IsMetadata()) { return(ODataPayloadElementType.MetadataPayloadElement); } if (requestUri.IsBatch()) { return(ODataPayloadElementType.BatchResponsePayload); } if (requestUri.IsCount() || requestUri.IsPropertyValue() || requestUri.IsMediaResource() || requestUri.IsNamedStream()) { return(ODataPayloadElementType.PrimitiveValue); } if (requestUri.IsEntity()) { return(ODataPayloadElementType.EntityInstance); } if (requestUri.IsEntitySet()) { return(ODataPayloadElementType.EntitySetInstance); } if (requestUri.IsEntityReferenceLink()) { return(requestUri.GetExpectedLinkPayloadType()); } if (requestUri.IsProperty()) { var property = requestUri.Segments.OfType <PropertySegment>().Last(); return(property.Property.GetExpectedPayloadType()); } if (requestUri.IsServiceOperation() || requestUri.IsAction()) { var serviceOp = requestUri.Segments.OfType <FunctionSegment>().Last(); return(serviceOp.Function.GetExpectedPayloadType()); } return(ODataPayloadElementType.Unknown); }
/// <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); }
/// <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); }
/// <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; }