/// <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; }
public void SelectProperties_OnSubPropertyWithTypeCastFromComplex_SelectsExpectedProperties() { // Arrange EdmComplexType subComplexType = new EdmComplexType("NS", "CnAddress", _model.Address); subComplexType.AddStructuralProperty("SubAddressProperty", EdmPrimitiveTypeKind.String); subComplexType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "CnAddressOrderNav", TargetMultiplicity = EdmMultiplicity.One, Target = _model.Order }); _model.Model.AddElement(subComplexType); string select = "Address/NS.CnAddress/SubAddressProperty"; string expand = "Address/NS.CnAddress/CnAddressOrderNav"; SelectExpandClause selectExpandClause = ParseSelectExpand(select, expand); // Act SelectExpandNode selectExpandNode = new SelectExpandNode(selectExpandClause, _model.Customer, _model.Model); // Assert: Top Level Assert.Null(selectExpandNode.SelectedStructuralProperties); Assert.Null(selectExpandNode.SelectedNavigationProperties); Assert.Null(selectExpandNode.ExpandedProperties); // Not expanded at first level Assert.NotNull(selectExpandNode.SelectedComplexProperties); var firstLevelSelected = Assert.Single(selectExpandNode.SelectedComplexProperties); Assert.Equal("Address", firstLevelSelected.Key.Name); Assert.NotNull(firstLevelSelected.Value); Assert.NotNull(firstLevelSelected.Value.SelectAndExpand); // Assert: Second Level { // use the base type to test SelectExpandNode subSelectExpandNode = new SelectExpandNode(firstLevelSelected.Value.SelectAndExpand, _model.Address, _model.Model); Assert.Null(subSelectExpandNode.SelectedStructuralProperties); Assert.Null(subSelectExpandNode.SelectedComplexProperties); Assert.Null(subSelectExpandNode.ExpandedProperties); Assert.Null(subSelectExpandNode.SelectedNavigationProperties); } { // use the sub type to test SelectExpandNode subSelectExpandNode = new SelectExpandNode(firstLevelSelected.Value.SelectAndExpand, subComplexType, _model.Model); Assert.Null(subSelectExpandNode.SelectedComplexProperties); Assert.NotNull(subSelectExpandNode.SelectedStructuralProperties); Assert.Equal("SubAddressProperty", Assert.Single(subSelectExpandNode.SelectedStructuralProperties).Name); Assert.NotNull(subSelectExpandNode.ExpandedProperties); var expandedProperty = Assert.Single(subSelectExpandNode.ExpandedProperties); Assert.Equal("CnAddressOrderNav", expandedProperty.Key.Name); Assert.NotNull(expandedProperty.Value); Assert.NotNull(expandedProperty.Value.SelectAndExpand); Assert.True(expandedProperty.Value.SelectAndExpand.AllSelected); Assert.Empty(expandedProperty.Value.SelectAndExpand.SelectedItems); } }
/// <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 SelectExpandNode CreateSelectExpandNode(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 selectExpandNode as SelectExpandNode; }