/// <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 override object GetValue(object value, string property) { APICallLog.Current.Push(); try { // for sub-values of a complex type inside an open property, GetValue will still be used // so we should check before calling GetOpenPropertyValue (which will throw on non-open types) DSP.ResourceType type = QueryProvider.GetResourceType(value); if (type == null || type.IsOpenType) { return(QueryProvider.GetOpenPropertyValue(value, property)); } if (type.ResourceTypeKind != ResourceTypeKind.ComplexType) { throw new DataServiceException(500, "OpenTypeMethods.GetValue used on non-open, non-complex type"); } DSP.ResourceProperty rp = type.Properties.SingleOrDefault(p => p.Name == property); if (rp == null) { throw new DataServiceException(500, "OpenTypeMethods.GetValue used on non-open type with non-existent property"); } return(QueryProvider.GetPropertyValue(value, rp)); } finally { APICallLog.Current.Pop(); } }
public void AddResourceProperty(string propertyName, string addToResourceType, string resourcePropertyKind, string propertyType, string containerName, bool isClrProperty) { DSP.ResourceProperty newProperty = null; DSP.ResourceType resourceType = GetResourceType(addToResourceType); DSP.ResourceSet assocResourceSet = GetResourceSet(containerName); if (assocResourceSet != null) { DSP.ResourceType assocResourceType = GetResourceType(propertyType); newProperty = new DSP.ResourceProperty( propertyName, ConvertResourcePropertyKind(resourcePropertyKind), assocResourceType); } else { DSP.ResourceType assocResourceType = GetResourceType(propertyType); if (assocResourceType == null) { Type t = Type.GetType(propertyType); assocResourceType = DSP.ResourceType.GetPrimitiveResourceType(t); } newProperty = new DSP.ResourceProperty( propertyName, ConvertResourcePropertyKind(resourcePropertyKind), assocResourceType); } newProperty.CanReflectOnInstanceTypeProperty = isClrProperty; resourceType.AddProperty(newProperty); }
} // GetOpenPropertyValues public object GetPropertyValue(object targetResource, DSP.ResourceProperty resourceProperty) { if (resourceProperty.Kind == DSP.ResourcePropertyKind.ResourceSetReference) { // there are 4 possibilites // 1) both the property and things in the list are strongly typed // 2) the property is strong, but the list is not // 3) the property is weak, but the things inside the list are strong // 4) neither is defined in clr terms // GetValue will automatically take care of #1 and #2, but we need to handle #3 here RowEntityType target = targetResource as RowEntityType; IEnumerable list = (IEnumerable)this.GetValue(targetResource, resourceProperty.Name); Type genericList = typeof(IEnumerable <>).MakeGenericType(resourceProperty.ResourceType.InstanceType); if (genericList.IsAssignableFrom(list.GetType())) { return(list); } MethodInfo castMethod = typeof(Enumerable).GetMethod("Cast", BindingFlags.Static | BindingFlags.Public); castMethod = castMethod.MakeGenericMethod(resourceProperty.ResourceType.InstanceType); return(castMethod.Invoke(null, new object[] { list })); } else { return(this.GetValue(targetResource, resourceProperty.Name)); } } // GetPropertyValue
public void GetStreamETag(object entity, DSP.ResourceProperty streamProperty, DataServiceOperationContext operationContext) { Parent.Add(new APICallLogEntry("IDataServiceStreamProvider2.GetStreamETag", "entity", this.Parent.Serialize(entity), "streamProperty", this.Serialize(streamProperty), "AbsoluteRequestUri", operationContext.AbsoluteRequestUri.ToString(), "AbsoluteServiceUri", operationContext.AbsoluteServiceUri.ToString(), "IsBatchRequest", operationContext.IsBatchRequest.ToString(), "RequestMethod", operationContext.RequestMethod.ToUpperInvariant())); }
/// <summary> /// Initializes a new instance of the <see cref="MetadataProviderEdmStructuralProperty"/> class. /// </summary> /// <param name="declaringType">The type that declares this property.</param> /// <param name="resourceProperty">The resource-property this edm property is based on.</param> /// <param name="type">The type of the property.</param> /// <param name="defaultValue">The default value of this property.</param> /// <param name="concurrencyMode">The concurrency mode of this property.</param> public MetadataProviderEdmStructuralProperty( IEdmStructuredType declaringType, ResourceProperty resourceProperty, IEdmTypeReference type, string defaultValue, EdmConcurrencyMode concurrencyMode) : base(declaringType, resourceProperty.Name, type, defaultValue, concurrencyMode) { this.ResourceProperty = resourceProperty; }
public void Init() { this.keyProperty1 = new ResourceProperty("Key1", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string))); this.keyProperty2 = new ResourceProperty("Key2", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int))); this.defaultSerializer = KeySerializer.Create(UrlConvention.CreateWithExplicitValue(false)); this.segmentSerializer = KeySerializer.Create(UrlConvention.CreateWithExplicitValue(true)); this.singleKeyProperty = new[] { this.keyProperty1 }; this.compositeKey = new[] { this.keyProperty1, this.keyProperty2 }; }
public EmptyOpenTypesContext() { this.resourceType = new ResourceType(typeof(StubTypeWithId), ResourceTypeKind.EntityType, null, "OpenTypes", "Entity", false); this.resourceType.CanReflectOnInstanceType = true; this.resourceType.IsOpenType = true; var idProperty = new ResourceProperty("Id", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, ResourceType.GetPrimitiveResourceType(typeof(int))); idProperty.CanReflectOnInstanceTypeProperty = true; this.resourceType.AddProperty(idProperty); this.resourceSet = new ResourceSet("Entities", this.resourceType); this.resourceSet.SetReadOnly(); }
/// <summary> /// Constructor. /// </summary> /// <param name="declaringType">The declaring type of the navigation property.</param> /// <param name="property">The resource property to create the navigation property from.</param> /// <param name="type">The type of the navigation property.</param> /// <remarks>This constructor assumes that the entity set for this service operation has already be created.</remarks> internal MetadataProviderEdmNavigationProperty(EdmEntityType declaringType, ResourceProperty property, IEdmTypeReference type) { Debug.Assert(declaringType != null, "declaringType != null"); Debug.Assert(property != null, "property != null"); Debug.Assert(type != null, "type != null"); this.declaringType = declaringType; this.name = property.Name; this.type = type; this.ResourceProperty = property; }
public Stream GetReadStream(object entity, provider.ResourceProperty streamProperty, string etag, bool?checkETagForEquality, DataServiceOperationContext operationContext) { Stream stream = this.GetReadStream(entity, streamProperty, null, etag, checkETagForEquality, operationContext); if (stream == null) { stream = CreateMemoryStream(); } return(stream); }
/// <summary> /// Creates a new instance of EndInfo. /// </summary> /// <param name="name">name of the end.</param> /// <param name="resourceType">resource type that the end refers to.</param> /// <param name="resourceProperty">property of the end.</param> /// <param name="multiplicity">Multiplicity of the association.</param> /// <param name="deleteBehavior">Delete behavior.</param> internal ResourceAssociationTypeEnd(string name, ResourceType resourceType, ResourceProperty resourceProperty, string multiplicity, EdmOnDeleteAction deleteBehavior) { Debug.Assert(!String.IsNullOrEmpty(name), "!String.IsNullOrEmpty(name)"); Debug.Assert(resourceType != null, "type != null"); Debug.Assert(multiplicity == XmlConstants.Many || multiplicity == XmlConstants.One || multiplicity == XmlConstants.ZeroOrOne, "Invalid multiplicity value"); Debug.Assert(deleteBehavior == EdmOnDeleteAction.None || deleteBehavior == EdmOnDeleteAction.Cascade, "Invalid deleteBehavior value"); this.name = name; this.resourceType = resourceType; this.resourceProperty = resourceProperty; this.multiplicity = multiplicity; this.deleteAction = deleteBehavior; }
public void GetWriteStream(object entity, DSP.ResourceProperty streamProperty, string etag, bool?checkETagForEquality, DataServiceOperationContext operationContext) { Parent.Add(new APICallLogEntry("IDataServiceStreamProvider2.GetWriteStream", "entity", this.Parent.Serialize(entity), "streamProperty", this.Serialize(streamProperty), "etag", (etag == null ? "null" : etag), "checkETagForEquality", (checkETagForEquality.HasValue ? checkETagForEquality.Value.ToString() : "null"), "AbsoluteRequestUri", operationContext.AbsoluteRequestUri.ToString(), "AbsoluteServiceUri", operationContext.AbsoluteServiceUri.ToString(), "IsBatchRequest", operationContext.IsBatchRequest.ToString(), "RequestMethod", operationContext.RequestMethod.ToUpperInvariant())); }
public override object GetValue(object value, DSP.ResourceProperty property) { APICallLog.Current.Push(); try { return(QueryProvider.GetPropertyValue(value, property)); } finally { APICallLog.Current.Pop(); } }
public override IEnumerable <T> GetSequenceValue <T>(object value, DSP.ResourceProperty property) { APICallLog.Current.Push(); try { return(QueryProvider.GetPropertyValue(value, property) as IEnumerable <T>); } finally { APICallLog.Current.Pop(); } }
public void VerifyVersionOfEntityWithGeographyPropertyIsV3() { ResourceType rt = new ResourceType(typeof(IDictionary<string, string>), ResourceTypeKind.EntityType, null, "TestNamespace", "TestEntity", false); var keyProperty = new ResourceProperty("ID", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, ResourceType.GetPrimitiveResourceType(typeof(int))) {CanReflectOnInstanceTypeProperty = false }; var geographyProperty = new ResourceProperty("GeographyProperty", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(Geography))) { CanReflectOnInstanceTypeProperty = false }; rt.AddProperty(keyProperty); rt.AddProperty(geographyProperty); rt.SetReadOnly(); Assert.AreEqual(v4, rt.MetadataVersion, "MetadataVersion must be 4.0"); Assert.AreEqual(MetadataEdmSchemaVersion.Version4Dot0, rt.SchemaVersion, "Schema version must be 4.0"); }
/// <summary> /// For the given association from source to target, perform the appropriate reversed action /// </summary> /// <param name="source">the source of the association to reverse</param> /// <param name="target">the target of the association to reverse</param> /// <param name="forwardPropertyName">the name of the property from source to target</param> /// <param name="remove">whether or not to remove the reversed association</param> private void SetReverseNavigation(RowEntityType source, RowEntityType target, string forwardPropertyName, bool remove) { DSP.ResourceType targetType; DSP.ResourceType sourceType = this.GetResourceType(source); if (target == null) { targetType = sourceType.Properties.Single(p => p.Name == forwardPropertyName).ResourceType; } else { targetType = this.GetResourceType(target); } DSP.ResourceProperty forwardProperty = sourceType.Properties.SingleOrDefault(p => p.Name == forwardPropertyName); if (forwardProperty != null && forwardProperty.CustomState != null) { // because sourceType could match targetType, we need to make sure we filter out the target property DSP.ResourceProperty reverseProperty = targetType.Properties .SingleOrDefault(p => p != forwardProperty && p.CustomState != null && (string)p.CustomState == (string)forwardProperty.CustomState); if (reverseProperty != null) { bool reference = (reverseProperty.Kind & DSP.ResourcePropertyKind.ResourceReference) != 0; if (remove) { if (reference) { this.SetReference_Internal(target, reverseProperty.Name, null, false); } else { this.RemoveReferenceFromCollection_Internal(target, reverseProperty.Name, source, false); } } else { if (reference) { this.SetReference_Internal(target, reverseProperty.Name, source, false); } else { this.AddReferenceToCollection_Internal(target, reverseProperty.Name, source, false); } } } } }
/// <summary> /// Validates the entity and stream parameters. /// </summary> /// <param name="entity">entity instance.</param> /// <param name="streamProperty">stream info</param> protected override void ValidateEntity(object entity, ResourceProperty streamProperty) { this.ValidateEntity(entity); DSPResource resource = (DSPResource)entity; ResourceType type = resource.ResourceType; if (streamProperty == null && !type.IsMediaLinkEntry) { throw new InvalidOperationException("The specified entity is not an MLE."); } if (streamProperty != null && type.Properties.SingleOrDefault(s => s.Kind == ResourcePropertyKind.Stream && s.Name == streamProperty.Name) == null) { throw new InvalidOperationException("The specified streamName does not exist on the entity."); } }
public void InvalidCasesTest() { ResourceProperty id = new ResourceProperty("ID", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false }; ResourceType customerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Foo", "CustomerType", false); customerType.AddProperty(id); ResourceType orderType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Foo", "OrderType", false); orderType.AddProperty(id); ResourceProperty customerOrders = new ResourceProperty("Orders", ResourcePropertyKind.ResourceSetReference, orderType); ResourceProperty orderCustomer = new ResourceProperty("Customer", ResourcePropertyKind.ResourceReference, customerType); customerType.AddProperty(customerOrders); orderType.AddProperty(orderCustomer); customerOrders.CanReflectOnInstanceTypeProperty = false; orderCustomer.CanReflectOnInstanceTypeProperty = false; customerType.SetReadOnly(); orderType.SetReadOnly(); ResourceSet customerSet = new ResourceSet("Customers", customerType); ResourceSet orderSet = new ResourceSet("Orders", orderType); ResourceAssociationSetEnd end1 = new ResourceAssociationSetEnd(customerSet, customerType, null); ResourceAssociationSetEnd end2 = new ResourceAssociationSetEnd(orderSet, orderType, null); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSet), "Value cannot be null or empty.\r\nParameter name: name", null, end1, end2); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSet), "Value cannot be null or empty.\r\nParameter name: name", string.Empty, end1, end2); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSet), "Value cannot be null.\r\nParameter name: end1", "Customer_Order", null, end2); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSet), "Value cannot be null.\r\nParameter name: end2", "Customer_Order", end1, null); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSet), "The ResourceProperty of the ResourceAssociationEnds cannot both be null.", "Customer_Order", end1, end2); }
public void InvalidCasesTest() { ResourceProperty id = new ResourceProperty("ID", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false }; ResourceType customerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Foo", "CustomerType", false); customerType.AddProperty(id); ResourceType orderType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Foo", "OrderType", false); orderType.AddProperty(id); ResourceProperty customerOrders = new ResourceProperty("Orders", ResourcePropertyKind.ResourceSetReference, orderType); ResourceProperty orderCustomer = new ResourceProperty("Customer", ResourcePropertyKind.ResourceReference, customerType); customerType.AddProperty(customerOrders); orderType.AddProperty(orderCustomer); customerOrders.CanReflectOnInstanceTypeProperty = false; orderCustomer.CanReflectOnInstanceTypeProperty = false; customerType.SetReadOnly(); orderType.SetReadOnly(); ResourceSet customerSet = new ResourceSet("Customers", customerType); ResourceSet orderSet = new ResourceSet("Orders", orderType); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSetEnd), "Value cannot be null.\r\nParameter name: resourceSet", null, customerType, customerOrders); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSetEnd), "Value cannot be null.\r\nParameter name: resourceType", customerSet, null, customerOrders); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSetEnd), "The resourceProperty parameter must be a navigation property on the resource type specified by the resourceType parameter.", customerSet, customerType, id); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSetEnd), "The resourceProperty parameter must be a navigation property on the resource type specified by the resourceType parameter.", customerSet, customerType, orderCustomer); ExceptionUtils.CheckInvalidConstructorParameters( typeof(ResourceAssociationSetEnd), "The resourceType parameter must be a type that is assignable to the resource set specified by the resourceSet parameter.", customerSet, orderType, orderCustomer); }
/// <summary> /// Creates a new media resource and adds it to the storage /// </summary> /// <param name="entity">entity instance.</param> /// <param name="streamProperty">stream info.</param> /// <returns>Returns the newly created media resource instance.</returns> public virtual DSPMediaResource CreateMediaResource(object entity, ResourceProperty streamProperty) { if (this.inMemoryStreamStorage == null) { this.inMemoryStreamStorage = this.keyComparer == null ? new Dictionary<object, Dictionary<string, DSPMediaResource>>() : new Dictionary<object, Dictionary<string, DSPMediaResource>>(this.keyComparer); } Dictionary<string, DSPMediaResource> streams; if (!this.inMemoryStreamStorage.TryGetValue(entity, out streams)) { streams = new Dictionary<string, DSPMediaResource>(); this.inMemoryStreamStorage[entity] = streams; } string streamName = streamProperty == null ? string.Empty : streamProperty.Name; streams[streamName] = new DSPMediaResource(); return streams[streamName]; }
/// <summary> /// Creates a new instance of EndInfo. /// </summary> /// <param name="name">name of the end.</param> /// <param name="resourceType">resource type that the end refers to.</param> /// <param name="resourceProperty">property of the end.</param> /// <param name="fromProperty">Property on the related end that points to this end. The multiplicity of this end is determined from the fromProperty.</param> internal ResourceAssociationTypeEnd(string name, ResourceType resourceType, ResourceProperty resourceProperty, ResourceProperty fromProperty) { Debug.Assert(!String.IsNullOrEmpty(name), "!String.IsNullOrEmpty(name)"); Debug.Assert(resourceType != null, "type != null"); this.name = name; this.resourceType = resourceType; this.resourceProperty = resourceProperty; if (fromProperty != null && fromProperty.Kind == ResourcePropertyKind.ResourceReference) { this.multiplicity = XmlConstants.ZeroOrOne; } else { this.multiplicity = XmlConstants.Many; } }
public Uri GetReadStreamUri(object entity, provider.ResourceProperty streamProperty, string name, DataServiceOperationContext operationContext) { StreamWrapper wrapper; if (streamProperty == null) { wrapper = GetStream(entity, name); } else { wrapper = GetStream(entity, streamProperty.Name); } if (wrapper == null) { return(null); } return(wrapper.ReadUri); }
public string GetStreamETag(object entity, provider.ResourceProperty stremProperty, string name, DataServiceOperationContext operationContext) { StreamWrapper wrapper; if (stremProperty == null) { wrapper = GetStream(entity, name); } else { wrapper = GetStream(entity, stremProperty.Name); } if (wrapper == null) { return(null); } GenerateStreamETag(wrapper); return(wrapper.ETag); }
/// <summary>Creates a new instance of the <see cref="T:Microsoft.OData.Service.Providers.ResourceAssociationSetEnd" /> class.</summary> /// <param name="resourceSet">The resource set to which the <see cref="T:Microsoft.OData.Service.Providers.ResourceAssociationSetEnd" /> end belongs.</param> /// <param name="resourceType">The resource type to which the <see cref="T:Microsoft.OData.Service.Providers.ResourceAssociationSetEnd" /> end belongs.</param> /// <param name="resourceProperty">The resource property that returns the <see cref="T:Microsoft.OData.Service.Providers.ResourceAssociationSetEnd" /> end.</param> public ResourceAssociationSetEnd(ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty) { WebUtil.CheckArgumentNull(resourceSet, "resourceSet"); WebUtil.CheckArgumentNull(resourceType, "resourceType"); if (resourceProperty != null && (resourceType.TryResolvePropertyName(resourceProperty.Name) == null || resourceProperty.TypeKind != ResourceTypeKind.EntityType)) { throw new ArgumentException(Strings.ResourceAssociationSetEnd_ResourcePropertyMustBeNavigationPropertyOnResourceType); } if (!resourceSet.ResourceType.IsAssignableFrom(resourceType) && !resourceType.IsAssignableFrom(resourceSet.ResourceType)) { throw new ArgumentException(Strings.ResourceAssociationSetEnd_ResourceTypeMustBeAssignableToResourceSet); } this.resourceSet = resourceSet; this.resourceType = resourceType; // Note that for the TargetEnd, resourceProperty can be null. this.resourceProperty = resourceProperty; }
public void ResourceTypeMustBeDeclaringType_2() { ResourceType baseCustomerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Test", "Employee", true /*isAbstract*/); ResourceType customerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, baseCustomerType, "Test", "Customer", false /*isAbstract*/); ResourceSet customerSet = new ResourceSet("CustomerSet", customerType); ResourceType orderType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Test", "Employee", false /*isAbstract*/); ResourceProperty orderProperty = new ResourceProperty("Orders", ResourcePropertyKind.ResourceSetReference, orderType); baseCustomerType.AddProperty(orderProperty); try { new ResourceAssociationSetEnd(customerSet, customerType, orderProperty); Assert.Fail("Creating resource association set end should never have succeeded"); } catch (ArgumentException e) { Assert.AreEqual( DataServicesResourceUtil.GetString("ResourceAssociationSetEnd_ResourceTypeMustBeTheDeclaringType", customerType.FullName, orderProperty.Name), e.Message); } }
public Stream GetWriteStream(object entity, provider.ResourceProperty streamProperty, string name, string etag, bool?checkETagForEquality, DataServiceOperationContext operationContext) { // Check concurrency if (etag != null) { string etagValue = this.GetStreamETag(entity, streamProperty, operationContext); if (checkETagForEquality.HasValue && checkETagForEquality == false && etag == etagValue) { return(null); } if (checkETagForEquality.HasValue && checkETagForEquality == true && etag != etagValue) { throw new DataServiceException(412, PreconditionFailedMessage); } } StreamWrapper wrapper; if (streamProperty == null) { wrapper = GetOrCreateStream(entity, name, operationContext); } else { wrapper = GetOrCreateStream(entity, streamProperty.Name, operationContext); } GenerateStreamETag(wrapper); if (wrapper.Stream != null && wrapper.Stream.CanSeek) { wrapper.Stream.Position = 0; } return(wrapper.Stream); }
/// <summary>Creates new instance of <see cref="ProjectionNode"/> which represents a simple projected property.</summary> /// <param name="propertyName">The name of the property to project.</param> /// <param name="property">The <see cref="ResourceProperty"/> for the property to project. If an open property /// is to be projected, specify null.</param> /// <param name="targetResourceType">The resource type for which the <see cref="property"/>needs to be projected.</param> internal ProjectionNode(string propertyName, ResourceProperty property, ResourceType targetResourceType) { Debug.Assert(propertyName != null, "propertyName != null"); Debug.Assert(property == null || property.Name == propertyName, "If the property is specified its name must match."); #if DEBUG // For rootProjectionNode, there is no targetResourceType. Hence checking for propertyName to be String.Empty to excluse RootProjectionNode from the assert. if (!String.IsNullOrEmpty(propertyName)) { Debug.Assert(targetResourceType != null, "targetResourceType != null"); if (property != null) { Debug.Assert(object.ReferenceEquals(targetResourceType.TryResolvePropertyName(propertyName), property), "object.ReferenceEquals(targetResourceType.TryResolvePropertyName(propertyName), property)"); } else { Debug.Assert(targetResourceType.IsOpenType, "targetResourceType.IsOpenType"); } } #endif this.propertyName = propertyName; this.property = property; this.targetResourceType = targetResourceType; }
/// <summary>Creates a server resource from the specified client resource</summary> /// <param name="clientResource">The client resource instance.</param> /// <param name="createCollection">Optional func to create a new collection instance on the server. /// The first parameter is the collection resource type, the second is enumeration of server items to be added to the collection.</param> /// <param name="clientInstanceToResourceType">Func to resolve client resource to a server resource type.</param> /// <returns>The server resource instance.</returns> public static DSPResource CreateServerResourceFromClientResource( object clientResource, Func <providers.CollectionResourceType, IEnumerable <object>, object> createCollection, Func <object, providers.ResourceType> clientInstanceToResourceType) { providers.ResourceType resourceType = clientInstanceToResourceType(clientResource); DSPResource resource = new DSPResource(resourceType); IEnumerable <PropertyInfo> properties = clientResource.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var property in properties) { var sameProperties = properties.Where(p => p.Name == property.Name).ToList(); sameProperties.Sort((p1, p2) => p1.DeclaringType.IsAssignableFrom(p2.DeclaringType) ? 1 : -1); if (sameProperties[0] == property) { object value = property.GetValue(clientResource, null); providers.ResourceProperty resourceProperty = resourceType == null ? null : resourceType.Properties.SingleOrDefault(p => p.Name == property.Name); resource.SetRawValue(property.Name, CreateServerValueFromClientValue(value, resourceProperty == null ? null : resourceProperty.ResourceType, createCollection, clientInstanceToResourceType)); } } return(resource); }
public void GetTargetSetTestsSetBindingTypeShouldPerformCorrectValidation() { ResourceType actorEntityType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "foo", "Actor", false) { CanReflectOnInstanceType = false }; ResourceProperty idProperty = new ResourceProperty("ID", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false }; actorEntityType.AddProperty(idProperty); ResourceType addressComplexType = new ResourceType(typeof(object), ResourceTypeKind.ComplexType, null, "foo", "Address", false) { CanReflectOnInstanceType = false }; addressComplexType.AddProperty(new ResourceProperty("StreetAddress", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string))) { CanReflectOnInstanceTypeProperty = false }); addressComplexType.AddProperty(new ResourceProperty("ZipCode", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false }); actorEntityType.AddProperty(new ResourceProperty("PrimaryAddress", ResourcePropertyKind.ComplexType, addressComplexType) { CanReflectOnInstanceTypeProperty = false }); actorEntityType.AddProperty(new ResourceProperty("OtherAddresses", ResourcePropertyKind.Collection, ResourceType.GetCollectionResourceType(addressComplexType)) { CanReflectOnInstanceTypeProperty = false }); ResourceType movieEntityType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "foo", "Movie", false) { CanReflectOnInstanceType = false }; movieEntityType.AddProperty(idProperty); ResourceProperty moviesNavProp = new ResourceProperty("Movies", ResourcePropertyKind.ResourceSetReference, movieEntityType) { CanReflectOnInstanceTypeProperty = false }; actorEntityType.AddProperty(moviesNavProp); ResourceProperty actorsNavProp = new ResourceProperty("Actors", ResourcePropertyKind.ResourceSetReference, actorEntityType) { CanReflectOnInstanceTypeProperty = false }; movieEntityType.AddProperty(actorsNavProp); ResourceType derivedActorEntityType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, actorEntityType, "foo", "DerivedActor", false) { CanReflectOnInstanceType = false }; ResourceType derivedMovieEntityType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, movieEntityType, "foo", "DerivedMovie", false) { CanReflectOnInstanceType = false }; actorEntityType.SetReadOnly(); derivedActorEntityType.SetReadOnly(); movieEntityType.SetReadOnly(); derivedMovieEntityType.SetReadOnly(); addressComplexType.SetReadOnly(); DataServiceProviderSimulator providerSimulator = new DataServiceProviderSimulator(); providerSimulator.AddResourceType(actorEntityType); providerSimulator.AddResourceType(derivedActorEntityType); providerSimulator.AddResourceType(movieEntityType); providerSimulator.AddResourceType(derivedMovieEntityType); providerSimulator.AddResourceType(addressComplexType); ResourceSet actorSet = new ResourceSet("Actors", actorEntityType); ResourceSet movieSet = new ResourceSet("Movies", movieEntityType); actorSet.SetReadOnly(); movieSet.SetReadOnly(); providerSimulator.AddResourceSet(actorSet); providerSimulator.AddResourceSet(movieSet); providerSimulator.AddResourceAssociationSet(new ResourceAssociationSet("Actors_Movies", new ResourceAssociationSetEnd(actorSet, actorEntityType, moviesNavProp), new ResourceAssociationSetEnd(movieSet, movieEntityType, actorsNavProp))); DataServiceConfiguration config = new DataServiceConfiguration(providerSimulator); config.SetEntitySetAccessRule("*", EntitySetRights.All); config.DataServiceBehavior.MaxProtocolVersion = ODataProtocolVersion.V4; var dataService = new DataServiceSimulator() { OperationContext = new DataServiceOperationContext(new DataServiceHostSimulator()) }; dataService.ProcessingPipeline = new DataServiceProcessingPipeline(); DataServiceStaticConfiguration staticConfiguration = new DataServiceStaticConfiguration(dataService.Instance.GetType(), providerSimulator); IDataServiceProviderBehavior providerBehavior = DataServiceProviderBehavior.CustomDataServiceProviderBehavior; DataServiceProviderWrapper provider = new DataServiceProviderWrapper( new DataServiceCacheItem( config, staticConfiguration), providerSimulator, providerSimulator, dataService, false); dataService.Provider = provider; provider.ProviderBehavior = providerBehavior; var testCases = new[] { new { AppendParameterName = true, Path = "", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), ErrorMessage = default(string) }, new { AppendParameterName = true, Path = "/Movies", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = ResourceSetWrapper.CreateResourceSetWrapper(movieSet, provider, set => set), ErrorMessage = default(string) }, new { AppendParameterName = true, Path = "/Movies/Actors/Movies", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = ResourceSetWrapper.CreateResourceSetWrapper(movieSet, provider, set => set), ErrorMessage = default(string) }, new { AppendParameterName = true, Path = "/foo.DerivedActor/Movies/foo.DerivedMovie/Actors/foo.DerivedActor/Movies", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = ResourceSetWrapper.CreateResourceSetWrapper(movieSet, provider, set => set), ErrorMessage = default(string) }, new { AppendParameterName = true, Path = "/", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression '{0}/' is not a valid expression because it contains an empty segment or it ends with '/'." }, new { AppendParameterName = true, Path = "/Movies/", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression '{0}/Movies/' is not a valid expression because it contains an empty segment or it ends with '/'." }, new { AppendParameterName = true, Path = "/Movies//Actors", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = ResourceSetWrapper.CreateResourceSetWrapper(movieSet, provider, set => set), ErrorMessage = "The path expression '{0}/Movies//Actors' is not a valid expression because it contains an empty segment or it ends with '/'." }, new { AppendParameterName = true, Path = "/foo.DerivedActor", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression '{0}/foo.DerivedActor' is not a valid expression because it ends with the type identifier 'foo.DerivedActor'. A valid path expression must not end in a type identifier." }, new { AppendParameterName = true, Path = "/Movies/foo.DerivedMovie", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression '{0}/Movies/foo.DerivedMovie' is not a valid expression because it ends with the type identifier 'foo.DerivedMovie'. A valid path expression must not end in a type identifier." }, new { AppendParameterName = true, Path = "/Foo", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression '{0}/Foo' is not a valid expression because the segment 'Foo' is not a type identifier or a property on the resource type 'foo.Actor'." }, new { AppendParameterName = true, Path = "/ID", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression '{0}/ID' is not a valid expression because the segment 'ID' is a property of type 'Edm.Int32'. A valid path expression must only contain properties of entity type." }, new { AppendParameterName = true, Path = "/OtherAddresses", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression '{0}/OtherAddresses' is not a valid expression because the segment 'OtherAddresses' is a property of type 'Collection(foo.Address)'. A valid path expression must only contain properties of entity type." }, new { AppendParameterName = true, Path = "/Movies/Actors/PrimaryAddress", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression '{0}/Movies/Actors/PrimaryAddress' is not a valid expression because the segment 'PrimaryAddress' is a property of type 'foo.Address'. A valid path expression must only contain properties of entity type." }, new { AppendParameterName = false, Path = "foo", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression 'foo' is not a valid path expression. A valid path expression must start with the binding parameter name '{0}'." }, new { AppendParameterName = false, Path = "abc/pqr", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression 'abc/pqr' is not a valid path expression. A valid path expression must start with the binding parameter name '{0}'." }, new { AppendParameterName = false, Path = "actorParameter", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression 'actorParameter' is not a valid path expression. A valid path expression must start with the binding parameter name '{0}'." }, new { AppendParameterName = false, Path = "actorsParameter", BindingSet = ResourceSetWrapper.CreateResourceSetWrapper(actorSet, provider, set => set), TargetSet = default(ResourceSetWrapper), ErrorMessage = "The path expression 'actorsParameter' is not a valid path expression. A valid path expression must start with the binding parameter name '{0}'." }, }; ServiceActionParameter actorParameter = new ServiceActionParameter("actor", actorEntityType); ServiceActionParameter actorsParameter = new ServiceActionParameter("actors", ResourceType.GetEntityCollectionResourceType(actorEntityType)); var parameters = new ServiceActionParameter[] { actorParameter, actorsParameter }; foreach (var parameter in parameters) { foreach (var testCase in testCases) { string pathString = testCase.AppendParameterName ? parameter.Name + testCase.Path : testCase.Path; var path = new ResourceSetPathExpression(pathString); Assert.AreEqual(pathString, path.PathExpression); string expectedErrorMessage = testCase.ErrorMessage == null ? null : string.Format(testCase.ErrorMessage, parameter.Name); try { path.SetBindingParameter(parameter); path.InitializePathSegments(provider); var targetSet = path.GetTargetSet(provider, testCase.BindingSet); Assert.IsNull(expectedErrorMessage, "Expecting exception but received none."); Assert.AreEqual(targetSet.Name, testCase.TargetSet.Name); } catch (InvalidOperationException e) { Assert.AreEqual(expectedErrorMessage, e.Message); } } } }
public abstract object GetValue(object value, DSP.ResourceProperty property);
/// <summary> /// Creates an <see cref="IEdmProperty"/> for the <paramref name="resourceProperty"/>. /// </summary> /// <param name="declaringType">The declaring type of the <paramref name="resourceProperty"/>.</param> /// <param name="resourceProperty">The resource property to create an EDM property for.</param> /// <returns>An <see cref="IEdmProperty"/> instance for the <paramref name="resourceProperty"/>.</returns> /// <remarks> /// Materialization state: none required. No change in materialization state. /// Cache state: none required. No change in cache state. /// </remarks> private IEdmProperty CreateProperty(EdmStructuredType declaringType, ResourceProperty resourceProperty) { Debug.Assert(declaringType != null, "structuralType != null"); Debug.Assert(resourceProperty != null, "resourceProperty != null"); List<KeyValuePair<string, object>> customAnnotations = resourceProperty.CustomAnnotations == null ? null : resourceProperty.CustomAnnotations.ToList(); IEdmProperty result; ODataNullValueBehaviorKind nullValueReadBehaviorKind = ODataNullValueBehaviorKind.Default; if (resourceProperty.IsOfKind(ResourcePropertyKind.Primitive) || resourceProperty.IsOfKind(ResourcePropertyKind.Stream)) { ResourceType resourceType = resourceProperty.ResourceType; IEdmPrimitiveTypeReference primitiveTypeReference = MetadataProviderUtils.CreatePrimitiveTypeReference(resourceType, customAnnotations); if (resourceProperty.IsOfKind(ResourcePropertyKind.Key)) { // if the property is a key we force nullable to be 'false' if (primitiveTypeReference.IsNullable) { Debug.Assert(resourceProperty.IsOfKind(ResourcePropertyKind.Primitive), "Streams are always non-nullable so this must be a primitive resource property"); primitiveTypeReference = (IEdmPrimitiveTypeReference)primitiveTypeReference.Clone(/*nullable*/false); } // EdmLib bridge marks all key properties as non-nullable, but Astoria allows them to be nullable. // Key properties must be non-nullable in CSDL; in Astoria we need the ability to ignore null values for // key properties since our client will send null values for non-initialized properties (e.g., insert with // auto-generated keys). // Note that this applies even to properties which are not nullable in Astoria, we still need to ignore null values // for key property like that. nullValueReadBehaviorKind = ODataNullValueBehaviorKind.IgnoreValue; } else if (MetadataProviderUtils.ShouldDisablePrimitivePropertyNullValidation(resourceProperty, primitiveTypeReference)) { nullValueReadBehaviorKind = ODataNullValueBehaviorKind.DisableValidation; } string defaultValue = MetadataProviderUtils.GetAndRemoveDefaultValue(customAnnotations); EdmConcurrencyMode concurrencyMode = resourceProperty.IsOfKind(ResourcePropertyKind.ETag) ? EdmConcurrencyMode.Fixed : EdmConcurrencyMode.None; result = new MetadataProviderEdmStructuralProperty(declaringType, resourceProperty, primitiveTypeReference, defaultValue, concurrencyMode); declaringType.AddProperty(result); string mimeType = resourceProperty.MimeType; if (!string.IsNullOrEmpty(mimeType)) { this.SetMimeType(result, mimeType); } } else if (resourceProperty.IsOfKind(ResourcePropertyKind.ComplexType)) { IEdmTypeReference typeReference = this.EnsureTypeReference(resourceProperty.ResourceType, customAnnotations); // NOTE: WCF DS does not support complex ETag properties string defaultValue = MetadataProviderUtils.GetAndRemoveDefaultValue(customAnnotations); result = new MetadataProviderEdmStructuralProperty(declaringType, resourceProperty, typeReference, defaultValue, EdmConcurrencyMode.None); declaringType.AddProperty(result); // We need to mark all complex types in EF provider as "allow null" in order to maintain backward compat behavior // of failing with 500 on null updates to complex values (since WCF DS V2 treated all complex values as nullable). // Note that V1 providers are EF and Reflection. But reflection provider marks all complex types as nullable. if (this.metadataProvider.HasReflectionOrEFProviderQueryBehavior && !typeReference.IsNullable) { nullValueReadBehaviorKind = ODataNullValueBehaviorKind.DisableValidation; } } else if (resourceProperty.IsOfKind(ResourcePropertyKind.Collection)) { string defaultValue = MetadataProviderUtils.GetAndRemoveDefaultValue(customAnnotations); IEdmTypeReference collectionTypeReference = this.EnsureTypeReference(resourceProperty.ResourceType, customAnnotations); result = new MetadataProviderEdmStructuralProperty(declaringType, resourceProperty, collectionTypeReference, defaultValue, EdmConcurrencyMode.None); declaringType.AddProperty(result); } else if (resourceProperty.IsOfKind(ResourcePropertyKind.ResourceSetReference) || resourceProperty.IsOfKind(ResourcePropertyKind.ResourceReference)) { Debug.Assert(resourceProperty.TypeKind == ResourceTypeKind.EntityType, "Expected entity type kind for navigation properties"); Debug.Assert(declaringType.TypeKind == EdmTypeKind.Entity, "declaringType.TypeKind == EdmTypeKind.Entity"); EdmEntityType sourceEntityType = (EdmEntityType)declaringType; IEdmTypeReference targetTypeReference = resourceProperty.IsOfKind(ResourcePropertyKind.ResourceSetReference) ? this.EnsureEntityPrimitiveOrComplexCollectionTypeReference(resourceProperty.ResourceType, new EntityCollectionResourceType(resourceProperty.ResourceType), customAnnotations) : this.EnsureTypeReference(resourceProperty.ResourceType, customAnnotations); result = new MetadataProviderEdmNavigationProperty(sourceEntityType, resourceProperty, targetTypeReference); sourceEntityType.AddProperty(result); } else { throw new InvalidOperationException(Microsoft.OData.Service.Strings.MetadataProviderEdmModel_UnsupportedResourcePropertyKind(resourceProperty.Kind.ToString())); } // Add the OData property annotation to the property // TODO: Once we want to support OData.Query we need to add a property annotation here to specify the CanReflectOnInstanceProperty value. this.SetNullValueReaderBehavior(result, nullValueReadBehaviorKind); // NOTE: we removed any facets from the annotations above; the remaining annotations will be serialized. MetadataProviderUtils.ConvertCustomAnnotations(this, customAnnotations, result); return result; }
public Uri GetReadStreamUri(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty, DataServiceOperationContext operationContext) { return(null); }
} // ServiceOperations public DSP.ResourceAssociationSet GetResourceAssociationSet(DSP.ResourceSet resourceSet, DSP.ResourceType resourceType, DSP.ResourceProperty resourceProperty) { if (associations == null) { associations = new Dictionary <string, DSP.ResourceAssociationSet>(); } DSP.ResourceType targetType = resourceProperty.ResourceType; DSP.ResourceSet targetSet = null; var targetContainers = this.containers.Where(c => IsAssignableFrom(c.ResourceType, targetType)); if (targetContainers.Count() == 1) { targetSet = targetContainers.First(); } else if (targetContainers.Count() > 1) { // MEST (uses naming convention) if (resourceSet.CustomState != null) { targetSet = targetContainers.Single(c => (string)c.CustomState == (string)resourceSet.CustomState); } else if (resourceProperty.CustomState != null) { targetSet = targetContainers.Single(c => (string)c.CustomState == (string)resourceProperty.CustomState); } else { throw new DataServiceException(500, "Cannot infer association set for MEST scenario"); } } string associationName = resourceSet.Name + "_" + resourceType.Name + '_' + resourceProperty.Name; if (associations.Keys.Contains(associationName)) { return(associations[associationName]); } else { DSP.ResourceProperty targetProperty = null; // Self links must be one-way if (resourceProperty.CustomState != null && (resourceSet != targetSet && resourceType != targetType)) { targetProperty = targetType.Properties.SingleOrDefault(p => p.CustomState != null && (string)p.CustomState == (string)resourceProperty.CustomState); } DSP.ResourceAssociationSetEnd sourceEnd = new DSP.ResourceAssociationSetEnd(resourceSet, resourceType, resourceProperty); DSP.ResourceAssociationSetEnd targetEnd = new DSP.ResourceAssociationSetEnd(targetSet, targetType, targetProperty); DSP.ResourceAssociationSet associationSet = new DSP.ResourceAssociationSet(associationName, sourceEnd, targetEnd); associations.Add(associationName, associationSet); // add to hash for target side if (targetProperty != null) { associationName = targetSet.Name + "_" + targetType.Name + '_' + targetProperty.Name; associations.Add(associationName, associationSet); } return(associationSet); } } // GetResourceAssociationSet
/// <summary> /// Gets the ResourceAssociationSet instance when given the source association end. /// </summary> /// <param name="resourceSet">Resource set of the source association end.</param> /// <param name="resourceType">Resource type of the source association end.</param> /// <param name="resourceProperty">Resource property of the source association end.</param> /// <returns>ResourceAssociationSet instance.</returns> /// <remarks>This method returns a ResourceAssociationSet representing a reference which is specified /// by the <paramref name="resourceProperty"/> on the <paramref name="resourceType"/> for instances in the <paramref name="resourceSet"/>.</remarks> public virtual ResourceAssociationSet GetResourceAssociationSet(ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty) { ResourceAssociationSet resourceAssociationSet; if (this.associationSets.TryGetValue(resourceSet.Name + "_" + resourceType.FullName + "_" + resourceProperty.Name, out resourceAssociationSet)) { Debug.Assert(resourceAssociationSet != null, "resourceAssociationSet != null"); // Just few verification to show what is expected of the returned resource association set. Debug.Assert( (resourceAssociationSet.End1.ResourceSet == resourceSet && resourceAssociationSet.End1.ResourceType == resourceType && resourceAssociationSet.End1.ResourceProperty == resourceProperty) || (resourceAssociationSet.End2.ResourceSet == resourceSet && resourceAssociationSet.End2.ResourceType == resourceType && resourceAssociationSet.End2.ResourceProperty == resourceProperty), "The precreated resource association set doesn't match the specified resource set."); } else { // We have the resource association set precreated on the property annotation, so no need to compute anything in here Debug.Assert(resourceProperty.GetAnnotation().ResourceAssociationSet != null, "resourceProperty.GetAnnotation().ResourceAssociationSet != null"); resourceAssociationSet = resourceProperty.GetAnnotation().ResourceAssociationSet(); // Just few verification to show what is expected of the returned resource association set. Debug.Assert(resourceAssociationSet.End1.ResourceSet == resourceSet, "The precreated resource association set doesn't match the specified resource set."); Debug.Assert(resourceAssociationSet.End1.ResourceType == resourceType, "The precreated resource association set doesn't match the specified resource type."); Debug.Assert(resourceAssociationSet.End1.ResourceProperty == resourceProperty, "The precreated resource association set doesn't match its resource property."); } return resourceAssociationSet; }
public void UpdatePutContentTypeTest() { var targets = new [] { // Declared property new PutContentTypeTarget { Url = "/Orders(0)/OrderName", Kind = AddressableElementKind.EntityPrimitiveProperty, ValidContentTypes = new [] { UnitTestsUtil.MimeApplicationXml, UnitTestsUtil.MimeTextXml, UnitTestsUtil.JsonLightMimeType }, }, // Open property new PutContentTypeTarget { Url = "/Orders(0)/OpenProperty", Kind = AddressableElementKind.EntityPrimitiveOpenProperty, ValidContentTypes = new [] { UnitTestsUtil.MimeApplicationXml, UnitTestsUtil.MimeTextXml, UnitTestsUtil.JsonLightMimeType }, }, // Declared property value new PutContentTypeTarget { Url = "/Orders(0)/OrderName/$value", Kind = AddressableElementKind.EntityPrimitivePropertyValue, ValidContentTypes = new [] { UnitTestsUtil.MimeTextPlain }, }, // Open property new PutContentTypeTarget { Url = "/Orders(0)/OpenProperty/$value", Kind = AddressableElementKind.EntityPrimitiveOpenPropertyValue, ValidContentTypes = new [] { UnitTestsUtil.MimeTextPlain }, }, // Entity new PutContentTypeTarget { Url = "/Orders(0)", Kind = AddressableElementKind.Entity, ValidContentTypes = new [] { UnitTestsUtil.AtomFormat, "application/atom+xml;type=entry", UnitTestsUtil.MimeAny, UnitTestsUtil.JsonLightMimeType }, }, // Singleton $ref new PutContentTypeTarget { Url = "/Orders(0)/Customer/$ref", Kind = AddressableElementKind.EntityReference, ValidContentTypes = new [] { UnitTestsUtil.MimeApplicationXml, UnitTestsUtil.MimeTextXml, UnitTestsUtil.JsonLightMimeType }, }, }; var payloads = new [] { new PutContentTypePayload { Description = "JSON Single property OrderName", ContentTypes = new [] { UnitTestsUtil.JsonLightMimeType }, Payload = "{ value: 'Foo' }", ValidKinds = new [] { AddressableElementKind.EntityPrimitiveOpenProperty, AddressableElementKind.EntityPrimitiveProperty, // Note that in JSON there's no way to distiguish between the property and entry payloads - so this is a valid entry payload as well AddressableElementKind.Entity }, }, new PutContentTypePayload { Description = "XML Single property OrderName", ContentTypes = new [] { UnitTestsUtil.MimeApplicationXml, UnitTestsUtil.MimeTextXml }, Payload = "<ads:OrderName xmlns:ads='http://docs.oasis-open.org/odata/ns/data'>Foo</ads:OrderName>", ValidKinds = new [] { AddressableElementKind.EntityPrimitiveProperty, // Server ignores the property name for open properties - so this payload is valid for the open property as well. AddressableElementKind.EntityPrimitiveOpenProperty } }, new PutContentTypePayload { Description = "JSON Single property OpenProperty", ContentTypes = new [] { UnitTestsUtil.JsonLightMimeType }, Payload = "{ value: 'Foo' }", ValidKinds = new [] { AddressableElementKind.EntityPrimitiveProperty, AddressableElementKind.EntityPrimitiveOpenProperty, // Note that in JSON there's no way to distiguish between the property and entry payloads - so this is a valid entry payload as well AddressableElementKind.Entity }, }, new PutContentTypePayload { Description = "Raw string value", ContentTypes = new [] { UnitTestsUtil.MimeTextPlain }, Payload = "some value", ValidKinds = new [] { AddressableElementKind.EntityPrimitivePropertyValue, AddressableElementKind.EntityPrimitiveOpenPropertyValue } }, new PutContentTypePayload { Description = "ATOM Entity instance with type", ContentTypes = new [] { UnitTestsUtil.AtomFormat, "application/atom+xml;type=entry", "application/atom+xml;type=feed", "application/atom+xml;type=test", // Server treats */* as ATOM content type UnitTestsUtil.MimeAny }, Payload = "<entry " + "xmlns:ads='http://docs.oasis-open.org/odata/ns/data' " + "xmlns:adsm='http://docs.oasis-open.org/odata/ns/metadata' " + "xmlns='http://www.w3.org/2005/Atom'>\r\n" + "<category scheme='http://docs.oasis-open.org/odata/ns/scheme' term='#AstoriaUnitTests.Stubs.Order'/>" + "</entry>", ValidKinds = new [] { AddressableElementKind.Entity }, ExpectedStatusCode = (kind, contentType) => { // We need to accept wrong type parameter as long as the mime type is correct. if (kind == AddressableElementKind.Entity && (contentType == "application/atom+xml;type=feed" || contentType == "application/atom+xml;type=test")) { return 200; } return 0; }, }, new PutContentTypePayload { Description = "JSON Entity instance with type", ContentTypes = new [] { UnitTestsUtil.JsonLightMimeType }, Payload = "{ @odata.type: 'AstoriaUnitTests.Stubs.Order' }", ValidKinds = new [] { AddressableElementKind.Entity }, }, new PutContentTypePayload { Description = "ATOM Entity instance without type", ContentTypes = new [] { UnitTestsUtil.AtomFormat, "application/atom+xml;type=entry", "application/atom+xml;type=feed", "application/atom+xml;type=test", // Server treats */* as ATOM content type UnitTestsUtil.MimeAny }, Payload = "<entry " + "xmlns:ads='http://docs.oasis-open.org/odata/ns/data' " + "xmlns:adsm='http://docs.oasis-open.org/odata/ns/metadata' " + "xmlns='http://www.w3.org/2005/Atom'>\r\n" + "</entry>", ValidKinds = new [] { AddressableElementKind.Entity }, ExpectedStatusCode = (kind, contentType) => { // We need to accept wrong type parameter as long as the mime type is correct. if (kind == AddressableElementKind.Entity && (contentType == "application/atom+xml;type=feed" || contentType == "application/atom+xml;type=test")) { return 200; } return 0; }, }, new PutContentTypePayload { Description = "JSON Entity instance without type", ContentTypes = new [] { UnitTestsUtil.JsonLightMimeType }, Payload = "{ }", ValidKinds = new [] { AddressableElementKind.Entity }, }, new PutContentTypePayload { Description = "ATOM Feed", ContentTypes = new [] { UnitTestsUtil.AtomFormat, "application/atom+xml;type=feed", // Server treats */* as ATOM content type UnitTestsUtil.MimeAny }, Payload = "<feed " + "xmlns:ads='http://docs.oasis-open.org/odata/ns/data' " + "xmlns:adsm='http://docs.oasis-open.org/odata/ns/metadata' " + "xmlns='http://www.w3.org/2005/Atom'>\r\n" + "</feed>", ValidKinds = new AddressableElementKind[] { }, ExpectedStatusCode = (kind, contentType) => { if (kind == AddressableElementKind.Entity && contentType != "application/atom+xml;type=feed") { // Sending an ATOM payload to an entity end point is valid, but it will fail due to the root element called "feed". return 400; } if (kind == AddressableElementKind.Entity && contentType == "application/atom+xml;type=feed") { // Server ignores the type=feed in the content type if it's ATOM content type. // but this will fail due to the root element called "feed" return 400; } return 0; }, }, new PutContentTypePayload { Description = "JSON feed", ContentTypes = new [] { UnitTestsUtil.JsonLightMimeType }, Payload = "[]", ValidKinds = new AddressableElementKind[] { }, }, new PutContentTypePayload { Description = "Empty payload with unrecognized content type.", ContentTypes = new [] { "mime/type", "application/foo", "test/foo" }, Payload = "", ValidKinds = new AddressableElementKind[] { }, }, }; string[] contentTypes = payloads.SelectMany(p => p.ContentTypes).Distinct().ToArray(); // Tests various content types for various possible PUT targets TestUtil.RunCombinations( targets, contentTypes, (target, contentType) => { TestUtil.RunCombinations( payloads.Where(payload => payload.ContentTypes.Contains(contentType)), payload => { using (TestUtil.RestoreStaticValueOnDispose(typeof(CustomRowBasedOpenTypesContext), "CustomizeMetadata")) using (CustomDataContext.CreateChangeScope()) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { if (payload.SkipWhen != null && payload.SkipWhen(target.Kind, contentType)) { return; } CustomRowBasedOpenTypesContext.CustomizeMetadata = (resourceSets, types, operations, associationSets) => { provider.ResourceType order = types.Where(t => t.Name == "Order").First(); provider.ResourceProperty orderNameProperty = new provider.ResourceProperty("OrderName", provider.ResourcePropertyKind.Primitive, provider.ResourceType.GetPrimitiveResourceType(typeof(string))); orderNameProperty.CanReflectOnInstanceTypeProperty = false; order.AddProperty(orderNameProperty); }; request.DataServiceType = typeof(PutContentTypeContext); request.HttpMethod = "PUT"; request.RequestUriString = target.Url; request.RequestContentType = contentType; request.RequestStream = new MemoryStream(Encoding.UTF8.GetBytes(payload.Payload)); TestUtil.RunCatching(request.SendRequest); Trace.WriteLine(payload.Description + ", Content-Type: " + contentType + ", Url: " + target.Url + ", Response Status: " + request.ResponseStatusCode.ToString()); Trace.WriteLine(request.GetResponseStreamAsText()); int expectedStatusCode = 0; if (payload.ExpectedStatusCode != null) { expectedStatusCode = payload.ExpectedStatusCode(target.Kind, contentType); } if (expectedStatusCode != 0) { if (expectedStatusCode == 200) { Assert.IsTrue(request.ResponseStatusCode == 200 || request.ResponseStatusCode == 204, "Should have succeeded."); } else { Assert.AreEqual(expectedStatusCode, request.ResponseStatusCode, "Unexpected status code."); } } else { if (target.ValidContentTypes.Contains(contentType)) { if (payload.ValidKinds.Contains(target.Kind)) { Assert.IsTrue(request.ResponseStatusCode == 200 || request.ResponseStatusCode == 204, "Should have succeeded."); } else { Assert.AreEqual(400, request.ResponseStatusCode, "Should have failed to process the payload."); } } else { Assert.AreEqual(415, request.ResponseStatusCode, "Should not be recognized as valid content type."); } } } }); }); }
public string GetStreamContentType(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty, DataServiceOperationContext operationContext) { return("text/plain"); }
public void GetResourceAssociationSet(DSP.ResourceSet resourceSet, DSP.ResourceType resourceType, DSP.ResourceProperty resourceProperty) { Add("GetResourceAssociationSet", Serialize(resourceSet), Serialize(resourceType), Serialize(resourceProperty)); }
private string Serialize(DSP.ResourceProperty streamProperty) { return(streamProperty == null ? "null ResourceProperty" : streamProperty.Name); }
/// <summary> /// Returns the URI associated with the stream /// </summary> /// <param name="entity">Entity that contains the stream</param> /// <param name="streamProperty">Stream information</param> /// <param name="operationContext">Gives the operation context</param> /// <returns>Returns the URI</returns> public Uri GetReadStreamUri(object entity, provider.ResourceProperty streamProperty, DataServiceOperationContext operationContext) { return(this.GetReadStreamUri(entity, streamProperty, null, operationContext)); }
/// <summary> /// Returns the ETag of the stream /// </summary> /// <param name="entity">Entity with the stream</param> /// <param name="streamProperty">Stream property</param> /// <param name="operationContext">Gives the operation context</param> /// <returns>Returns the Stream ETag</returns> public string GetStreamETag(object entity, provider.ResourceProperty streamProperty, DataServiceOperationContext operationContext) { return(this.GetStreamETag(entity, streamProperty, null, operationContext)); }
/// <summary> /// Validates the entity and stream info prameters. /// </summary> /// <param name="entity">entity instance.</param> /// <param name="streamProperty">stream property</param> protected override void ValidateEntity(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty) { this.ValidateEntity(entity); }
public Stream GetReadStream(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty, string etag, bool?checkETagForEquality, DataServiceOperationContext operationContext) { return(new MemoryStream()); }
private static bool IsPropertyKind(ResourceProperty property, ResourcePropertyKind propertyKind) { return (property.Kind & propertyKind) == propertyKind; }
private string Serialize(DSP.ResourceProperty property) { return(property.Name); }
/// <summary>Adds a new resource property.</summary> /// <param name="resourceType">The resource type to add the property to.</param> /// <param name="name">The name of the property to add.</param> /// <param name="kind">The kind of the property to add.</param> /// <param name="propertyType">The type of the property to add.</param> /// <param name="propertyInfo">If this is a CLR property, the <see cref="PropertyInfo"/> for the property, or null otherwise.</param> /// <returns>The newly created and added property.</returns> private static ResourceProperty AddResourceProperty( ResourceType resourceType, string name, ResourcePropertyKind kind, ResourceType propertyType, PropertyInfo propertyInfo) { ResourceProperty property = new ResourceProperty(name, kind, propertyType); if (propertyInfo != null) { property.CanReflectOnInstanceTypeProperty = true; property.CustomState = new ResourcePropertyAnnotation() { PropertyInfo = propertyInfo }; } else if (kind != ResourcePropertyKind.Stream) { property.CanReflectOnInstanceTypeProperty = false; property.CustomState = new ResourcePropertyAnnotation() { }; } resourceType.AddProperty(property); return property; }
public void GetPropertyValue(object target, DSP.ResourceProperty resourceProperty) { Add("GetPropertyValue", Parent.Serialize(target), Serialize(resourceProperty)); }
/// <summary>Initializes a new <see cref="ExpandSegment"/> instance.</summary> /// <param name="name">Segment name.</param> /// <param name="filter">Filter expression for segment, possibly null.</param> /// <param name="maxResultsExpected"> /// Expand providers may choose to return at most MaxResultsExpected + 1 elements to allow the /// data service to detect a failure to meet this constraint. /// </param> /// <param name="container">Container to which the segment belongs; possibly null.</param> /// <param name="targetResourceType">Target resource type on which the expansion needs to happen.</param> /// <param name="expandedProperty">Property expanded by this expand segment</param> /// <param name="orderingInfo">Collection of ordering information for this segment, used for paging</param> internal ExpandSegment( string name, Expression filter, int maxResultsExpected, ResourceSetWrapper container, ResourceType targetResourceType, ResourceProperty expandedProperty, OrderingInfo orderingInfo) { WebUtil.CheckArgumentNull(name, "name"); CheckFilterType(filter); this.name = name; this.filter = filter; this.container = container; this.maxResultsExpected = maxResultsExpected; this.expandedProperty = expandedProperty; this.orderingInfo = orderingInfo; this.targetResourceType = targetResourceType; }
public object GetPropertyValue(object target, ResourceProperty resourceProperty) { Assert.IsTrue(resourceProperty.CanReflectOnInstanceTypeProperty == false, "We should never call GetPropertyValue on reflectable properties"); return InternalGetPropertyValue(target, resourceProperty.Name); }
/// <summary> /// Override for member access visitor /// </summary> /// <param name="m">Member access expression</param> /// <returns>Same expressions as <paramref name="m"/></returns> internal override Expression VisitMemberAccess(MemberExpression m) { if (m.Member.MemberType != MemberTypes.Property || m.Expression.NodeType != ExpressionType.Parameter) { this.NeedSkipToken = true; return m; } // Is this a visitor for collection of resource properties if (this.rt != null) { this.property = this.rt.TryResolvePropertyName(m.Member.Name, exceptKind: ResourcePropertyKind.Stream); Debug.Assert( this.property != null && this.property.ResourceType.ResourceTypeKind == ResourceTypeKind.Primitive, "skip token should be made up of primitive properties."); } return base.VisitMemberAccess(m); }
private static DataServiceProviderWrapper CreateProvider(out DataServiceConfiguration config, out DataServiceOperationContext operationContext) { var baseUri = new Uri("http://localhost"); var host = new DataServiceHostSimulator() { AbsoluteServiceUri = baseUri, AbsoluteRequestUri = new Uri(baseUri.AbsoluteUri + "/$metadata", UriKind.Absolute), RequestHttpMethod = "GET", RequestAccept = "application/xml+atom", RequestVersion = "4.0", RequestMaxVersion = "4.0", }; operationContext = new DataServiceOperationContext(host); var dataService = new DataServiceSimulator() { OperationContext = operationContext }; operationContext.InitializeAndCacheHeaders(dataService); DataServiceProviderSimulator providerSimulator = new DataServiceProviderSimulator(); providerSimulator.ContainerNamespace = "MyModel"; providerSimulator.ContainerName = "CustomersContainer"; ResourceType customerEntityType = new ResourceType( typeof(object), ResourceTypeKind.EntityType, null, "MyModel", "Customer", false) { CanReflectOnInstanceType = false }; ResourcePropertyKind idPropertyKind = ResourcePropertyKind.Primitive | ResourcePropertyKind.Key; ResourceProperty idProperty = new ResourceProperty( "Id", idPropertyKind, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false }; customerEntityType.AddProperty(idProperty); ResourcePropertyKind firstNamePropertyKind = ResourcePropertyKind.Primitive | ResourcePropertyKind.Key; ResourceProperty firstNameProperty = new ResourceProperty( "FirstName", firstNamePropertyKind, ResourceType.GetPrimitiveResourceType(typeof(string))) { CanReflectOnInstanceTypeProperty = false }; customerEntityType.AddProperty(firstNameProperty); customerEntityType.SetReadOnly(); providerSimulator.AddResourceType(customerEntityType); ResourceSet customerSet = new ResourceSet("Customers", customerEntityType); customerSet.SetReadOnly(); providerSimulator.AddResourceSet(customerSet); config = new DataServiceConfiguration(providerSimulator); config.SetEntitySetAccessRule("*", EntitySetRights.All); config.DataServiceBehavior.MaxProtocolVersion = ODataProtocolVersion.V4; IDataServiceProviderBehavior providerBehavior = DataServiceProviderBehavior.CustomDataServiceProviderBehavior; DataServiceStaticConfiguration staticConfig = new DataServiceStaticConfiguration(dataService.Instance.GetType(), providerSimulator); DataServiceProviderWrapper provider = new DataServiceProviderWrapper( new DataServiceCacheItem(config, staticConfig), providerSimulator, providerSimulator, dataService, false); dataService.ProcessingPipeline = new DataServiceProcessingPipeline(); dataService.Provider = provider; provider.ProviderBehavior = providerBehavior; dataService.ActionProvider = DataServiceActionProviderWrapper.Create(dataService); #if DEBUG dataService.ProcessingPipeline.SkipDebugAssert = true; #endif operationContext.RequestMessage.InitializeRequestVersionHeaders(VersionUtil.ToVersion(config.DataServiceBehavior.MaxProtocolVersion)); return provider; }
public void AddLazyProperty(DSP.ResourceProperty property) { this.lazyProperties.Add(property); }
public string GetStreamETag(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty, DataServiceOperationContext operationContext) { return(null); }
public abstract IEnumerable <T> GetSequenceValue <T>(object value, DSP.ResourceProperty property);
/// <summary> /// Retrieve the related end for the given resource set, type and property. /// </summary> /// <param name="resourceType">resource type for the source end</param> /// <param name="resourceProperty">resource property for the source end</param> /// <returns>Related association type end for the given parameters</returns> internal ResourceAssociationTypeEnd GetRelatedResourceAssociationSetEnd(ResourceType resourceType, ResourceProperty resourceProperty) { Debug.Assert(resourceType != null, "resourceType != null"); ResourceAssociationTypeEnd thisEnd = this.GetResourceAssociationTypeEnd(resourceType, resourceProperty); if (thisEnd != null) { foreach (ResourceAssociationTypeEnd end in new[] { this.end1, this.end2 }) { if (end != thisEnd) { return end; } } } return null; }
private static IDataServiceMetadataProvider PopulateMetadata(object dataSourceInstance) { List<ResourceType> types = new List<ResourceType>(4); ResourceType customer = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, null, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "Customer", false /*isAbstract*/); customer.CanReflectOnInstanceType = false; ResourceType order = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, null, "AstoriaUnitTests.Stubs", "Order", false); order.CanReflectOnInstanceType = false; ResourceType region = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, null, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "Region", false /*isAbstract*/); region.CanReflectOnInstanceType = false; ResourceType address = new ResourceType( typeof(RowComplexType), ResourceTypeKind.ComplexType, null, "AstoriaUnitTests.Stubs", "Address", false); address.CanReflectOnInstanceType = false; ResourceType product = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, null, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "Product", false /*isAbstract*/); product.CanReflectOnInstanceType = false; ResourceType orderDetail = new ResourceType( typeof(RowEntityType), ResourceTypeKind.EntityType, null, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "OrderDetail", false /*isAbstract*/); orderDetail.CanReflectOnInstanceType = false; ResourceType currency = new ResourceType( typeof(RowComplexType), ResourceTypeKind.ComplexType, null, "AstoriaUnitTests.Stubs", "CurrencyAmount", false); ResourceType headquarter = new ResourceType( typeof(RowComplexType), ResourceTypeKind.ComplexType, null, "AstoriaUnitTests.Stubs", "Headquarter", false); headquarter.CanReflectOnInstanceType = false; ResourceSet customerEntitySet = new ResourceSet("Customers", customer); ResourceSet orderEntitySet = new ResourceSet("Orders", order); ResourceSet regionEntitySet = new ResourceSet("Regions", region); ResourceSet productEntitySet = new ResourceSet("Products", product); ResourceSet orderDetailEntitySet = new ResourceSet("OrderDetails", orderDetail); ResourceSet memberCustomerEntitySet = new ResourceSet("MemberCustomers", customer); ResourceSet memberOrderEntitySet = new ResourceSet("MemberOrders", order); ResourceSet memberRegionEntitySet = new ResourceSet("MemberRegions", region); ResourceSet memberProductEntitySet = new ResourceSet("MemberProducts", product); ResourceSet memberOrderDetailEntitySet = new ResourceSet("MemberOrderDetails", orderDetail); ResourceProperty keyProperty = new ResourceProperty( "ID", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int))); // populate customer properties customer.AddProperty(keyProperty); customer.AddProperty(CreateNonClrProperty("Name", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(String)))); customer.AddProperty(CreateNonClrProperty("BestFriend", ResourcePropertyKind.ResourceReference, customer)); customer.AddProperty(CreateNonClrProperty("Orders", ResourcePropertyKind.ResourceSetReference, order)); customer.AddProperty(CreateNonClrProperty("Region", ResourcePropertyKind.ResourceReference, region)); customer.AddProperty(CreateNonClrProperty("Address", ResourcePropertyKind.ComplexType, address)); customer.AddProperty(CreateNonClrProperty("GuidValue", ResourcePropertyKind.Primitive | ResourcePropertyKind.ETag, ResourceType.GetPrimitiveResourceType(typeof(Guid)))); ResourceProperty property = CreateNonClrProperty("NameAsHtml", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string))); property.MimeType = "text/html"; customer.AddProperty(property); if (OpenWebDataServiceHelper.EnableBlobServer) { customer.IsMediaLinkEntry = true; } // create Customer With Birthday and populate its properties ResourceType customerWithBirthday = new ResourceType( typeof(RowEntityTypeWithIDAsKey), ResourceTypeKind.EntityType, customer, /*baseType*/ "AstoriaUnitTests.Stubs", /*namespaceName*/ "CustomerWithBirthday", false /*isAbstract*/); customerWithBirthday.AddProperty(CreateNonClrProperty("Birthday", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(DateTime)))); customerWithBirthday.CanReflectOnInstanceType = false; // populate order properties order.AddProperty(keyProperty); order.AddProperty(CreateNonClrProperty("DollarAmount", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(double)))); order.AddProperty(CreateNonClrProperty("OrderDetails", ResourcePropertyKind.ResourceSetReference, orderDetail)); order.AddProperty(CreateNonClrProperty("CurrencyAmount", ResourcePropertyKind.ComplexType, currency)); order.AddProperty(CreateNonClrProperty("Customer", ResourcePropertyKind.ResourceReference, customer)); // populate region properties region.AddProperty(keyProperty); region.AddProperty(CreateNonClrProperty("Name", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); region.AddProperty(CreateNonClrProperty("Headquarter", ResourcePropertyKind.ComplexType, headquarter)); //populate headquarter properties headquarter.AddProperty(CreateNonClrProperty("DrivingDirections", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); headquarter.AddProperty(CreateNonClrProperty("Address", ResourcePropertyKind.ComplexType, address)); //populate address properties address.AddProperty(CreateNonClrProperty("StreetAddress", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); address.AddProperty(CreateNonClrProperty("City", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); address.AddProperty(CreateNonClrProperty("State", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); address.AddProperty(CreateNonClrProperty("PostalCode", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(string)))); // create product type and its properties product.AddProperty(keyProperty); product.AddProperty(CreateNonClrProperty("ProductName", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(String)))); product.AddProperty(CreateNonClrProperty("Discontinued", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(bool)))); product.AddProperty(CreateNonClrProperty("OrderDetails", ResourcePropertyKind.ResourceSetReference, orderDetail)); // create order detail and its properties // DEVNOTE: it's very important that ProductID and OrderID are not in alphabetical order. There are tests relying on this. orderDetail.AddProperty(CreateNonClrProperty("ProductID", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int)))); orderDetail.AddProperty(CreateNonClrProperty("OrderID", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int)))); orderDetail.AddProperty(CreateNonClrProperty("UnitPrice", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(double)))); orderDetail.AddProperty(CreateNonClrProperty("Quantity", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(short)))); //populate currency amount properties currency.AddProperty(CreateNonClrProperty("Amount", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(decimal)))); currency.AddProperty(CreateNonClrProperty("CurrencyName", ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(String)))); types.Add(customer); types.Add(customerWithBirthday); types.Add(order); types.Add(region); types.Add(address); types.Add(product); types.Add(orderDetail); types.Add(currency); types.Add(headquarter); List<ResourceSet> containers = new List<ResourceSet>(7); containers.Add(customerEntitySet); containers.Add(orderEntitySet); containers.Add(regionEntitySet); containers.Add(productEntitySet); containers.Add(orderDetailEntitySet); containers.Add(memberCustomerEntitySet); containers.Add(memberOrderEntitySet); containers.Add(memberRegionEntitySet); containers.Add(memberProductEntitySet); containers.Add(memberOrderDetailEntitySet); List<ServiceOperation> operations = new List<ServiceOperation>(1); operations.Add(new ServiceOperation("IntServiceOperation", ServiceOperationResultKind.DirectValue, ResourceType.GetPrimitiveResourceType(typeof(int)), null, "GET", null)); operations.Add(new ServiceOperation("InsertCustomer", ServiceOperationResultKind.DirectValue, customer, customerEntitySet, "POST", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))), new ServiceOperationParameter("name", ResourceType.GetPrimitiveResourceType(typeof(string))) } )); operations.Add(new ServiceOperation("GetCustomerByCity", ServiceOperationResultKind.QueryWithMultipleResults, customer, customerEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("city", ResourceType.GetPrimitiveResourceType(typeof(string))) })); operations.Add(new ServiceOperation("DoNothingOperation", ServiceOperationResultKind.Void, null, null, "POST", null)); operations.Add(new ServiceOperation("GetCustomerAddress", ServiceOperationResultKind.DirectValue, address, null, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetOrderById", ServiceOperationResultKind.DirectValue, order, orderEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetRegionByName", ServiceOperationResultKind.QueryWithMultipleResults, region, regionEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("name", ResourceType.GetPrimitiveResourceType(typeof(string))) })); operations.Add(new ServiceOperation("AddressServiceOperation", ServiceOperationResultKind.DirectValue, address, null, "GET", null)); operations.Add(new ServiceOperation("GetAllCustomersQueryable", ServiceOperationResultKind.QueryWithMultipleResults, customer, customerEntitySet, "GET", null)); operations.Add(new ServiceOperation("GetCustomerByIdQueryable", ServiceOperationResultKind.QueryWithSingleResult, customer, customerEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetAllCustomersEnumerable", ServiceOperationResultKind.Enumeration, customer, customerEntitySet, "GET", null)); operations.Add(new ServiceOperation("GetCustomerByIdDirectValue", ServiceOperationResultKind.DirectValue, customer, customerEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetAllOrdersQueryable", ServiceOperationResultKind.QueryWithMultipleResults, order, orderEntitySet, "GET", null)); operations.Add(new ServiceOperation("GetOrderByIdQueryable", ServiceOperationResultKind.QueryWithSingleResult, order, orderEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); operations.Add(new ServiceOperation("GetAllOrdersEnumerable", ServiceOperationResultKind.Enumeration, order, orderEntitySet, "GET", null)); operations.Add(new ServiceOperation("GetOrderByIdDirectValue", ServiceOperationResultKind.DirectValue, order, orderEntitySet, "GET", new ServiceOperationParameter[] { new ServiceOperationParameter("id", ResourceType.GetPrimitiveResourceType(typeof(int))) })); List<ResourceAssociationSet> associationSets = new List<ResourceAssociationSet>(); ResourceAssociationSet customer_BestFriend = new ResourceAssociationSet( "Customers_BestFriend", new ResourceAssociationSetEnd(customerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "BestFriend")), new ResourceAssociationSetEnd(customerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "BestFriend"))); associationSets.Add(customer_BestFriend); ResourceAssociationSet customer_Order = new ResourceAssociationSet( "Customers_Orders", new ResourceAssociationSetEnd(customerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Orders")), new ResourceAssociationSetEnd(orderEntitySet, order, order.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Customer"))); associationSets.Add(customer_Order); ResourceAssociationSet customer_Region = new ResourceAssociationSet( "Customers_Regions", new ResourceAssociationSetEnd(customerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Region")), new ResourceAssociationSetEnd(regionEntitySet, region, region.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Customer"))); associationSets.Add(customer_Region); ResourceAssociationSet order_OrderDetails = new ResourceAssociationSet( "Orders_OrderDetails", new ResourceAssociationSetEnd(orderEntitySet, order, order.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "OrderDetails")), new ResourceAssociationSetEnd(orderDetailEntitySet, orderDetail, null)); associationSets.Add(order_OrderDetails); ResourceAssociationSet product_OrderDetails = new ResourceAssociationSet( "Products_OrderDetails", new ResourceAssociationSetEnd(productEntitySet, product, product.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "OrderDetails")), new ResourceAssociationSetEnd(orderDetailEntitySet, orderDetail, null)); associationSets.Add(product_OrderDetails); ResourceAssociationSet memberCustomer_BestFriend = new ResourceAssociationSet( "MemberCustomers_BestFriend", new ResourceAssociationSetEnd(memberCustomerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "BestFriend")), new ResourceAssociationSetEnd(memberCustomerEntitySet, customer, null)); associationSets.Add(memberCustomer_BestFriend); ResourceAssociationSet memberCustomer_MemberOrder = new ResourceAssociationSet( "MemberCustomers_MemberOrders", new ResourceAssociationSetEnd(memberCustomerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Orders")), new ResourceAssociationSetEnd(memberOrderEntitySet, order, order.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Customer"))); associationSets.Add(memberCustomer_MemberOrder); ResourceAssociationSet memberCustomer_MemberRegion = new ResourceAssociationSet( "MemberCustomers_MemberRegions", new ResourceAssociationSetEnd(memberCustomerEntitySet, customer, customer.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Region")), new ResourceAssociationSetEnd(memberRegionEntitySet, region, region.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "Customer"))); associationSets.Add(memberCustomer_MemberRegion); ResourceAssociationSet memberOrder_MemberOrderDetails = new ResourceAssociationSet( "MemberOrder_MemberOrderDetails", new ResourceAssociationSetEnd(memberOrderEntitySet, order, order.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "OrderDetails")), new ResourceAssociationSetEnd(memberOrderDetailEntitySet, orderDetail, null)); associationSets.Add(memberOrder_MemberOrderDetails); ResourceAssociationSet memberProduct_MemberOrderDetails = new ResourceAssociationSet( "MemberProduct_MemberOrderDetails", new ResourceAssociationSetEnd(memberProductEntitySet, product, product.PropertiesDeclaredOnThisType.FirstOrDefault(p => p.Name == "OrderDetails")), new ResourceAssociationSetEnd(memberOrderDetailEntitySet, orderDetail, null)); associationSets.Add(memberProduct_MemberOrderDetails); return new CustomDataServiceProvider(containers, types, operations, associationSets, dataSourceInstance); }
public Stream GetWriteStream(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty, string etag, bool?checkETagForEquality, DataServiceOperationContext operationContext) { throw new NotImplementedException(); }
/// <summary> /// Returns whether or not the property should be included in the $metadata output. /// Navigation properties are only included when their target type is reachable from a visible set. /// Structural properties are always included. /// </summary> /// <param name="property">The property to check.</param> /// <returns>Whether the property should be included in $metadata.</returns> private bool ShouldPropertyBeIncludedInMetadata(ResourceProperty property) { Debug.Assert(property != null, "property != null"); Debug.Assert(this.ShouldCheckForPropertyVisibility, "Should only be called during metadata serialization."); if (property.TypeKind != ResourceTypeKind.EntityType) { // non-entity properties are always visible. return true; } // NOTE: For $metadata serialization we check the set of visible types to determine whether // a navigation property should be visible or not. // When ODataLib serializes a payload and looks up properties, // we don't consider visibility at all since it depends // not only on the type but also the entity set the type came from (MEST scenarios!). // ODataLib has no knowledge of entity sets so the design is for Astoria to not include // hidden navigation properties in the ODataEntry to begin with and not bother with // visibility here. // NOTE: We get here in materialization state 'Full' when we create the association types. // We get here in cache state 'Full' when delay-loading the properties. ResourceType propertyType = property.ResourceType; string typeNamespace = this.GetTypeNamespace(propertyType); HashSet<ResourceType> typesInNamespace = this.GetResourceTypesForNamespace(typeNamespace); return typesInNamespace.Contains(propertyType); }
/// <summary> /// Retrieve the end for the given resource set, type and property. /// </summary> /// <param name="resourceType">resource type for the end</param> /// <param name="resourceProperty">resource property for the end</param> /// <returns>Association type end for the given parameters</returns> internal ResourceAssociationTypeEnd GetResourceAssociationTypeEnd(ResourceType resourceType, ResourceProperty resourceProperty) { Debug.Assert(resourceType != null, "resourceType != null"); foreach (ResourceAssociationTypeEnd end in new[] { this.end1, this.end2 }) { if (end.ResourceType == resourceType && end.ResourceProperty == resourceProperty) { return end; } } return null; }
/// <summary> /// Fills in the rest of required information for navigation properties. /// </summary> /// <param name="resourceSet">Resource set to inspect.</param> /// <param name="resourceType">Resource type to inspect.</param> /// <param name="navigationProperty">Navigation property to inspect.</param> internal void PairUpNavigationProperty(ResourceSetWrapper resourceSet, ResourceType resourceType, ResourceProperty navigationProperty) { Debug.Assert(resourceSet != null, "resourceSet != null"); Debug.Assert(resourceType != null, "resourceType != null"); Debug.Assert(navigationProperty != null && navigationProperty.ResourceType.ResourceTypeKind == ResourceTypeKind.EntityType, "navigationProperty != null && navigationProperty.ResourceType.ResourceTypeKind == ResourceTypeKind.EntityType"); Debug.Assert(resourceType.TryResolvePropertiesDeclaredOnThisTypeByName(navigationProperty.Name) != null, "navigationProperty must be declared on resourceType."); string associationSetKey = resourceSet.Name + '_' + resourceType.FullName + '_' + navigationProperty.Name; // We changed the association logic on the server to create the correct navigation property for V4 to run the tests. // The association logic on server side needs to be removed. // Check the cache first; we might already have visited the partiner of this navigation property. if (this.associationSetByKeyCache.ContainsKey(associationSetKey)) { return; } ResourceAssociationSet resourceAssociationSet = this.MetadataProvider.GetResourceAssociationSet(resourceSet, resourceType, navigationProperty); if (resourceAssociationSet != null) { this.PairUpNavigationPropertyWithResourceAssociationSet(resourceAssociationSet); this.associationSetByKeyCache.Add(associationSetKey, resourceAssociationSet.Name); } }
/// <summary> /// Validates the entity and stream parameters. /// </summary> /// <param name="entity">entity instance.</param> /// <param name="streamProperty">stream info</param> protected abstract void ValidateEntity(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty);