public override void WriteStart(DataServiceODataWriterNavigationLinkArgs args) { var current = new CustomInstanceAnnotationsDescriptor { TypeOfAnnotatedItem = typeof(ODataNavigationLink) }; writtenItemsStack.Push(current); base.WriteStart(args); }
public override void WriteEnd(DataServiceODataWriterNavigationLinkArgs args) { if (WriteLinkEnd.Value != null) { if (WriteLinkEnd.Value(args)) { return; } } base.WriteEnd(args); }
private void WriteNavigationProperties(IExpandedResult expanded, EntityToSerialize entityToSerialize, bool resourceInstanceInFeed, IEnumerable <ProjectionNode> projectionNodesForCurrentResourceType) { Debug.Assert(entityToSerialize != null, "entityToSerialize != null"); Debug.Assert( projectionNodesForCurrentResourceType == null || projectionNodesForCurrentResourceType.All(projectionNode => projectionNode.TargetResourceType.IsAssignableFrom(entityToSerialize.ResourceType)), "The projection nodes must be filtered to the current resource type only."); IEnumerable <ResourceProperty> navProperties = projectionNodesForCurrentResourceType == null ? this.Provider.GetResourceSerializableProperties(this.CurrentContainer, entityToSerialize.ResourceType).Where(p => p.TypeKind == ResourceTypeKind.EntityType) : projectionNodesForCurrentResourceType.Where(p => p.Property != null && p.Property.TypeKind == ResourceTypeKind.EntityType).Select(p1 => p1.Property); foreach (ResourceProperty property in navProperties) { ResourcePropertyInfo navProperty = this.GetNavigationPropertyInfo(expanded, entityToSerialize.Entity, entityToSerialize.ResourceType, property); ODataNavigationLink navLink = this.GetNavigationLink(entityToSerialize, navProperty.Property); // WCF Data Services show performance degradation with JsonLight when entities have > 25 Navgations on writing entries // DEVNOTE: for performance reasons, if the link has no content due to the metadata level, and is not expanded // then don't tell ODataLib about it at all. if (navLink.Url == null && navLink.AssociationLinkUrl == null && !navProperty.Expand) { continue; } var linkArgs = new DataServiceODataWriterNavigationLinkArgs(navLink, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(linkArgs); if (navProperty.Expand) { object navPropertyValue = navProperty.Value; IExpandedResult navPropertyExpandedResult = navPropertyValue as IExpandedResult; object expandedPropertyValue = navPropertyExpandedResult != null? GetExpandedElement(navPropertyExpandedResult) : navPropertyValue; bool needPop = this.PushSegmentForProperty(navProperty.Property, entityToSerialize.ResourceType, navProperty.ExpandedNode); // if this.CurrentContainer is null, the target set of the navigation property is hidden. if (this.CurrentContainer != null) { if (navProperty.Property.Kind == ResourcePropertyKind.ResourceSetReference) { IEnumerable enumerable; bool collection = WebUtil.IsElementIEnumerable(expandedPropertyValue, out enumerable); Debug.Assert(collection, "metadata loading must have ensured that navigation set properties must implement IEnumerable"); QueryResultInfo queryResults = new QueryResultInfo(enumerable); try { queryResults.MoveNext(); Func <Uri> getNavPropertyRelativeUri = () => RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.RelativeEditLink, navLink.Name); Func <Uri> getNavPropertyAbsoluteUri = () => RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.AbsoluteEditLink, navLink.Name); this.WriteFeedElements(navPropertyExpandedResult, queryResults, navProperty.Property.ResourceType, navLink.Name, getNavPropertyRelativeUri, getNavPropertyAbsoluteUri, false); } finally { // After the navigation property is completely serialized, dispose the property value. WebUtil.Dispose(queryResults); } } else if (WebUtil.IsNullValue(expandedPropertyValue)) { // Write a null reference navigation property var entryArgs = new DataServiceODataWriterEntryArgs(null, null, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(entryArgs); this.dataServicesODataWriter.WriteEnd(entryArgs); } else { this.WriteEntry(navPropertyExpandedResult, expandedPropertyValue, resourceInstanceInFeed, navProperty.Property.ResourceType); } } this.PopSegmentName(needPop); } this.dataServicesODataWriter.WriteEnd(linkArgs); // end of navigation property } }
private void WriteNavigationProperties(IExpandedResult expanded, EntityToSerialize entityToSerialize, bool resourceInstanceInFeed, IEnumerable<ProjectionNode> projectionNodesForCurrentResourceType) { Debug.Assert(entityToSerialize != null, "entityToSerialize != null"); Debug.Assert( projectionNodesForCurrentResourceType == null || projectionNodesForCurrentResourceType.All(projectionNode => projectionNode.TargetResourceType.IsAssignableFrom(entityToSerialize.ResourceType)), "The projection nodes must be filtered to the current resource type only."); IEnumerable<ResourceProperty> navProperties = projectionNodesForCurrentResourceType == null ? this.Provider.GetResourceSerializableProperties(this.CurrentContainer, entityToSerialize.ResourceType).Where(p => p.TypeKind == ResourceTypeKind.EntityType) : projectionNodesForCurrentResourceType.Where(p => p.Property != null && p.Property.TypeKind == ResourceTypeKind.EntityType).Select(p1 => p1.Property); foreach (ResourceProperty property in navProperties) { ResourcePropertyInfo navProperty = this.GetNavigationPropertyInfo(expanded, entityToSerialize.Entity, entityToSerialize.ResourceType, property); ODataNavigationLink navLink = this.GetNavigationLink(entityToSerialize, navProperty.Property); // WCF Data Services show performance degradation with JsonLight when entities have > 25 Navgations on writing entries // DEVNOTE: for performance reasons, if the link has no content due to the metadata level, and is not expanded // then don't tell ODataLib about it at all. if (navLink.Url == null && navLink.AssociationLinkUrl == null && !navProperty.Expand) { continue; } var linkArgs = new DataServiceODataWriterNavigationLinkArgs(navLink, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(linkArgs); if (navProperty.Expand) { object navPropertyValue = navProperty.Value; IExpandedResult navPropertyExpandedResult = navPropertyValue as IExpandedResult; object expandedPropertyValue = navPropertyExpandedResult != null ? GetExpandedElement(navPropertyExpandedResult) : navPropertyValue; bool needPop = this.PushSegmentForProperty(navProperty.Property, entityToSerialize.ResourceType, navProperty.ExpandedNode); // if this.CurrentContainer is null, the target set of the navigation property is hidden. if (this.CurrentContainer != null) { if (navProperty.Property.Kind == ResourcePropertyKind.ResourceSetReference) { IEnumerable enumerable; bool collection = WebUtil.IsElementIEnumerable(expandedPropertyValue, out enumerable); Debug.Assert(collection, "metadata loading must have ensured that navigation set properties must implement IEnumerable"); QueryResultInfo queryResults = new QueryResultInfo(enumerable); try { queryResults.MoveNext(); Func<Uri> getNavPropertyRelativeUri = () => RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.RelativeEditLink, navLink.Name); Func<Uri> getNavPropertyAbsoluteUri = () => RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.AbsoluteEditLink, navLink.Name); this.WriteFeedElements(navPropertyExpandedResult, queryResults, navProperty.Property.ResourceType, navLink.Name, getNavPropertyRelativeUri, getNavPropertyAbsoluteUri, false); } finally { // After the navigation property is completely serialized, dispose the property value. WebUtil.Dispose(queryResults); } } else if (WebUtil.IsNullValue(expandedPropertyValue)) { // Write a null reference navigation property var entryArgs = new DataServiceODataWriterEntryArgs(null, null, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(entryArgs); this.dataServicesODataWriter.WriteEnd(entryArgs); } else { this.WriteEntry(navPropertyExpandedResult, expandedPropertyValue, resourceInstanceInFeed, navProperty.Property.ResourceType); } } this.PopSegmentName(needPop); } this.dataServicesODataWriter.WriteEnd(linkArgs); // end of navigation property } }