private void WriteFeed(object graph, ODataWriter writer, ODataSerializerContext writeContext) { ODataSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(_edmCollectionType.ElementType()); if (entrySerializer == null) { throw Error.NotSupported(SRResources.TypeCannotBeSerialized, _edmCollectionType.ElementType(), typeof(ODataMediaTypeFormatter).Name); } Contract.Assert(entrySerializer.ODataPayloadKind == ODataPayloadKind.Entry); IEnumerable enumerable = graph as IEnumerable; // Data to serialize if (enumerable != null) { ODataFeed feed = new ODataFeed(); if (writeContext.EntitySet != null) { IEntitySetLinkBuilder linkBuilder = SerializerProvider.EdmModel.GetEntitySetLinkBuilder(writeContext.EntitySet); Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(new FeedContext(writeContext.EntitySet, writeContext.UrlHelper, graph)); if (feedSelfLink != null) { feed.SetAnnotation(new AtomFeedMetadata() { SelfLink = new AtomLinkMetadata() { Relation = SelfLinkRelation, Href = feedSelfLink } }); } } // TODO: Bug 467590: remove the hardcoded feed id. Get support for it from the model builder ? feed.Id = FeedNamespace + _edmCollectionType.FullName(); // If we have more OData format specific information apply it now. ODataResult odataFeedAnnotations = graph as ODataResult; if (odataFeedAnnotations != null) { feed.Count = odataFeedAnnotations.Count; feed.NextPageLink = odataFeedAnnotations.NextPageLink; } writer.WriteStart(feed); foreach (object entry in enumerable) { entrySerializer.WriteObjectInline(entry, writer, writeContext); } writer.WriteEnd(); } }
/// <summary> /// Create the <see cref="ODataFeed"/> to be written for the given feed instance. /// </summary> /// <param name="feedInstance">The instance representing the feed being written.</param> /// <param name="writeContext">The serializer context.</param> /// <returns>The created <see cref="ODataFeed"/> object.</returns> public virtual ODataFeed CreateODataFeed(IEnumerable feedInstance, ODataSerializerContext writeContext) { ODataFeed feed = new ODataFeed(); if (writeContext.EntitySet != null) { IEdmModel model = writeContext.Model; EntitySetLinkBuilderAnnotation linkBuilder = model.GetEntitySetLinkBuilder(writeContext.EntitySet); FeedContext feedContext = new FeedContext { Request = writeContext.Request, EntitySet = writeContext.EntitySet, Url = writeContext.Url, FeedInstance = feedInstance }; Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(feedContext); if (feedSelfLink != null) { feed.SetAnnotation(new AtomFeedMetadata() { SelfLink = new AtomLinkMetadata() { Relation = "self", Href = feedSelfLink } }); } } // TODO: Bug 467590: remove the hardcoded feed id. Get support for it from the model builder ? feed.Id = "http://schemas.datacontract.org/2004/07/" + EntityCollectionType.FullName(); // If we have more OData format specific information apply it now. PageResult odataFeedAnnotations = feedInstance as PageResult; if (odataFeedAnnotations != null) { feed.Count = odataFeedAnnotations.Count; feed.NextPageLink = odataFeedAnnotations.NextPageLink; } else if (writeContext.Request != null) { feed.NextPageLink = writeContext.Request.GetNextPageLink(); long?inlineCount = writeContext.Request.GetInlineCount(); if (inlineCount.HasValue) { feed.Count = inlineCount.Value; } } return(feed); }
private static void AddFeedMetadata(EntitySetInstance payloadElement, ODataFeed feed) { AtomFeedMetadata metadata = CreateFeedMetadata(payloadElement.Annotations.OfType <XmlTreeAnnotation>(), feed); // Fix up metadata for baselining metadata = metadata.Fixup(); if (metadata != null) { feed.SetAnnotation <AtomFeedMetadata>(metadata); } }
public static MaterializerFeed CreateFeed(ODataFeed feed, IEnumerable <ODataEntry> entries) { if (entries == null) { entries = Enumerable.Empty <ODataEntry>(); } else { feed.SetAnnotation <IEnumerable <ODataEntry> >(entries); } return(new MaterializerFeed(feed, entries)); }
public static AtomFeedMetadata Atom(this ODataFeed feed) { ExceptionUtils.CheckArgumentNotNull <ODataFeed>(feed, "feed"); AtomFeedMetadata annotation = feed.GetAnnotation <AtomFeedMetadata>(); if (annotation == null) { annotation = new AtomFeedMetadata(); feed.SetAnnotation <AtomFeedMetadata>(annotation); } return(annotation); }
/// <summary> /// Creates the materializer feed. /// </summary> /// <param name="feed">The feed.</param> /// <param name="entries">The entries.</param> /// <returns>The materializer feed.</returns> public static MaterializerFeed CreateFeed(ODataFeed feed, IEnumerable <ODataEntry> entries) { Debug.Assert(feed.GetAnnotation <IEnumerable <ODataEntry> >() == null, "Feed state has already been created."); if (entries == null) { entries = Enumerable.Empty <ODataEntry>(); } else { feed.SetAnnotation <IEnumerable <ODataEntry> >(entries); } return(new MaterializerFeed(feed, entries)); }
public static AtomFeedMetadata Atom(this ODataFeed feed) { ExceptionUtils.CheckArgumentNotNull(feed, "feed"); AtomFeedMetadata feedMetadata = feed.GetAnnotation <AtomFeedMetadata>(); if (feedMetadata == null) { feedMetadata = new AtomFeedMetadata(); feed.SetAnnotation(feedMetadata); } return(feedMetadata); }
protected override bool ReadAtFeedStartImplementation() { if ((this.atomEntryAndFeedDeserializer.XmlReader.NodeType == XmlNodeType.EndElement) || this.CurrentFeedState.FeedElementEmpty) { IODataAtomReaderFeedState currentFeedState = this.CurrentFeedState; ODataFeed currentFeed = base.CurrentFeed; if (this.atomInputContext.MessageReaderSettings.EnableAtomMetadataReading) { currentFeed.SetAnnotation <AtomFeedMetadata>(currentFeedState.AtomFeedMetadata); } this.ReplaceScope(ODataReaderState.FeedEnd); } else { this.ReadEntryStart(); } return(true); }
private void Read(Lazy <ODataReader> lazyReader) { foreach (var state in this.expectedStates) { lazyReader.Value.Read(); ExceptionUtilities.Assert(lazyReader.Value.State == state, "Expected %1, Found %2", state, lazyReader.Value.State); switch (state) { case ODataReaderState.FeedStart: if (readItems.Count > 0) { ODataNavigationLink navLink = (ODataNavigationLink)readItems.Peek(); var annotation = navLink.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>(); if (annotation == null) { annotation = new ODataNavigationLinkExpandedItemObjectModelAnnotation(); navLink.SetAnnotation(annotation); } annotation.ExpandedItem = lazyReader.Value.Item; } readItems.Push(lazyReader.Value.Item); break; case ODataReaderState.EntryStart: var currentEntry = (ODataEntry)lazyReader.Value.Item; if (readItems.Count > 0) { ODataFeed feed = readItems.Peek() as ODataFeed; if (feed != null) { var annotation = feed.GetAnnotation <ODataFeedEntriesObjectModelAnnotation>(); if (annotation == null) { annotation = new ODataFeedEntriesObjectModelAnnotation(); feed.SetAnnotation(annotation); } annotation.Add((ODataEntry)lazyReader.Value.Item); } else { ODataNavigationLink navLink = (ODataNavigationLink)readItems.Peek(); var annotation = navLink.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>(); if (annotation == null) { annotation = new ODataNavigationLinkExpandedItemObjectModelAnnotation(); navLink.SetAnnotation(annotation); } annotation.ExpandedItem = currentEntry; } } readItems.Push(currentEntry); break; case ODataReaderState.NavigationLinkStart: ODataEntry entry = (ODataEntry)readItems.Peek(); var navLinksAnnotation = entry.GetAnnotation <ODataEntryNavigationLinksObjectModelAnnotation>(); if (navLinksAnnotation == null) { navLinksAnnotation = new ODataEntryNavigationLinksObjectModelAnnotation(); entry.SetAnnotation(navLinksAnnotation); } navLinksAnnotation.Add((ODataNavigationLink)lazyReader.Value.Item, entry.Properties.Count() + navLinksAnnotation.Count); readItems.Push(lazyReader.Value.Item); break; case ODataReaderState.EntryEnd: case ODataReaderState.FeedEnd: case ODataReaderState.NavigationLinkEnd: if (readItems.Count() > 1) { readItems.Pop(); } break; } } this.expectedStates.Clear(); }
/// <summary> /// Writes the feed element for the atom payload. /// </summary> /// <param name="expanded">Expanded properties for the result.</param> /// <param name="elements">Collection of entries in the feed element.</param> /// <param name="expectedType">ExpectedType of the elements in the collection.</param> /// <param name="title">Title of the feed element.</param> /// <param name="getRelativeUri">Callback to get the relative uri of the feed.</param> /// <param name="getAbsoluteUri">Callback to get the absolute uri of the feed.</param> /// <param name="topLevel">True if the feed is the top level feed, otherwise false for the inner expanded feed.</param> private void WriteFeedElements( IExpandedResult expanded, QueryResultInfo elements, ResourceType expectedType, string title, Func <Uri> getRelativeUri, Func <Uri> getAbsoluteUri, bool topLevel) { Debug.Assert(elements != null, "elements != null"); Debug.Assert(expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType, "expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType"); Debug.Assert(!string.IsNullOrEmpty(title), "!string.IsNullOrEmpty(title)"); ODataFeed feed = new ODataFeed(); feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = this.CurrentContainer.Name, NavigationSourceEntityTypeName = this.CurrentContainer.ResourceType.FullName, ExpectedTypeName = expectedType.FullName }); // Write the other elements for the feed this.PayloadMetadataPropertyManager.SetId(feed, () => getAbsoluteUri()); #pragma warning disable 618 if (this.contentFormat == ODataFormat.Atom) #pragma warning restore 618 { // Create the atom feed metadata and set the self link and title value. AtomFeedMetadata feedMetadata = new AtomFeedMetadata(); feed.SetAnnotation(feedMetadata); feedMetadata.Title = new AtomTextConstruct { Text = title }; feedMetadata.SelfLink = new AtomLinkMetadata { Href = getRelativeUri(), Title = title }; } // support for $count // in ATOM we write it at the beginning (we always have) // in JSON for backward compatiblity reasons we write it at the end, so we must not fill it here. if (topLevel && this.RequestDescription.CountOption == RequestQueryCountOption.CountQuery) { feed.Count = this.RequestDescription.CountValue; } var feedArgs = elements.GetDataServiceODataWriterFeedArgs(feed, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(feedArgs); object lastObject = null; IExpandedResult lastExpandedSkipToken = null; while (elements.HasMoved) { object o = elements.Current; IExpandedResult skipToken = this.GetSkipToken(expanded); if (o != null) { IExpandedResult expandedO = o as IExpandedResult; if (expandedO != null) { expanded = expandedO; o = GetExpandedElement(expanded); skipToken = this.GetSkipToken(expanded); } this.WriteEntry(expanded, o, true /*resourceInstanceInFeed*/, expectedType); } elements.MoveNext(); lastObject = o; lastExpandedSkipToken = skipToken; } // After looping through the objects in the sequence, decide if we need to write the next // page link and if yes, write it by invoking the delegate if (this.NeedNextPageLink(elements)) { this.PayloadMetadataPropertyManager.SetNextPageLink( feed, this.AbsoluteServiceUri, this.GetNextLinkUri(lastObject, lastExpandedSkipToken, getAbsoluteUri())); } this.dataServicesODataWriter.WriteEnd(feedArgs); #if ASTORIA_FF_CALLBACKS this.Service.InternalOnWriteFeed(feed); #endif }
internal static ODataItem ReadEntryOrFeed(ODataReader odataReader, ODataDeserializerContext readContext) { ODataItem topLevelItem = null; Stack <ODataItem> itemsStack = new Stack <ODataItem>(); while (odataReader.Read()) { switch (odataReader.State) { case ODataReaderState.EntryStart: ODataEntry entry = (ODataEntry)odataReader.Item; ODataEntryAnnotation entryAnnotation = null; if (entry != null) { entryAnnotation = new ODataEntryAnnotation(); entry.SetAnnotation(entryAnnotation); } if (itemsStack.Count == 0) { Contract.Assert(entry != null, "The top-level entry can never be null."); topLevelItem = entry; } else { ODataItem parentItem = itemsStack.Peek(); ODataFeed parentFeed = parentItem as ODataFeed; if (parentFeed != null) { ODataFeedAnnotation parentFeedAnnotation = parentFeed.GetAnnotation <ODataFeedAnnotation>(); Contract.Assert(parentFeedAnnotation != null, "Every feed we added to the stack should have the feed annotation on it."); parentFeedAnnotation.Add(entry); } else { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)parentItem; ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); Contract.Assert(parentNavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child."); Contract.Assert(parentNavigationLinkAnnotation.Count == 0, "Each navigation property can contain only one entry as its direct child."); parentNavigationLinkAnnotation.Add(entry); } } itemsStack.Push(entry); RecurseEnter(readContext); break; case ODataReaderState.EntryEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The entry which is ending should be on the top of the items stack."); itemsStack.Pop(); RecurseLeave(readContext); break; case ODataReaderState.NavigationLinkStart: ODataNavigationLink navigationLink = (ODataNavigationLink)odataReader.Item; Contract.Assert(navigationLink != null, "Navigation link should never be null."); navigationLink.SetAnnotation(new ODataNavigationLinkAnnotation()); Contract.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item."); { ODataEntry parentEntry = (ODataEntry)itemsStack.Peek(); ODataEntryAnnotation parentEntryAnnotation = parentEntry.GetAnnotation <ODataEntryAnnotation>(); Contract.Assert(parentEntryAnnotation != null, "Every entry we added to the stack should have the entry annotation on it."); parentEntryAnnotation.Add(navigationLink); } itemsStack.Push(navigationLink); RecurseEnter(readContext); break; case ODataReaderState.NavigationLinkEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The navigation link which is ending should be on the top of the items stack."); itemsStack.Pop(); RecurseLeave(readContext); break; case ODataReaderState.FeedStart: ODataFeed feed = (ODataFeed)odataReader.Item; Contract.Assert(feed != null, "Feed should never be null."); feed.SetAnnotation(new ODataFeedAnnotation()); if (itemsStack.Count > 0) { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)itemsStack.Peek(); Contract.Assert(parentNavigationLink != null, "this has to be an inner feed. inner feeds always have a navigation link."); ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); Contract.Assert(parentNavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child."); parentNavigationLinkAnnotation.Add(feed); } else { topLevelItem = feed; } itemsStack.Push(feed); RecurseEnter(readContext); break; case ODataReaderState.FeedEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The feed which is ending should be on the top of the items stack."); itemsStack.Pop(); RecurseLeave(readContext); break; case ODataReaderState.EntityReferenceLink: ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)odataReader.Item; Contract.Assert(entityReferenceLink != null, "Entity reference link should never be null."); Contract.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item."); { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)itemsStack.Peek(); ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); parentNavigationLinkAnnotation.Add(entityReferenceLink); } break; default: Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } } Contract.Assert(odataReader.State == ODataReaderState.Completed, "We should have consumed all of the input by now."); Contract.Assert(topLevelItem != null, "A top level entry or feed should have been read by now."); return(topLevelItem); }
public void FeedAndEntryUpdatedTimeTests() { ODataFeed defaultFeedWithEmptyMetadata = ObjectModelUtils.CreateDefaultFeed(); defaultFeedWithEmptyMetadata.SetAnnotation <AtomFeedMetadata>(new AtomFeedMetadata()); ODataEntry defaultEntryWithEmptyMetadata = ObjectModelUtils.CreateDefaultEntry(); defaultEntryWithEmptyMetadata.SetAnnotation <AtomEntryMetadata>(new AtomEntryMetadata()); IEnumerable <PayloadWriterTestDescriptor <ODataItem> > testPayloads = new[] { new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultFeed()), new PayloadWriterTestDescriptor <ODataItem>(this.Settings, defaultFeedWithEmptyMetadata), new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultFeedWithAtomMetadata()), }.PayloadCases(WriterPayloads.FeedPayloads) .Concat((new[] { new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultEntry()), new PayloadWriterTestDescriptor <ODataItem>(this.Settings, defaultEntryWithEmptyMetadata), new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultEntryWithAtomMetadata()), }.PayloadCases(WriterPayloads.EntryPayloads))); this.CombinatorialEngineProvider.RunCombinations( testPayloads, this.WriterTestConfigurationProvider.AtomFormatConfigurationsWithIndent.Where(tc => !tc.IsRequest), (testPayload, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); string lastUpdatedTimeStr = null; using (var memoryStream = new MemoryStream()) { using (var testMemoryStream = TestWriterUtils.CreateTestStream(testConfiguration, memoryStream, ignoreDispose: true)) { bool feedWriter = testPayload.PayloadItems[0] is ODataFeed; TestMessage testMessage = null; Exception exception = TestExceptionUtils.RunCatching(() => { using (var messageWriter = TestWriterUtils.CreateMessageWriter(testMemoryStream, testConfiguration, this.Assert, out testMessage, null, testPayload.Model)) { ODataWriter writer = messageWriter.CreateODataWriter(feedWriter); TestWriterUtils.WritePayload(messageWriter, writer, true, testPayload.PayloadItems, testPayload.ThrowUserExceptionAt); } }); this.Assert.IsNull(exception, "Received exception but expected none."); } memoryStream.Position = 0; XElement result = XElement.Load(memoryStream); foreach (XElement updated in result.Descendants(((XNamespace)TestAtomConstants.AtomNamespace) + "updated")) { if (updated.Value != ObjectModelUtils.DefaultFeedUpdated && updated.Value != ObjectModelUtils.DefaultEntryUpdated) { if (lastUpdatedTimeStr == null) { lastUpdatedTimeStr = updated.Value; } else { this.Assert.AreEqual(lastUpdatedTimeStr, updated.Value, "<atom:updated> should contain the same value."); } } } } }); }
private void WriteFeed(object graph, ODataWriter writer, ODataSerializerContext writeContext) { IEnumerable enumerable = graph as IEnumerable; // Data to serialize if (enumerable != null) { ODataFeed feed = new ODataFeed(); if (writeContext.EntitySet != null) { IEntitySetLinkBuilder linkBuilder = SerializerProvider.EdmModel.GetEntitySetLinkBuilder(writeContext.EntitySet); FeedContext feedContext = new FeedContext { EntitySet = writeContext.EntitySet, UrlHelper = writeContext.UrlHelper, PathHandler = writeContext.PathHandler, FeedInstance = graph }; Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(feedContext); if (feedSelfLink != null) { feed.SetAnnotation(new AtomFeedMetadata() { SelfLink = new AtomLinkMetadata() { Relation = SelfLinkRelation, Href = feedSelfLink } }); } } // TODO: Bug 467590: remove the hardcoded feed id. Get support for it from the model builder ? feed.Id = FeedNamespace + _edmCollectionType.FullName(); // If we have more OData format specific information apply it now. ODataResult odataFeedAnnotations = graph as ODataResult; if (odataFeedAnnotations != null) { feed.Count = odataFeedAnnotations.Count; feed.NextPageLink = odataFeedAnnotations.NextPageLink; } else { object nextPageLinkPropertyValue; HttpRequestMessage request = writeContext.Request; if (request != null && request.Properties.TryGetValue(ODataQueryOptions.NextPageLinkPropertyKey, out nextPageLinkPropertyValue)) { Uri nextPageLink = nextPageLinkPropertyValue as Uri; if (nextPageLink != null) { feed.NextPageLink = nextPageLink; } } } writer.WriteStart(feed); foreach (object entry in enumerable) { if (entry == null) { throw Error.NotSupported(SRResources.NullElementInCollection); } ODataSerializer entrySerializer = SerializerProvider.GetODataPayloadSerializer(entry.GetType()); if (entrySerializer == null) { throw Error.NotSupported(SRResources.TypeCannotBeSerialized, entry.GetType(), typeof(ODataMediaTypeFormatter).Name); } Contract.Assert(entrySerializer.ODataPayloadKind == ODataPayloadKind.Entry); entrySerializer.WriteObjectInline(entry, writer, writeContext); } writer.WriteEnd(); } }
/// <summary> /// Create the <see cref="ODataFeed"/> to be written for the given feed instance. /// </summary> /// <param name="feedInstance">The instance representing the feed being written.</param> /// <param name="feedType">The EDM type of the feed being written.</param> /// <param name="writeContext">The serializer context.</param> /// <returns>The created <see cref="ODataFeed"/> object.</returns> public virtual ODataFeed CreateODataFeed(IEnumerable feedInstance, IEdmCollectionTypeReference feedType, ODataSerializerContext writeContext) { ODataFeed feed = new ODataFeed(); if (writeContext.EntitySet != null) { IEdmModel model = writeContext.Model; EntitySetLinkBuilderAnnotation linkBuilder = model.GetEntitySetLinkBuilder(writeContext.EntitySet); FeedContext feedContext = new FeedContext { Request = writeContext.Request, RequestContext = writeContext.RequestContext, EntitySet = writeContext.EntitySet, Url = writeContext.Url, FeedInstance = feedInstance }; Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(feedContext); if (feedSelfLink != null) { feed.SetAnnotation(new AtomFeedMetadata() { SelfLink = new AtomLinkMetadata() { Relation = "self", Href = feedSelfLink } }); } } // TODO: Bug 467590: remove the hardcoded feed id. Get support for it from the model builder ? feed.Id = "http://schemas.datacontract.org/2004/07/" + feedType.FullName(); if (writeContext.ExpandedEntity == null) { // If we have more OData format specific information apply it now, only if we are the root feed. PageResult odataFeedAnnotations = feedInstance as PageResult; if (odataFeedAnnotations != null) { feed.Count = odataFeedAnnotations.Count; feed.NextPageLink = odataFeedAnnotations.NextPageLink; } else if (writeContext.Request != null) { feed.NextPageLink = writeContext.Request.ODataProperties().NextLink; long?inlineCount = writeContext.Request.ODataProperties().TotalCount; if (inlineCount.HasValue) { feed.Count = inlineCount.Value; } } } else { // nested feed ITruncatedCollection truncatedCollection = feedInstance as ITruncatedCollection; if (truncatedCollection != null && truncatedCollection.IsTruncated) { feed.NextPageLink = GetNestedNextPageLink(writeContext, truncatedCollection.PageSize); } } return(feed); }
private void WriteFeedElements(IExpandedResult expanded, IEnumerator elements, ResourceType expectedType, string title, Uri relativeUri, Uri absoluteUri, bool hasMoved, bool topLevel) { ODataFeed feed = new ODataFeed { Id = absoluteUri.AbsoluteUri }; AtomFeedMetadata annotation = new AtomFeedMetadata(); feed.SetAnnotation <AtomFeedMetadata>(annotation); AtomTextConstruct construct = new AtomTextConstruct { Text = title }; annotation.Title = construct; AtomLinkMetadata metadata2 = new AtomLinkMetadata { Href = relativeUri, Title = title }; annotation.SelfLink = metadata2; bool flag = false; if (topLevel && (base.RequestDescription.CountOption == RequestQueryCountOption.Inline)) { flag = this.contentFormat == ODataFormat.VerboseJson; if (!flag) { feed.Count = new long?(base.RequestDescription.CountValue); } } this.odataWriter.WriteStart(feed); try { object lastObject = null; IExpandedResult skipTokenExpandedResult = null; while (hasMoved) { object current = elements.Current; IExpandedResult skipToken = base.GetSkipToken(expanded); if (current != null) { IExpandedResult result3 = current as IExpandedResult; if (result3 != null) { expanded = result3; current = Serializer.GetExpandedElement(expanded); skipToken = base.GetSkipToken(expanded); } this.WriteEntry(expanded, current, true, expectedType); } hasMoved = elements.MoveNext(); lastObject = current; skipTokenExpandedResult = skipToken; } if (flag) { feed.Count = new long?(base.RequestDescription.CountValue); } if (base.NeedNextPageLink(elements)) { feed.NextPageLink = base.GetNextLinkUri(lastObject, skipTokenExpandedResult, absoluteUri); } } finally { if (!topLevel) { WebUtil.Dispose(elements); } } this.odataWriter.WriteEnd(); }
/// <summary> /// Reads an entry from the <paramref name="odataReader"/> and all it's children including expanded entries and feeds. /// </summary> /// <param name="odataReader">The ODataReader to read from.</param> /// <param name="topLevelSegmentInfo">The segment info for the top-level entry to read.</param> /// <returns>The <see cref="ODataEntry"/> with annotations which store the navigation links and their expanded values.</returns> private ODataEntry ReadEntry(ODataReader odataReader, SegmentInfo topLevelSegmentInfo) { Debug.Assert(odataReader != null, "odataReader != null"); Debug.Assert(odataReader.State == ODataReaderState.Start, "The ODataReader must not have been used yet."); Debug.Assert(topLevelSegmentInfo != null, "topLevelSegmentInfo != null"); ODataEntry topLevelEntry = null; Stack <ODataItem> itemsStack = new Stack <ODataItem>(); while (odataReader.Read()) { // Don't let the item stack grow larger than we can process later. Also lets us to fail and report the recursion depth limit error before ODL does. if (itemsStack.Count >= RecursionLimit) { throw DataServiceException.CreateDeepRecursion(RecursionLimit); } switch (odataReader.State) { case ODataReaderState.EntryStart: ODataEntry entry = (ODataEntry)odataReader.Item; ODataEntryAnnotation entryAnnotation = null; if (entry != null) { entryAnnotation = new ODataEntryAnnotation(); entry.SetAnnotation(entryAnnotation); } if (itemsStack.Count == 0) { Debug.Assert(entry != null, "The top-level entry can never be null."); topLevelEntry = entry; // For top-level entry, create the entry resource here. // This is needed since the creation of the resource may fail (especially if this is an update in which case // we evaluate the URL query, which may return no results and thus we would fail with 404) // and we need to report that failure rather then potential other failures caused by the properties in the entry in question. this.CreateEntityResource(topLevelSegmentInfo, entry, entryAnnotation, /*topLevel*/ true); } else { ODataItem parentItem = itemsStack.Peek(); ODataFeed parentFeed = parentItem as ODataFeed; if (parentFeed != null) { ODataFeedAnnotation parentFeedAnnotation = parentFeed.GetAnnotation <ODataFeedAnnotation>(); Debug.Assert(parentFeedAnnotation != null, "Every feed we added to the stack should have the feed annotation on it."); parentFeedAnnotation.Add(entry); } else { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)parentItem; ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); Debug.Assert(parentNavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child."); Debug.Assert(parentNavigationLinkAnnotation.Count == 0, "Each navigation property can contain only one entry as its direct child."); parentNavigationLinkAnnotation.Add(entry); } } itemsStack.Push(entry); break; case ODataReaderState.EntryEnd: Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The entry which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.NavigationLinkStart: ODataNavigationLink navigationLink = (ODataNavigationLink)odataReader.Item; Debug.Assert(navigationLink != null, "Navigation link should never be null."); navigationLink.SetAnnotation(new ODataNavigationLinkAnnotation()); Debug.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item."); { ODataEntry parentEntry = (ODataEntry)itemsStack.Peek(); ODataEntryAnnotation parentEntryAnnotation = parentEntry.GetAnnotation <ODataEntryAnnotation>(); Debug.Assert(parentEntryAnnotation != null, "Every entry we added to the stack should have the navigation link annotation on it."); parentEntryAnnotation.Add(navigationLink); } itemsStack.Push(navigationLink); break; case ODataReaderState.NavigationLinkEnd: Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The navigation link which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.FeedStart: ODataFeed feed = (ODataFeed)odataReader.Item; Debug.Assert(feed != null, "Feed should never be null."); feed.SetAnnotation(new ODataFeedAnnotation()); Debug.Assert(itemsStack.Count > 0, "Since we always start reading entry, we should never get a feed as the top-level item."); { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)itemsStack.Peek(); ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); Debug.Assert(parentNavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child."); parentNavigationLinkAnnotation.Add(feed); } itemsStack.Push(feed); break; case ODataReaderState.FeedEnd: Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The feed which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.EntityReferenceLink: ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)odataReader.Item; Debug.Assert(entityReferenceLink != null, "Entity reference link should never be null."); Debug.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item."); { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)itemsStack.Peek(); ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); parentNavigationLinkAnnotation.Add(entityReferenceLink); } break; default: Debug.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } } Debug.Assert(odataReader.State == ODataReaderState.Completed, "We should have consumed all of the input by now."); Debug.Assert(topLevelEntry != null, "A top level entry should have been read by now."); return(topLevelEntry); }
private ODataEntry ReadEntry(ODataReader odataReader, System.Data.Services.SegmentInfo topLevelSegmentInfo) { ODataEntry entry = null; Stack <ODataItem> stack = new Stack <ODataItem>(); while (odataReader.Read()) { if (stack.Count >= 100) { throw DataServiceException.CreateDeepRecursion(100); } switch (odataReader.State) { case ODataReaderState.FeedStart: { ODataFeed feed2 = (ODataFeed)odataReader.Item; feed2.SetAnnotation <ODataFeedAnnotation>(new ODataFeedAnnotation()); ODataNavigationLink link3 = (ODataNavigationLink)stack.Peek(); link3.GetAnnotation <ODataNavigationLinkAnnotation>().Add(feed2); stack.Push(feed2); break; } case ODataReaderState.FeedEnd: stack.Pop(); break; case ODataReaderState.EntryStart: { ODataEntry entry2 = (ODataEntry)odataReader.Item; ODataEntryAnnotation annotation = null; if (entry2 != null) { annotation = new ODataEntryAnnotation(); entry2.SetAnnotation <ODataEntryAnnotation>(annotation); } if (stack.Count == 0) { entry = entry2; this.CreateEntityResource(topLevelSegmentInfo, entry2, annotation, true); } else { ODataItem item = stack.Peek(); ODataFeed feed = item as ODataFeed; if (feed != null) { feed.GetAnnotation <ODataFeedAnnotation>().Add(entry2); } else { ODataNavigationLink link = (ODataNavigationLink)item; link.GetAnnotation <ODataNavigationLinkAnnotation>().Add(entry2); } } stack.Push(entry2); break; } case ODataReaderState.EntryEnd: stack.Pop(); break; case ODataReaderState.NavigationLinkStart: { ODataNavigationLink link2 = (ODataNavigationLink)odataReader.Item; link2.SetAnnotation <ODataNavigationLinkAnnotation>(new ODataNavigationLinkAnnotation()); ODataEntry entry3 = (ODataEntry)stack.Peek(); entry3.GetAnnotation <ODataEntryAnnotation>().Add(link2); stack.Push(link2); break; } case ODataReaderState.NavigationLinkEnd: stack.Pop(); break; case ODataReaderState.EntityReferenceLink: { ODataEntityReferenceLink link4 = (ODataEntityReferenceLink)odataReader.Item; ODataNavigationLink link5 = (ODataNavigationLink)stack.Peek(); link5.GetAnnotation <ODataNavigationLinkAnnotation>().Add(link4); break; } } } return(entry); }