Example #1
0
        /// <summary>
        /// Binds a service operation segment.
        /// </summary>
        /// <param name="segmentToken">The segment which represents a service operation.</param>
        /// <param name="serviceOperation">The service operation to bind.</param>
        /// <returns>The bound node.</returns>
        private QueryNode BindServiceOperation(SegmentQueryToken segmentToken, IEdmFunctionImport serviceOperation)
        {
            Debug.Assert(segmentToken != null, "segmentToken != null");
            Debug.Assert(serviceOperation != null, "serviceOperation != null");
            Debug.Assert(segmentToken.Name == serviceOperation.Name, "The segment represents a different service operation.");

            //// This is a metadata copy of the RequestUriProcessor.CreateSegmentForServiceOperation

            //// The WCF DS checks the verb in this place, we can't do that here

            // All service operations other than those returning IQueryable MUST NOT have () appended to the URI
            // V1/V2 behavior: if it's IEnumerable<T>, we do not allow () either, because it's not further composable.
            ODataServiceOperationResultKind? resultKind = serviceOperation.GetServiceOperationResultKind(this.model);
            if (resultKind != ODataServiceOperationResultKind.QueryWithMultipleResults && segmentToken.NamedValues != null)
            {
                throw new ODataException(Strings.MetadataBinder_NonQueryableServiceOperationWithKeyLookup(segmentToken.Name));
            }

            if (!resultKind.HasValue)
            {
                throw new ODataException(Strings.MetadataBinder_ServiceOperationWithoutResultKind(serviceOperation.Name));
            }

            IEnumerable<QueryNode> serviceOperationParameters = this.BindServiceOperationParameters(serviceOperation);
            switch (resultKind.Value)
            {
                case ODataServiceOperationResultKind.QueryWithMultipleResults:
                    if (serviceOperation.ReturnType.TypeKind() != EdmTypeKind.Entity)
                    {
                        throw new ODataException(Strings.MetadataBinder_QueryServiceOperationOfNonEntityType(serviceOperation.Name, resultKind.Value.ToString(), serviceOperation.ReturnType.ODataFullName()));
                    }

                    CollectionServiceOperationQueryNode collectionServiceOperationQueryNode = new CollectionServiceOperationQueryNode()
                    {
                        ServiceOperation = serviceOperation,
                        Parameters = serviceOperationParameters
                    };

                    if (segmentToken.NamedValues != null)
                    {
                        return this.BindKeyValues(collectionServiceOperationQueryNode, segmentToken.NamedValues);
                    }
                    else
                    {
                        return collectionServiceOperationQueryNode;
                    }

                case ODataServiceOperationResultKind.QueryWithSingleResult:
                    if (!serviceOperation.ReturnType.IsODataEntityTypeKind())
                    {
                        throw new ODataException(Strings.MetadataBinder_QueryServiceOperationOfNonEntityType(serviceOperation.Name, resultKind.Value.ToString(), serviceOperation.ReturnType.ODataFullName()));
                    }

                    return new SingleValueServiceOperationQueryNode()
                    {
                        ServiceOperation = serviceOperation,
                        Parameters = serviceOperationParameters
                    };

                case ODataServiceOperationResultKind.DirectValue:
                    if (serviceOperation.ReturnType.IsODataPrimitiveTypeKind())
                    {
                        // Direct primitive values are composable, $value is allowed on them.
                        return new SingleValueServiceOperationQueryNode()
                        {
                            ServiceOperation = serviceOperation,
                            Parameters = serviceOperationParameters
                        };
                    }
                    else
                    {
                        // Direct non-primitive values are not composable at all
                        return new UncomposableServiceOperationQueryNode()
                        {
                            ServiceOperation = serviceOperation,
                            Parameters = serviceOperationParameters
                        };
                    }

                case ODataServiceOperationResultKind.Enumeration:
                case ODataServiceOperationResultKind.Void:
                    // Enumeration and void service operations are not composable
                    return new UncomposableServiceOperationQueryNode()
                    {
                        ServiceOperation = serviceOperation,
                        Parameters = serviceOperationParameters
                    };

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.MetadataBinder_BindServiceOperation));
            }
        }
 /// <summary>
 /// Translates a service operation node which returns a collection of entities.
 /// </summary>
 /// <param name="serviceOperationNode">The collection service operation node to translate.</param>
 /// <returns>Expression which evaluates to IQueryable&lt;T&gt; where T is the InstanceType of the ResultType of the service operation.</returns>
 protected abstract Expression TranslateCollectionServiceOperation(CollectionServiceOperationQueryNode serviceOperationNode);