/// <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)); }
public void TestServiceOperationsWithSpatialParameters() { Action<string, Type, DSPMetadata> AddIdentityServiceOp = (name, type, dspMetadata) => { var primitiveType = Microsoft.OData.Service.Providers.ResourceType.GetPrimitiveResourceType(type); var parameter = new ServiceOperationParameter("param1", primitiveType); dspMetadata.AddServiceOperation(name, ServiceOperationResultKind.DirectValue, primitiveType, null, "GET", new ServiceOperationParameter[] { parameter }); }; DSPUnitTestServiceDefinition roadTripServiceDefinition = GetRoadTripServiceDefinition(typeof(GeographyPoint), TestPoint.DefaultValues, false, false, (m) => { AddIdentityServiceOp("GetGeographyPoint", typeof(GeographyPoint), m); AddIdentityServiceOp("GetGeometryPoint", typeof(GeometryPoint), m); AddIdentityServiceOp("GetDouble", typeof(double), m); }); Func<object[], object> sopCallBack = (args) => { return args[0]; }; roadTripServiceDefinition.CreateDataSource = (metadata) => { return new DSPContext() { ServiceOperations = new Dictionary <string, Func<object[], object>>() { {"GetGeographyPoint", sopCallBack}, {"GetGeometryPoint", sopCallBack}, {"GetDouble", sopCallBack}, } }; }; using (TestWebRequest request = roadTripServiceDefinition.CreateForInProcess()) { request.StartService(); // GET request.Accept = "application/xml"; request.RequestContentType = null; request.HttpMethod = "GET"; request.RequestUriString = "/GetDouble?param1=1.2"; request.SendRequest(); var response = request.GetResponseStreamAsText(); StringAssert.Contains(response, "1.2", "didn't get the identity back"); const string wellKnownText = "SRID=4326;POINT (177.508 51.9917)"; // GET request.Accept = "application/xml"; request.RequestContentType = null; request.HttpMethod = "GET"; request.RequestUriString = string.Format("/GetGeographyPoint?param1=geography'{0}'", wellKnownText); request.SendRequest(); response = request.GetResponseStreamAsText(); var geographyPoint = WellKnownTextSqlFormatter.Create().Read<Geography>(new StringReader(wellKnownText)); string geographyPointReturn = GmlFormatter.Create().Write(geographyPoint); // The gml namespace is already declared on the top-level element geographyPointReturn = geographyPointReturn.Replace(" xmlns:gml=\"http://www.opengis.net/gml\"", string.Empty); StringAssert.Contains(response, geographyPointReturn, "didn't get the identity back"); // GET request.Accept = "application/xml"; request.RequestContentType = null; request.HttpMethod = "GET"; request.RequestUriString = string.Format("/GetGeometryPoint?param1=geometry'{0}'", wellKnownText); request.SendRequest(); response = request.GetResponseStreamAsText(); var geometryPoint = WellKnownTextSqlFormatter.Create().Read<Geometry>(new StringReader(wellKnownText)); string geometryPointReturn = GmlFormatter.Create().Write(geometryPoint); // The gml namespace is already declared on the top-level element geometryPointReturn = geometryPointReturn.Replace(" xmlns:gml=\"http://www.opengis.net/gml\"", string.Empty); StringAssert.Contains(response, geometryPointReturn, "didn't get the identity back"); } }
/// <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); }
/// <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; }