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

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

            throw new Exception(String.Format("Unexpected type encountered: '{0}'", type.FullName));
        }
Example #2
0
        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();
            }
        }
Example #3
0
        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);
        }
Example #4
0
        } // 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
Example #5
0
 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;
        }
Example #10
0
        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;
 }
Example #12
0
 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();
     }
 }
Example #15
0
        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");
        }
Example #16
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);
                        }
                    }
                }
            }
        }
Example #17
0
        /// <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;
            }
        }
Example #22
0
        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);
        }
Example #23
0
        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);
            }
        }
Example #26
0
        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);
        }
Example #27
0
        /// <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;
        }
Example #28
0
        /// <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;
        }
Example #32
0
 public Uri GetReadStreamUri(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty, DataServiceOperationContext operationContext)
 {
     return(null);
 }
Example #33
0
        } // 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
Example #34
0
        /// <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;
        }
Example #35
0
            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.");
                                        }
                                    }
                                }
                            });
                    });
            }
Example #36
0
 public string GetStreamContentType(object entity, Microsoft.OData.Service.Providers.ResourceProperty streamProperty, DataServiceOperationContext operationContext)
 {
     return("text/plain");
 }
Example #37
0
 public void GetResourceAssociationSet(DSP.ResourceSet resourceSet, DSP.ResourceType resourceType, DSP.ResourceProperty resourceProperty)
 {
     Add("GetResourceAssociationSet", Serialize(resourceSet), Serialize(resourceType), Serialize(resourceProperty));
 }
Example #38
0
 private string Serialize(DSP.ResourceProperty streamProperty)
 {
     return(streamProperty == null ? "null ResourceProperty" : streamProperty.Name);
 }
Example #39
0
 /// <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));
 }
Example #40
0
 /// <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));
 }
Example #41
0
 /// <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);
 }
Example #42
0
 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;
 }
Example #44
0
 private string Serialize(DSP.ResourceProperty property)
 {
     return(property.Name);
 }
Example #45
0
        /// <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;
        }
Example #46
0
 public void GetPropertyValue(object target, DSP.ResourceProperty resourceProperty)
 {
     Add("GetPropertyValue", Parent.Serialize(target), Serialize(resourceProperty));
 }
Example #47
0
 /// <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);
        }
Example #50
0
        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;
        }
Example #51
0
 public void AddLazyProperty(DSP.ResourceProperty property)
 {
     this.lazyProperties.Add(property);
 }
Example #52
0
 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);
        }
Example #56
0
 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);
            }
        }
Example #60
0
 /// <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);