Example #1
0
        /// <summary>
        /// Returns a test instance of one of the provider OM types.
        /// </summary>
        /// <param name="type">The type to get instance of.</param>
        /// <returns>The </returns>
        public static object GetTestInstance(Type type)
        {
            if (type == typeof(ResourceType))
            {
                ResourceProperty p = new ResourceProperty("ID", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false };
                ResourceType resourceType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Foo", "NoBaseType", false);
                Assert.IsTrue(resourceType.KeyProperties.Count == 0, "It's okay not to have key properties, since we haven't set this type to readonly yet");
                resourceType.AddProperty(p);
                return resourceType;
            }
            else if (type == typeof(ResourceProperty))
            {
                return new ResourceProperty("NonKeyProperty", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int)));
            }
            else if (type == typeof(ServiceOperation))
            {
                ServiceOperationParameter parameter = new ServiceOperationParameter("o", ResourceType.GetPrimitiveResourceType(typeof(string)));
                ServiceOperation operation = new ServiceOperation("Dummy", ServiceOperationResultKind.Void, null, null, "POST", new ServiceOperationParameter[] { parameter });
                return operation;
            }
            else if (type == typeof(ServiceOperationParameter))
            {
                return new ServiceOperationParameter("o", ResourceType.GetPrimitiveResourceType(typeof(string)));
            }
            else if (type == typeof(ResourceSet))
            {
                ResourceProperty p = new ResourceProperty("ID", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, ResourceType.GetPrimitiveResourceType(typeof(int)));

                ResourceType resourceType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Foo", "NoBaseType", false);
                resourceType.AddProperty(p);
                return new ResourceSet("Customers", resourceType);
            }

            throw new Exception(String.Format("Unexpected type encountered: '{0}'", type.FullName));
        }
Example #2
0
        } // IsNullPropagationRequired

        public object InvokeServiceOperation(DSP.ServiceOperation serviceOperation, object[] parameters)
        {
            MethodInfo methodInfo = _service.GetType().GetMethod(serviceOperation.Name);

            if (methodInfo == null)
            {
                throw new Exception(String.Format("Method with name '{0}' not found on the context instance", serviceOperation.Name));
            }

            return(methodInfo.Invoke(_service, parameters));
        } // InvokeServiceOperation
Example #3
0
        } // TryResolveResourceSet

        public bool TryResolveServiceOperation(string name, out DSP.ServiceOperation serviceOperation)
        {
            if (this.ServiceOperations != null)
            {
                serviceOperation = this.ServiceOperations.Where <DSP.ServiceOperation>(s => s.Name == name).FirstOrDefault <DSP.ServiceOperation>();
                return(serviceOperation != null);
            }

            serviceOperation = null;
            return(false);
        } // TryResolveServiceOperation
        public OperationCacheTests()
        {
            this.entityType1 = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "My.Namespace", "Entity1", false);
            this.entityType2 = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "My.Namespace", "Entity2", false);

            var intType = ResourceType.GetPrimitiveResourceType(typeof(int));
            this.actionWithBindingParameter1 = CreateAction("SameName", intType, this.entityType1);
            this.actionWithBindingParameter2 = CreateAction("SameName", intType, this.entityType2);
            this.serviceOperation = CreateServiceOperation("SameName", intType);

            this.actionWithBindingParameter1.SetReadOnly();
            this.actionWithBindingParameter2.SetReadOnly();
            this.serviceOperation.SetReadOnly();

            this.actionWithBindingParameterWrapper1 = new OperationWrapper(this.actionWithBindingParameter1);
            this.actionWithBindingParameterWrapper2 = new OperationWrapper(this.actionWithBindingParameter2);
            this.serviceOperationWrapper = new OperationWrapper(this.serviceOperation);
        }
        public void DataServiceProviderWrapperShouldFailOnMultipleServiceOperationsWithSameName()
        {
            ResourceType stringType = ResourceType.GetPrimitiveResourceType(typeof(string));
            var duplicateOperation1 = new ServiceOperation("Duplicate", ServiceOperationResultKind.DirectValue, stringType, null, "GET", new[] { new ServiceOperationParameter("p1", stringType) });
            duplicateOperation1.SetReadOnly();
            var duplicateOpration2 = new ServiceOperation("Duplicate", ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(int)), null, "GET", new ServiceOperationParameter[0]);
            duplicateOpration2.SetReadOnly();

            var providerWrapper = CreateProviderWrapper(addMetadata: p =>
                                                                     {
                                                                         p.AddServiceOp(duplicateOperation1);
                                                                         p.AddServiceOp(duplicateOpration2);
                                                                     });

            Action getVisibleOperations = () => providerWrapper.GetVisibleOperations().ToList();
            getVisibleOperations.ShouldThrow<DataServiceException>()
                .WithMessage(ErrorStrings.DataServiceProviderWrapper_MultipleServiceOperationsWithSameName("Duplicate"))
                .And.StatusCode.Should().Be(500);
        }
Example #6
0
        /// <summary>
        /// Invoke the given service operation instance.
        /// </summary>
        /// <param name="serviceOperation">metadata for the service operation to invoke.</param>
        /// <param name="parameters">list of parameters to pass to the service operation.</param>
        /// <returns>returns the result by the service operation instance.</returns>
        public virtual object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters)
        {
            WebUtil.CheckArgumentNull(serviceOperation, "serviceOperation");

            try
            {
                return(((MethodInfo)serviceOperation.CustomState).Invoke(
                           this.dataServiceInstance,
                           BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy,
                           null,
                           parameters,
                           CultureInfo.InvariantCulture));
            }
            catch (TargetInvocationException exception)
            {
                ErrorHandler.HandleTargetInvocationException(exception);
                throw;
            }
        }
Example #7
0
 /// <summary>Creates a new instance of the service operation.</summary>
 /// <param name="name">Name of the service operation.</param>
 /// <param name="resultKind">
 ///   <see cref="T:Microsoft.OData.Service.Providers.ServiceOperationResultKind" /> that is the kind of result expected from this operation.</param>
 /// <param name="resultType">
 ///   <see cref="T:Microsoft.OData.Service.Providers.ResourceType" /> that is the result of the operation.</param>
 /// <param name="resultSet">
 ///   <see cref="T:Microsoft.OData.Service.Providers.ResourceSet" /> that is the result of the operation.</param>
 /// <param name="method">Protocol method to which the service operation responds.</param>
 /// <param name="parameters">Ordered collection of <see cref="T:Microsoft.OData.Service.Providers.ServiceOperationParameter" /> objects that are parameters for the operation.</param>
 public ServiceOperation(string name, ServiceOperationResultKind resultKind, ResourceType resultType, ResourceSet resultSet, string method, IEnumerable <ServiceOperationParameter> parameters)
     : base(
         name,
         resultKind,
         ServiceOperation.GetReturnTypeFromResultType(resultType, resultKind),
         resultSet,
         null /*resultSetExpression*/,
         method,
         parameters,
         OperationParameterBindingKind.Never,
         OperationKind.ServiceOperation)
 {
     Debug.Assert(this.OperationParameters != null, "this.OperationParameters != null");
     if (this.OperationParameters == OperationParameter.EmptyOperationParameterCollection)
     {
         this.parameters = ServiceOperationParameter.EmptyServiceOperationParameterCollection;
     }
     else
     {
         this.parameters = new ReadOnlyCollection <ServiceOperationParameter>(this.OperationParameters.Cast <ServiceOperationParameter>().ToList());
     }
 }
Example #8
0
 private string Serialize(DSP.ServiceOperation serviceOp)
 {
     return(serviceOp.Name);
 }
Example #9
0
 public void InvokeServiceOperation(DSP.ServiceOperation serviceOperation, object[] parameters)
 {
     Add("InvokeServiceOperation", Serialize(serviceOperation), Parent.Serialize(parameters));
 }
 public object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters)
 {
     return null;
 }
        /// <summary>Gets the effective rights on the specified operation.</summary>
        /// <param name="serviceOperation">Operation to get rights for.</param>
        /// <returns>The effective rights as per this configuration.</returns>
        internal ServiceOperationRights GetServiceOperationRights(ServiceOperation serviceOperation)
        {
            Debug.Assert(serviceOperation != null, "operation != null");
            Debug.Assert(this.serviceOperationRights != null, "this.serviceOperationRights != null");

            ServiceOperationRights result;
            if (!this.serviceOperationRights.TryGetValue(serviceOperation.Name, out result))
            {
                result = this.rightsForUnspecifiedServiceOperation;
            }

            return result;
        }
Example #12
0
 /// <summary>
 /// Initializes a new <see cref="ServiceOperation"/> instance.
 /// </summary>
 /// <param name="name">name of the service operation.</param>
 /// <param name="resultKind">Kind of result expected from this operation.</param>
 /// <param name="resultType">Type of element of the method result.</param>
 /// <param name="resultSet">EntitySet of the result expected from this operation.</param>
 /// <param name="method">Protocol (for example HTTP) method the service operation responds to.</param>
 /// <param name="parameters">In-order parameters for this operation.</param>
 public ServiceOperation  AddServiceOperation(string name, ServiceOperationResultKind resultKind, ResourceType resultType, ResourceSet resultSet, string method, IEnumerable<ServiceOperationParameter> parameters)
 {
     ServiceOperation so = new ServiceOperation(name, resultKind, resultType, resultSet, method, parameters);
     this.serviceOperationsByName.Add(name, so);
     return so;
 }
        public object InvokeServiceOperation(ServiceOperation operation, object[] parameters)
        {
            MethodInfo methodInfo = this.dataContextInstance.GetType().GetMethod(operation.Name);
            if (methodInfo == null)
            {
                throw new Exception(String.Format("Method with name '{0}' not found on the context instance", operation.Name));
            }

            return methodInfo.Invoke(this.dataContextInstance, parameters);
        }
        /// <summary>
        /// Invokes the service operation with the given parameters
        /// </summary>
        /// <param name="serviceOperation">The service operation to invoke</param>
        /// <param name="parameters">The parameters to the service operation</param>
        /// <returns>The result of invoking the service operation</returns>
        public virtual object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters)
        {
            ExceptionUtilities.CheckArgumentNotNull(serviceOperation, "serviceOperation");
            ExceptionUtilities.CheckArgumentNotNull(parameters, "parameters");
            ExceptionUtilities.CheckObjectNotNull(this.dataServiceInstance, "The data service instance has not been specified");

            Type serviceType = this.dataServiceInstance.GetType();
            MethodInfo serviceOperationMethod = serviceType.GetMethod(serviceOperation.Name);

            ExceptionUtilities.CheckObjectNotNull(serviceOperationMethod, "Method for service operation {0} not found", serviceOperation.Name);
            return serviceOperationMethod.Invoke(this.dataServiceInstance, BindingFlags.FlattenHierarchy | BindingFlags.Instance, null, parameters, System.Globalization.CultureInfo.InvariantCulture);
        }
Example #15
0
 /// <summary>Given the specified name, tries to find a service operation.</summary>
 /// <param name="name">Name of the service operation to resolve.</param>
 /// <param name="serviceOperation">Returns the resolved service operation, null if no service operation was found for the given name.</param>
 /// <returns>True if we found the service operation for the given name, false otherwise.</returns>
 public virtual bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     WebUtil.CheckStringArgumentNullOrEmpty(name, "name");
     return(this.metadata.ServiceOperations.TryGetValue(name, out serviceOperation));
 }
 /// <summary>Given the specified name, tries to find a service operation.</summary>
 /// <param name="name">Name of the service operation to resolve.</param>
 /// <param name="serviceOperation">Returns the resolved service operation, null if no service operation was found for the given name.</param>
 /// <returns>True if we found the service operation for the given name, false otherwise.</returns>
 public virtual bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     WebUtil.CheckStringArgumentNullOrEmpty(name, "name");
     return this.metadata.ServiceOperations.TryGetValue(name, out serviceOperation);
 }
        /// <summary>
        /// Invoke the given service operation instance.
        /// </summary>
        /// <param name="serviceOperation">metadata for the service operation to invoke.</param>
        /// <param name="parameters">list of parameters to pass to the service operation.</param>
        /// <returns>returns the result by the service operation instance.</returns>
        public virtual object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters)
        {
            WebUtil.CheckArgumentNull(serviceOperation, "serviceOperation");

            try
            {
                return ((MethodInfo)serviceOperation.CustomState).Invoke(
                    this.dataServiceInstance,
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy,
                    null,
                    parameters,
                    CultureInfo.InvariantCulture);
            }
            catch (TargetInvocationException exception)
            {
                ErrorHandler.HandleTargetInvocationException(exception);
                throw;
            }
        }
 public override bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     this.TryResolveServiceOperationCallCount++;
     return base.TryResolveServiceOperation(name, out serviceOperation);
 }
 public void AddServiceOp(ServiceOperation sop)
 {
     this.serviceOps.Add(sop);
 }
        /// <summary>
        /// Ensures that the product caches service operations based on their names.
        /// </summary>
        /// <param name="operation">The operation which may or may-not be cached.</param>
        /// <param name="throwIfAlreadyCached">Whether or not to throw if the operation is already cached.</param>
        /// <returns>The same operation if not cached, or a copy if it was.</returns>
        private ServiceOperation EnforceMetadataCache(ServiceOperation operation, bool throwIfAlreadyCached)
        {
            if (!ProviderImplementationSettings.Current.EnforceMetadataCaching)
            {
                return operation;
            }

            ResourceType resultType = null;
            ResourceSet resultSet = null;
            if (operation.ResourceSet != null)
            {
                // The ResourceSet of a service operation should be cached, but it isnt
                resultSet = this.EnforceMetadataCache(operation.ResourceSet, false, true, false);
                resultType = resultSet.ResourceType;
            }
            else
            {
                // The ResultType of a service operation should be cached, but it isn't
                resultType = this.EnforceMetadataCache(operation.ResultType, false, false);
            }

            if (this.serviceOperationCache.Add(operation.Name))
            {
                return operation;
            }

            ExceptionUtilities.Assert(!throwIfAlreadyCached, "Service operation '{0}' was resolved more than once", operation.Name);

            var copy = new ServiceOperation(operation.Name, operation.ResultKind, resultType, resultSet, operation.Method, Enumerable.Empty<ServiceOperationParameter>());
            copy.SetReadOnly();
            return copy;
        }
        /// <summary>
        /// Trys to find the service operation with the given name 
        /// </summary>
        /// <param name="name">The name of the set</param>
        /// <param name="serviceOperation">The service operation, if found</param>
        /// <returns>Whether or not the service operation was found</returns>
        public virtual bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
        {
            ExceptionUtilities.CheckArgumentNotNull(name, "name");
            serviceOperation = this.metadataHelper.ServiceOperations.SingleOrDefault(o => o.Name == name);
            if (serviceOperation != null)
            {
                // Because this is a 'try-resolve' style API, throw on repeats
                serviceOperation = this.EnforceMetadataCache(serviceOperation, true);
                return true;
            }

            return false;
        }
 public object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters)
 {
     throw new NotImplementedException();
 }
 public bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     Trace("TryResolveServiceOperation - " + name);
     serviceOperation = this.operations.Where<ServiceOperation>(s => s.Name == name).FirstOrDefault<ServiceOperation>();
     return serviceOperation != null;
 }
 public bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     serviceOperation = null;
     return false;
 }
        private static void RunPayloadKindTest(RequestTargetKind requestTargetKind, RequestTargetSource requestTargetSource, ResourceType targetResourceType, bool singleResult, bool isLinkUri, ODataPayloadKind expectedKind)
        {
            var segment = new SegmentInfo
            {
                TargetKind = requestTargetKind,
                TargetSource = requestTargetSource,
                TargetResourceType = targetResourceType,
                SingleResult = singleResult,
                Identifier = "Fake",
            };

            var operation = new ServiceOperation("Fake", ServiceOperationResultKind.Void, null, null, "GET", null);
            operation.SetReadOnly();
            segment.Operation = new OperationWrapper(operation);
            segment.ProjectedProperty = new ResourceProperty("Fake", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int)));

            SegmentInfo[] segmentInfos;
            if (isLinkUri)
            {
                segmentInfos = new[]
                {
                    new SegmentInfo(),
                    new SegmentInfo
                    {
                       TargetKind = RequestTargetKind.Link,  
                    },
                    segment
                };
            }
            else
            {
                segmentInfos = new[]
                {
                    new SegmentInfo
                    {
                        Identifier = "Fake",
                    },
                    new SegmentInfo(),
                    segment
                };
            }

            var requestDescription = new RequestDescription(segmentInfos, new Uri("http://temp.org/"));
            requestDescription.ResponsePayloadKind.Should().Be(expectedKind);
        }
 /// <summary>Given the specified name, tries to find a service operation.</summary>
 /// <param name="name">Name of the service operation to resolve.</param>
 /// <param name="serviceOperation">Returns the resolved service operation, null if no service operation was found for the given name.</param>
 /// <returns>True if we found the service operation for the given name, false otherwise.</returns>
 public virtual bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     return(this.innerProvider.TryResolveServiceOperation(name, out serviceOperation));
 }
Example #27
0
 /// <summary>Returns a service operation specified by its name.</summary>
 /// <param name="name">The name of the service operation to find.</param>
 /// <param name="serviceOperation">The service operation instance found.</param>
 /// <returns>true if the service operation was found or false otherwise.</returns>
 /// <remarks>The implementation of this method should be very fast as it will get called for many requests. It should also be fast
 /// for non-existing service operations to avoid possible DoS attacks on the service.</remarks>
 public virtual bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     return this.serviceOperationsByName.TryGetValue(name, out serviceOperation);
 }
        /// <summary>
        /// Returns a new <see cref="ServiceOperation"/> based on the specified <paramref name="method"/>
        /// instance.
        /// </summary>
        /// <param name="method">Method to expose as a service operation.</param>
        /// <param name="protocolMethod">Protocol (for example HTTP) method the service operation responds to.</param>
        /// <returns>Service operation corresponding to give <paramref name="method"/>.</returns>
        private ServiceOperation GetServiceOperationForMethod(MethodInfo method, string protocolMethod)
        {
            Debug.Assert(method != null, "method != null");
            Debug.Assert(!method.IsAbstract, "!method.IsAbstract - if method is abstract, the type is abstract - already checked");

            bool hasSingleResult = BaseServiceProvider.MethodHasSingleResult(method);
            ServiceOperationResultKind resultKind;
            ResourceType resourceType = null;

            if (method.ReturnType == typeof(void))
            {
                resultKind = ServiceOperationResultKind.Void;
            }
            else
            {
                // Load the metadata of the resource type on the fly.
                // For Edm provider, it might not mean anything, but for reflection service provider, we need to
                // load the metadata of the type if its used only in service operation case
                Type resultType;
                if (WebUtil.IsPrimitiveType(method.ReturnType))
                {
                    resultKind   = ServiceOperationResultKind.DirectValue;
                    resultType   = method.ReturnType;
                    resourceType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(resultType);
                }
                else
                {
                    Type queryableElement = BaseServiceProvider.GetIQueryableElement(method.ReturnType);
                    if (queryableElement != null)
                    {
                        resultKind = hasSingleResult ?
                                     ServiceOperationResultKind.QueryWithSingleResult :
                                     ServiceOperationResultKind.QueryWithMultipleResults;
                        resultType = queryableElement;
                    }
                    else
                    {
                        Type enumerableElement = BaseServiceProvider.GetIEnumerableElement(method.ReturnType);
                        if (enumerableElement != null)
                        {
                            resultKind = ServiceOperationResultKind.Enumeration;
                            resultType = enumerableElement;
                        }
                        else
                        {
                            resultType = method.ReturnType;
                            resultKind = ServiceOperationResultKind.DirectValue;
                        }
                    }

                    Debug.Assert(resultType != null, "resultType != null");
                    resourceType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(resultType);
                    if (resourceType == null)
                    {
                        resourceType = this.ResolveResourceType(resultType);
                    }
                }

                if (resourceType == null)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_UnsupportedReturnType(method, method.ReturnType));
                }

                if (resultKind == ServiceOperationResultKind.Enumeration && hasSingleResult)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_IEnumerableAlwaysMultiple(type, method));
                }
            }

            ParameterInfo[]             parametersInfo = method.GetParameters();
            ServiceOperationParameter[] parameters     = new ServiceOperationParameter[parametersInfo.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                ParameterInfo parameterInfo = parametersInfo[i];
                if (parameterInfo.IsOut || parameterInfo.IsRetval)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_ParameterNotIn(method, parameterInfo));
                }

                ResourceType parameterType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(parameterInfo.ParameterType);
                if (parameterType == null)
                {
                    throw new InvalidOperationException(
                              Strings.BaseServiceProvider_ParameterTypeNotSupported(method, parameterInfo, parameterInfo.ParameterType));
                }

                string parameterName = parameterInfo.Name ?? "p" + i.ToString(CultureInfo.InvariantCulture);
                parameters[i] = new ServiceOperationParameter(parameterName, parameterType);
            }

            ResourceSet resourceSet = null;

            if (resourceType != null && resourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
            {
                resourceSet = this.ResolveResourceSet(resourceType, method);

                if (resourceSet == null)
                {
                    throw new InvalidOperationException(
                              Strings.BaseServiceProvider_ServiceOperationMissingSingleEntitySet(method, resourceType.FullName));
                }
            }

            ServiceOperation operation = new ServiceOperation(method.Name, resultKind, resourceType, resourceSet, protocolMethod, parameters);

            operation.CustomState = method;

            MimeTypeAttribute attribute = BaseServiceProvider.GetMimeTypeAttribute(method);

            if (attribute != null)
            {
                operation.MimeType = attribute.MimeType;
            }

            return(operation);
        }
        public void ServiceOperationConstructorInvalidTests()
        {
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "The 'resultType' parameter must be null when the 'resultKind' parameter value is 'Void', however the 'resultType' parameter cannot be null when the 'resultKind' parameter is of any value other than 'Void'. Please make sure that the 'resultKind' parameter value is set according to the 'resultType' parameter value.",
                "op", ServiceOperationResultKind.Void, ResourceType.GetPrimitiveResourceType(typeof(int)), null, "GET", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "The 'resultType' parameter must be null when the 'resultKind' parameter value is 'Void', however the 'resultType' parameter cannot be null when the 'resultKind' parameter is of any value other than 'Void'. Please make sure that the 'resultKind' parameter value is set according to the 'resultType' parameter value.",
                "op", ServiceOperationResultKind.DirectValue, null, null, "GET", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "A parameter with the name 'p1' already exists. Please make sure that every parameter has a unique name.",
                "op", ServiceOperationResultKind.Void, null, null, "GET",
                new ServiceOperationParameter[] { 
                        new ServiceOperationParameter("p1", ResourceType.GetPrimitiveResourceType(typeof(int))),
                        new ServiceOperationParameter("p1", ResourceType.GetPrimitiveResourceType(typeof(string))) });
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "The resource type 'Collection(foo.Customer)' is not a type that can be returned by a service operation. A service operation can only return values of an entity type, a complex type or any primitive type, other than the stream type.",
                "op", ServiceOperationResultKind.QueryWithMultipleResults, ResourceType.GetEntityCollectionResourceType(new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "foo", "Customer", false)), null, "GET", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "The resource type 'Edm.Stream' is not a type that can be returned by a service operation. A service operation can only return values of an entity type, a complex type or any primitive type, other than the stream type.",
                "op", ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(System.IO.Stream)), null, "GET", null);

            ResourceProperty p = new ResourceProperty("ID", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, ResourceType.GetPrimitiveResourceType(typeof(int)));
            ResourceType customerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Foo", "NoBaseType", false);
            customerType.AddProperty(p);
            customerType.SetReadOnly();
            ResourceSet customerSet = new ResourceSet("Customers", customerType);
            ResourceType orderType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Foo", "NoBaseType", false);
            orderType.AddProperty(p);
            orderType.SetReadOnly();

            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "'resultSet' must be null when 'resultType' is null or not an EntityType.",
                "op", ServiceOperationResultKind.Void, null, customerSet, "GET", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "'resultSet' must be null when 'resultType' is null or not an EntityType.",
                "op", ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(int)), customerSet, "GET", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "When 'resultType' is an entity type, 'resultSet' cannot be null and the resource type of 'resultSet' must be assignable from 'resultType'.",
                "op", ServiceOperationResultKind.QueryWithMultipleResults, customerType, null, "GET", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "When 'resultType' is an entity type, 'resultSet' cannot be null and the resource type of 'resultSet' must be assignable from 'resultType'.",
                "op", ServiceOperationResultKind.QueryWithMultipleResults, orderType, customerSet, "GET", null);

            ExceptionUtils.ThrowsException<InvalidOperationException>(
                () =>
                {
                    ServiceOperation op = new ServiceOperation("op", ServiceOperationResultKind.Void, null, null, "GET", null);
                    op.MimeType = null;
                },
                "MimeType cannot be set to null");

            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "Value cannot be null or empty.\r\nParameter name: method",
                "op", ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(int)), null, null, null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "Value cannot be null or empty.\r\nParameter name: method",
                "op", ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(int)), null, string.Empty, null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "Value cannot be null or empty.\r\nParameter name: name",
                null, ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(int)), null, "GET", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "Value cannot be null or empty.\r\nParameter name: name",
                string.Empty, ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(int)), null, "GET", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "An invalid HTTP method 'PUT' was specified for the service operation 'op'. Only the HTTP 'POST' and 'GET' methods are supported for service operations.",
                "op", ServiceOperationResultKind.Void, null, null, "PUT", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "An invalid HTTP method 'PATCH' was specified for the service operation 'op'. Only the HTTP 'POST' and 'GET' methods are supported for service operations.",
                "op", ServiceOperationResultKind.Void, null, null, "PATCH", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "An invalid HTTP method 'DELETE' was specified for the service operation 'op'. Only the HTTP 'POST' and 'GET' methods are supported for service operations.",
                "op", ServiceOperationResultKind.Void, null, null, "DELETE", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "An invalid HTTP method 'HEAD' was specified for the service operation 'op'. Only the HTTP 'POST' and 'GET' methods are supported for service operations.",
                "op", ServiceOperationResultKind.Void, null, null, "HEAD", null);
            ExceptionUtils.CheckInvalidConstructorParameters(
                typeof(ServiceOperation),
                "An invalid HTTP method 'Some Method' was specified for the service operation 'op'. Only the HTTP 'POST' and 'GET' methods are supported for service operations.",
                "op", ServiceOperationResultKind.Void, null, null, "Some Method", null);
        }
 public bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     serviceOperation = this.serviceOps.FirstOrDefault(r => r.Name == name);
     return serviceOperation != null;
 }
 /// <summary>Given the specified name, tries to find a service operation.</summary>
 /// <param name="name">Name of the service operation to resolve.</param>
 /// <param name="serviceOperation">Returns the resolved service operation, null if no service operation was found for the given name.</param>
 /// <returns>True if we found the service operation for the given name, false otherwise.</returns>
 public virtual bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation)
 {
     return this.innerProvider.TryResolveServiceOperation(name, out serviceOperation);
 }
 /// <summary>
 /// Invoke the given service operation and returns the results.
 /// </summary>
 /// <param name="serviceOperation">service operation to invoke.</param>
 /// <param name="parameters">value of parameters to pass to the service operation.</param>
 /// <returns>returns the result of the service operation. If the service operation returns void, then this should return null.</returns>
 public virtual object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters)
 {
     return this.innerProvider.InvokeServiceOperation(serviceOperation, parameters);
 }
 /// <summary>
 /// Invoke the given service operation and returns the results.
 /// </summary>
 /// <param name="serviceOperation">service operation to invoke.</param>
 /// <param name="parameters">value of parameters to pass to the service operation.</param>
 /// <returns>returns the result of the service operation. If the service operation returns void, then this should return null.</returns>
 public virtual object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters)
 {
     return(this.innerProvider.InvokeServiceOperation(serviceOperation, parameters));
 }
        /// <summary>
        /// Returns a new <see cref="ServiceOperation"/> based on the specified <paramref name="method"/>
        /// instance.
        /// </summary>
        /// <param name="method">Method to expose as a service operation.</param>
        /// <param name="protocolMethod">Protocol (for example HTTP) method the service operation responds to.</param>
        /// <returns>Service operation corresponding to give <paramref name="method"/>.</returns>
        private ServiceOperation GetServiceOperationForMethod(MethodInfo method, string protocolMethod)
        {
            Debug.Assert(method != null, "method != null");
            Debug.Assert(!method.IsAbstract, "!method.IsAbstract - if method is abstract, the type is abstract - already checked");

            bool hasSingleResult = BaseServiceProvider.MethodHasSingleResult(method);
            ServiceOperationResultKind resultKind;
            ResourceType resourceType = null;
            if (method.ReturnType == typeof(void))
            {
                resultKind = ServiceOperationResultKind.Void;
            }
            else
            {
                // Load the metadata of the resource type on the fly.
                // For Edm provider, it might not mean anything, but for reflection service provider, we need to
                // load the metadata of the type if its used only in service operation case
                Type resultType;
                if (WebUtil.IsPrimitiveType(method.ReturnType))
                {
                    resultKind = ServiceOperationResultKind.DirectValue;
                    resultType = method.ReturnType;
                    resourceType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(resultType);
                }
                else
                {
                    Type queryableElement = BaseServiceProvider.GetIQueryableElement(method.ReturnType);
                    if (queryableElement != null)
                    {
                        resultKind = hasSingleResult ?
                            ServiceOperationResultKind.QueryWithSingleResult :
                            ServiceOperationResultKind.QueryWithMultipleResults;
                        resultType = queryableElement;
                    }
                    else
                    {
                        Type enumerableElement = BaseServiceProvider.GetIEnumerableElement(method.ReturnType);
                        if (enumerableElement != null)
                        {
                            resultKind = ServiceOperationResultKind.Enumeration;
                            resultType = enumerableElement;
                        }
                        else
                        {
                            resultType = method.ReturnType;
                            resultKind = ServiceOperationResultKind.DirectValue;
                        }
                    }

                    Debug.Assert(resultType != null, "resultType != null");
                    resourceType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(resultType);
                    if (resourceType == null)
                    {
                        resourceType = this.ResolveResourceType(resultType);
                    }
                }

                if (resourceType == null)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_UnsupportedReturnType(method, method.ReturnType));
                }

                if (resultKind == ServiceOperationResultKind.Enumeration && hasSingleResult)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_IEnumerableAlwaysMultiple(type, method));
                }
            }

            ParameterInfo[] parametersInfo = method.GetParameters();
            ServiceOperationParameter[] parameters = new ServiceOperationParameter[parametersInfo.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                ParameterInfo parameterInfo = parametersInfo[i];
                if (parameterInfo.IsOut || parameterInfo.IsRetval)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_ParameterNotIn(method, parameterInfo));
                }

                ResourceType parameterType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(parameterInfo.ParameterType);
                if (parameterType == null)
                {
                    throw new InvalidOperationException(
                        Strings.BaseServiceProvider_ParameterTypeNotSupported(method, parameterInfo, parameterInfo.ParameterType));
                }

                string parameterName = parameterInfo.Name ?? "p" + i.ToString(CultureInfo.InvariantCulture);
                parameters[i] = new ServiceOperationParameter(parameterName, parameterType);
            }

            ResourceSet resourceSet = null;
            if (resourceType != null && resourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
            {
                resourceSet = this.ResolveResourceSet(resourceType, method);

                if (resourceSet == null)
                {
                    throw new InvalidOperationException(
                        Strings.BaseServiceProvider_ServiceOperationMissingSingleEntitySet(method, resourceType.FullName));
                }
            }

            ServiceOperation operation = new ServiceOperation(method.Name, resultKind, resourceType, resourceSet, protocolMethod, parameters);

            operation.CustomState = method;

            MimeTypeAttribute attribute = BaseServiceProvider.GetMimeTypeAttribute(method);
            if (attribute != null)
            {
                operation.MimeType = attribute.MimeType;
            }

            return operation;
        }