/// <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(); }
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); } }
/// <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); }