/// <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); }
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); } }
/// <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.GetNextPageLink(); long? inlineCount = writeContext.Request.GetInlineCount(); 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; }
/// <summary> /// Creates a an ODataFeed instance with default values for 'Id' and 'Updated' /// that can be used and modified in tests. /// </summary> /// <returns>The created ODataFeed instance.</returns> public static ODataFeed CreateDefaultFeedWithAtomMetadata() { ODataFeed feed = new ODataFeed() { Id = DefaultFeedId, SerializationInfo = MySerializationInfo }; AtomFeedMetadata metadata = new AtomFeedMetadata() { Updated = DateTimeOffset.Parse(DefaultFeedUpdated) }; feed.SetAnnotation<AtomFeedMetadata>(metadata); return feed; }
/// <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 }
/// <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.NavigationSource != null) { IEdmModel model = writeContext.Model; NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(writeContext.NavigationSource); FeedContext feedContext = new FeedContext { Request = writeContext.Request, RequestContext = writeContext.RequestContext, EntitySet = writeContext.NavigationSource as IEdmEntitySet, Url = writeContext.Url, FeedInstance = feedInstance }; Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(feedContext); if (feedSelfLink != null) { feed.SetAnnotation(new AtomFeedMetadata() { SelfLink = new AtomLinkMetadata() { Relation = "self", Href = feedSelfLink } }); } } feed.Id = new Uri("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? countValue = writeContext.Request.ODataProperties().TotalCount; if (countValue.HasValue) { feed.Count = countValue.Value; } } } else { // nested feed ITruncatedCollection truncatedCollection = feedInstance as ITruncatedCollection; if (truncatedCollection != null && truncatedCollection.IsTruncated) { feed.NextPageLink = GetNestedNextPageLink(writeContext, truncatedCollection.PageSize); } } return feed; }