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); } } }
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; }
/// <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; }
/// <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; }