/// <summary>
		/// Creates the <see cref="ODataEntry"/> to be written while writing this entity.
		/// </summary>
		/// <param name="selectExpandNode">The <see cref="SelectExpandNode"/> describing the response graph.</param>
		/// <param name="entityInstanceContext">The context for the entity instance being written.</param>
		/// <returns>The created <see cref="ODataEntry"/>.</returns>
		public virtual async Task<ODataEntry> CreateEntryAsync(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)
		{
			if (selectExpandNode == null)
			{
				throw Error.ArgumentNull("selectExpandNode");
			}
			if (entityInstanceContext == null)
			{
				throw Error.ArgumentNull("entityInstanceContext");
			}

			string typeName = entityInstanceContext.EntityType.FullName();

			ODataEntry entry = new ODataEntry
			{
				TypeName = typeName,
				Properties = await CreateStructuralPropertyBagAsync(selectExpandNode.SelectedStructuralProperties, entityInstanceContext),
			};

			// Try to add the dynamic properties if the entity type is open.
			if ((entityInstanceContext.EntityType.IsOpen && selectExpandNode.SelectAllDynamicProperties) ||
				(entityInstanceContext.EntityType.IsOpen && selectExpandNode.SelectedDynamicProperties.Any()))
			{
				IEdmTypeReference entityTypeReference =
					entityInstanceContext.EntityType.ToEdmTypeReference(isNullable: false);
				List<ODataProperty> dynamicProperties = await AppendDynamicProperties(entityInstanceContext.EdmObject,
					(IEdmStructuredTypeReference)entityTypeReference,
					entityInstanceContext.SerializerContext,
					entry.Properties.ToList(),
					selectExpandNode.SelectedDynamicProperties.ToArray());

				if (dynamicProperties != null)
				{
					entry.Properties = entry.Properties.Concat(dynamicProperties);
				}
			}

			IEnumerable<ODataAction> actions = await CreateODataActionsAsync(selectExpandNode.SelectedActions, entityInstanceContext);
			foreach (ODataAction action in actions)
			{
				entry.AddAction(action);
			}

			IEdmEntityType pathType = GetODataPathType(entityInstanceContext.SerializerContext);
			AddTypeNameAnnotationAsNeeded(entry, pathType, entityInstanceContext.SerializerContext.MetadataLevel);

			if (entityInstanceContext.NavigationSource != null)
			{
				if (!(entityInstanceContext.NavigationSource is IEdmContainedEntitySet))
				{
					IEdmModel model = entityInstanceContext.SerializerContext.Model;
					NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(entityInstanceContext.NavigationSource);
					EntitySelfLinks selfLinks = linkBuilder.BuildEntitySelfLinks(entityInstanceContext, entityInstanceContext.SerializerContext.MetadataLevel);

					if (selfLinks.IdLink != null)
					{
						entry.Id = selfLinks.IdLink;
					}

					if (selfLinks.ReadLink != null)
					{
						entry.ReadLink = selfLinks.ReadLink;
					}

					if (selfLinks.EditLink != null)
					{
						entry.EditLink = selfLinks.EditLink;
					}
				}

				string etag = await CreateETagAsync(entityInstanceContext);
				if (etag != null)
				{
					entry.ETag = etag;
				}
			}

			return entry;
		}
		/// <summary>
		/// Creates the <see cref="SelectExpandNode"/> that describes the set of properties and actions to select and expand while writing this entity.
		/// </summary>
		/// <param name="entityInstanceContext">Contains the entity instance being written and the context.</param>
		/// <returns>
		/// The <see cref="SelectExpandNode"/> that describes the set of properties and actions to select and expand while writing this entity.
		/// </returns>
		public virtual Task<SelectExpandNode> CreateSelectExpandNodeAsync(EntityInstanceContext entityInstanceContext)
		{
			if (entityInstanceContext == null)
			{
				throw Error.ArgumentNull("entityInstanceContext");
			}

			ODataSerializerContext writeContext = entityInstanceContext.SerializerContext;
			IEdmEntityType entityType = entityInstanceContext.EntityType;

			object selectExpandNode;
			Tuple<SelectExpandClause, IEdmEntityType> key = Tuple.Create(writeContext.SelectExpandClause, entityType);
			if (!writeContext.Items.TryGetValue(key, out selectExpandNode))
			{
				// cache the selectExpandNode so that if we are writing a feed we don't have to construct it again.
				selectExpandNode = new SelectExpandNode(writeContext.SelectExpandClause, entityType, writeContext.Model);
				writeContext.Items[key] = selectExpandNode;
			}
			return Task.FromResult(selectExpandNode as SelectExpandNode);
		}
		private async Task WriteNodeAsync(ODataWriter writer, ODataEntry entry, SelectExpandNode selectExpandNode,
			EntityInstanceContext entityInstanceContext)
		{

			//(entityInstanceContext.EdmModel as ISelectExpandWrapper<string>)
			writer.WriteStart(entry);
			await WriteNavigationLinksAsync(selectExpandNode.SelectedNavigationProperties, entityInstanceContext, writer);
			await WriteExpandedNavigationPropertiesAsync(selectExpandNode.ExpandedNavigationProperties, entityInstanceContext, writer);
			writer.WriteEnd();
		}
示例#4
0
        public virtual void AppendDynamicProperties(ODataResource resource, SelectExpandNode selectExpandNode,
                                                    ResourceContext resourceContext)
        {
            Contract.Assert(resource != null);
            Contract.Assert(selectExpandNode != null);
            Contract.Assert(resourceContext != null);

            if (!resourceContext.StructuredType.IsOpen || // non-open type
                (!selectExpandNode.SelectAllDynamicProperties && !selectExpandNode.SelectedDynamicProperties.Any()))
            {
                return;
            }

            bool nullDynamicPropertyEnabled = false;

            if (resourceContext.Request != null)
            {
                // TODO:

                /*
                 * HttpConfiguration configuration = resourceContext.Request.GetConfiguration();
                 * if (configuration != null)
                 * {
                 *  nullDynamicPropertyEnabled = configuration.HasEnabledNullDynamicProperty();
                 * }*/
            }

            IEdmStructuredType   structuredType   = resourceContext.StructuredType;
            IEdmStructuredObject structuredObject = resourceContext.EdmObject;
            object value;
            IDelta delta = structuredObject as IDelta;

            if (delta == null)
            {
                PropertyInfo dynamicPropertyInfo = EdmLibHelpers.GetDynamicPropertyDictionary(structuredType,
                                                                                              resourceContext.EdmModel);
                if (dynamicPropertyInfo == null || structuredObject == null ||
                    !structuredObject.TryGetPropertyValue(dynamicPropertyInfo.Name, out value) || value == null)
                {
                    return;
                }
            }
            else
            {
                value = ((EdmStructuredObject)structuredObject).TryGetDynamicProperties();
            }

            IDictionary <string, object> dynamicPropertyDictionary = (IDictionary <string, object>)value;

            // Build a HashSet to store the declared property names.
            // It is used to make sure the dynamic property name is different from all declared property names.
            HashSet <string>     declaredPropertyNameSet = new HashSet <string>(resource.Properties.Select(p => p.Name));
            List <ODataProperty> dynamicProperties       = new List <ODataProperty>();
            IEnumerable <KeyValuePair <string, object> > dynamicPropertiesToSelect =
                dynamicPropertyDictionary.Where(
                    x =>
                    !selectExpandNode.SelectedDynamicProperties.Any() ||
                    selectExpandNode.SelectedDynamicProperties.Contains(x.Key));

            foreach (KeyValuePair <string, object> dynamicProperty in dynamicPropertiesToSelect)
            {
                if (String.IsNullOrEmpty(dynamicProperty.Key))
                {
                    continue;
                }

                if (dynamicProperty.Value == null)
                {
                    if (nullDynamicPropertyEnabled)
                    {
                        dynamicProperties.Add(new ODataProperty
                        {
                            Name  = dynamicProperty.Key,
                            Value = new ODataNullValue()
                        });
                    }

                    continue;
                }

                if (declaredPropertyNameSet.Contains(dynamicProperty.Key))
                {
                    throw Error.InvalidOperation(SRResources.DynamicPropertyNameAlreadyUsedAsDeclaredPropertyName,
                                                 dynamicProperty.Key, structuredType.FullTypeName());
                }

                IEdmTypeReference edmTypeReference = resourceContext.SerializerContext.GetEdmType(dynamicProperty.Value,
                                                                                                  dynamicProperty.Value.GetType());
                if (edmTypeReference == null)
                {
                    throw Error.NotSupported(SRResources.TypeOfDynamicPropertyNotSupported,
                                             dynamicProperty.Value.GetType().FullName, dynamicProperty.Key);
                }

                if (edmTypeReference.IsStructured() ||
                    (edmTypeReference.IsCollection() && edmTypeReference.AsCollection().ElementType().IsStructured()))
                {
                    if (resourceContext.DynamicComplexProperties == null)
                    {
                        resourceContext.DynamicComplexProperties = new ConcurrentDictionary <string, object>();
                    }

                    resourceContext.DynamicComplexProperties.Add(dynamicProperty);
                }
                else
                {
                    ODataEdmTypeSerializer propertySerializer = SerializerProvider.GetEdmTypeSerializer(resourceContext.Context, edmTypeReference);
                    if (propertySerializer == null)
                    {
                        throw Error.NotSupported(SRResources.DynamicPropertyCannotBeSerialized, dynamicProperty.Key,
                                                 edmTypeReference.FullName());
                    }

                    dynamicProperties.Add(propertySerializer.CreateProperty(
                                              dynamicProperty.Value, edmTypeReference, dynamicProperty.Key, resourceContext.SerializerContext));
                }
            }

            if (dynamicProperties.Any())
            {
                resource.Properties = resource.Properties.Concat(dynamicProperties);
            }
        }
示例#5
0
        /// <summary>
        /// Creates the <see cref="ODataResource"/> to be written while writing this resource.
        /// </summary>
        /// <param name="selectExpandNode">The <see cref="SelectExpandNode"/> describing the response graph.</param>
        /// <param name="resourceContext">The context for the resource instance being written.</param>
        /// <returns>The created <see cref="ODataResource"/>.</returns>
        public virtual ODataResource CreateResource(SelectExpandNode selectExpandNode, ResourceContext resourceContext)
        {
            if (selectExpandNode == null)
            {
                throw Error.ArgumentNull("selectExpandNode");
            }

            if (resourceContext == null)
            {
                throw Error.ArgumentNull("resourceContext");
            }

            string typeName = resourceContext.StructuredType.FullTypeName();

            ODataResource resource = new ODataResource
            {
                TypeName   = typeName,
                Properties = CreateStructuralPropertyBag(selectExpandNode.SelectedStructuralProperties, resourceContext),
            };

            // Try to add the dynamic properties if the structural type is open.
            AppendDynamicProperties(resource, selectExpandNode, resourceContext);

            IEnumerable <ODataAction> actions = CreateODataActions(selectExpandNode.SelectedActions, resourceContext);

            foreach (ODataAction action in actions)
            {
                resource.AddAction(action);
            }

            IEnumerable <ODataFunction> functions = CreateODataFunctions(selectExpandNode.SelectedFunctions, resourceContext);

            foreach (ODataFunction function in functions)
            {
                resource.AddFunction(function);
            }

            IEdmStructuredType pathType = GetODataPathType(resourceContext.SerializerContext);

            if (resourceContext.StructuredType.TypeKind == EdmTypeKind.Complex)
            {
                AddTypeNameAnnotationAsNeededForComplex(resource, resourceContext.SerializerContext.MetadataLevel);
            }
            else
            {
                AddTypeNameAnnotationAsNeeded(resource, pathType, resourceContext.SerializerContext.MetadataLevel);
            }

            if (resourceContext.StructuredType.TypeKind == EdmTypeKind.Entity && resourceContext.NavigationSource != null)
            {
                if (!(resourceContext.NavigationSource is IEdmContainedEntitySet))
                {
                    IEdmModel model = resourceContext.SerializerContext.Model;
                    NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(resourceContext.NavigationSource);
                    EntitySelfLinks selfLinks = linkBuilder.BuildEntitySelfLinks(resourceContext, resourceContext.SerializerContext.MetadataLevel);

                    if (selfLinks.IdLink != null)
                    {
                        resource.Id = selfLinks.IdLink;
                    }

                    if (selfLinks.ReadLink != null)
                    {
                        resource.ReadLink = selfLinks.ReadLink;
                    }

                    if (selfLinks.EditLink != null)
                    {
                        resource.EditLink = selfLinks.EditLink;
                    }
                }

                string etag = CreateETag(resourceContext);
                if (etag != null)
                {
                    resource.ETag = etag;
                }
            }

            return(resource);
        }
        /// <summary>
        /// Creates the <see cref="ODataEntry"/> to be written while writing this entity.
        /// </summary>
        /// <param name="selectExpandNode">The <see cref="SelectExpandNode"/> describing the response graph.</param>
        /// <param name="entityInstanceContext">The context for the entity instance being written.</param>
        /// <returns>The created <see cref="ODataEntry"/>.</returns>
        public virtual ODataEntry CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)
        {
            if (selectExpandNode == null)
            {
                throw Error.ArgumentNull("selectExpandNode");
            }
            if (entityInstanceContext == null)
            {
                throw Error.ArgumentNull("entityInstanceContext");
            }

            string typeName = entityInstanceContext.EntityType.FullName();

            ODataEntry entry = new ODataEntry
            {
                TypeName   = typeName,
                Properties = CreateStructuralPropertyBag(selectExpandNode.SelectedStructuralProperties, entityInstanceContext),
            };

            // Try to add the dynamic properties if the entity type is open.
            if ((entityInstanceContext.EntityType.IsOpen && selectExpandNode.SelectAllDynamicProperties) ||
                (entityInstanceContext.EntityType.IsOpen && selectExpandNode.SelectedDynamicProperties.Any()))
            {
                IEdmTypeReference entityTypeReference =
                    entityInstanceContext.EntityType.ToEdmTypeReference(isNullable: false);
                List <ODataProperty> dynamicProperties = AppendDynamicProperties(entityInstanceContext.EdmObject,
                                                                                 (IEdmStructuredTypeReference)entityTypeReference,
                                                                                 entityInstanceContext.SerializerContext,
                                                                                 entry.Properties.ToList(),
                                                                                 selectExpandNode.SelectedDynamicProperties.ToArray());

                if (dynamicProperties != null)
                {
                    entry.Properties = entry.Properties.Concat(dynamicProperties);
                }
            }

            IEnumerable <ODataAction> actions = CreateODataActions(selectExpandNode.SelectedActions, entityInstanceContext);

            foreach (ODataAction action in actions)
            {
                entry.AddAction(action);
            }

            IEdmEntityType pathType = GetODataPathType(entityInstanceContext.SerializerContext);

            AddTypeNameAnnotationAsNeeded(entry, pathType, entityInstanceContext.SerializerContext.MetadataLevel);

            if (entityInstanceContext.NavigationSource != null)
            {
                if (!(entityInstanceContext.NavigationSource is IEdmContainedEntitySet))
                {
                    IEdmModel model = entityInstanceContext.SerializerContext.Model;
                    NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(entityInstanceContext.NavigationSource);
                    EntitySelfLinks selfLinks = linkBuilder.BuildEntitySelfLinks(entityInstanceContext, entityInstanceContext.SerializerContext.MetadataLevel);

                    if (selfLinks.IdLink != null)
                    {
                        entry.Id = selfLinks.IdLink;
                    }

                    if (selfLinks.ReadLink != null)
                    {
                        entry.ReadLink = selfLinks.ReadLink;
                    }

                    if (selfLinks.EditLink != null)
                    {
                        entry.EditLink = selfLinks.EditLink;
                    }
                }

                string etag = CreateETag(entityInstanceContext);
                if (etag != null)
                {
                    entry.ETag = etag;
                }
            }

            return(entry);
        }