/// <inheritdoc /> public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext) { if (item == null) { return(null); } if (edmType == null) { throw Error.ArgumentNull("edmType"); } if (!edmType.IsCollection() || !edmType.AsCollection().ElementType().IsEntity()) { throw Error.Argument("edmType", SRResources.TypeMustBeEntityCollection, edmType.ToTraceString(), typeof(IEdmEntityType).Name); } IEdmEntityTypeReference elementType = edmType.AsCollection().ElementType().AsEntity(); ODataFeedWithEntries feed = item as ODataFeedWithEntries; if (feed == null) { throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataFeedWithEntries).Name); } // Recursion guard to avoid stack overflows RuntimeHelpers.EnsureSufficientExecutionStack(); return(ReadFeed(feed, elementType, readContext)); }
public void ReadFeed_Calls_ReadInlineForEachEntry() { // Arrange Mock <ODataDeserializerProvider> deserializerProvider = new Mock <ODataDeserializerProvider>(); Mock <ODataEdmTypeDeserializer> entityDeserializer = new Mock <ODataEdmTypeDeserializer>(ODataPayloadKind.Entry); ODataFeedDeserializer deserializer = new ODataFeedDeserializer(deserializerProvider.Object); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(new ODataFeed()); feedWrapper.Entries.Add(new ODataEntryWithNavigationLinks(new ODataEntry { Id = new Uri("http://a1/") })); feedWrapper.Entries.Add(new ODataEntryWithNavigationLinks(new ODataEntry { Id = new Uri("http://a2/") })); ODataDeserializerContext readContext = new ODataDeserializerContext(); deserializerProvider.Setup(p => p.GetEdmTypeDeserializer(_customerType)).Returns(entityDeserializer.Object); entityDeserializer.Setup(d => d.ReadInline(feedWrapper.Entries[0], _customerType, readContext)).Returns("entry1").Verifiable(); entityDeserializer.Setup(d => d.ReadInline(feedWrapper.Entries[1], _customerType, readContext)).Returns("entry2").Verifiable(); // Act var result = deserializer.ReadFeed(feedWrapper, _customerType, readContext); // Assert Assert.Equal(new[] { "entry1", "entry2" }, result.OfType <String>()); entityDeserializer.Verify(); }
public void ReadFeed_Throws_TypeCannotBeDeserialized() { Mock<ODataDeserializerProvider> deserializerProvider = new Mock<ODataDeserializerProvider>(); ODataFeedDeserializer deserializer = new ODataFeedDeserializer(deserializerProvider.Object); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(new ODataFeed()); ODataDeserializerContext readContext = new ODataDeserializerContext(); deserializerProvider.Setup(p => p.GetEdmTypeDeserializer(_customerType)).Returns<ODataEdmTypeDeserializer>(null); Assert.Throws<SerializationException>( () => deserializer.ReadFeed(feedWrapper, _customerType, readContext).GetEnumerator().MoveNext(), "'System.Web.OData.TestCommon.Models.Customer' cannot be deserialized using the ODataMediaTypeFormatter."); }
public void ReadFeed_Throws_TypeCannotBeDeserialized() { Mock <ODataDeserializerProvider> deserializerProvider = new Mock <ODataDeserializerProvider>(); ODataFeedDeserializer deserializer = new ODataFeedDeserializer(deserializerProvider.Object); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(new ODataFeed()); ODataDeserializerContext readContext = new ODataDeserializerContext(); deserializerProvider.Setup(p => p.GetEdmTypeDeserializer(_customerType)).Returns <ODataEdmTypeDeserializer>(null); Assert.Throws <SerializationException>( () => deserializer.ReadFeed(feedWrapper, _customerType, readContext).GetEnumerator().MoveNext(), "'System.Web.OData.TestCommon.Models.Customer' cannot be deserialized using the ODataMediaTypeFormatter."); }
/// <summary> /// Deserializes the given <paramref name="feed"/> under the given <paramref name="readContext"/>. /// </summary> /// <param name="feed">The feed to deserialize.</param> /// <param name="readContext">The deserializer context.</param> /// <param name="elementType">The element type of the feed being read.</param> /// <returns>The deserialized feed object.</returns> public virtual IEnumerable ReadFeed(ODataFeedWithEntries feed, IEdmEntityTypeReference elementType, ODataDeserializerContext readContext) { ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(elementType); if (deserializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeDeserialized, elementType.FullName(), typeof(ODataMediaTypeFormatter).Name)); } foreach (ODataEntryWithNavigationLinks entry in feed.Entries) { yield return deserializer.ReadInline(entry, elementType, readContext); } }
/// <summary> /// Deserializes the given <paramref name="feed"/> under the given <paramref name="readContext"/>. /// </summary> /// <param name="feed">The feed to deserialize.</param> /// <param name="readContext">The deserializer context.</param> /// <param name="elementType">The element type of the feed being read.</param> /// <returns>The deserialized feed object.</returns> public virtual IEnumerable ReadFeed(ODataFeedWithEntries feed, IEdmEntityTypeReference elementType, ODataDeserializerContext readContext) { ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(elementType); if (deserializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeDeserialized, elementType.FullName(), typeof(ODataMediaTypeFormatter).Name)); } foreach (ODataEntryWithNavigationLinks entry in feed.Entries) { yield return(deserializer.ReadInline(entry, elementType, readContext)); } }
/// <summary> /// Deserializes the navigation property from <paramref name="navigationLinkWrapper"/> into <paramref name="entityResource"/>. /// </summary> /// <param name="entityResource">The object into which the navigation property should be read.</param> /// <param name="navigationLinkWrapper">The navigation link.</param> /// <param name="entityType">The entity type of the entity resource.</param> /// <param name="readContext">The deserializer context.</param> public virtual void ApplyNavigationProperty(object entityResource, ODataNavigationLinkWithItems navigationLinkWrapper, IEdmEntityTypeReference entityType, ODataDeserializerContext readContext) { if (navigationLinkWrapper == null) { throw Error.ArgumentNull("navigationLinkWrapper"); } if (entityResource == null) { throw Error.ArgumentNull("entityResource"); } IEdmNavigationProperty navigationProperty = entityType.FindProperty(navigationLinkWrapper.NavigationLink.Name) as IEdmNavigationProperty; if (navigationProperty == null) { throw new ODataException( Error.Format(SRResources.NavigationPropertyNotfound, navigationLinkWrapper.NavigationLink.Name, entityType.FullName())); } foreach (ODataItemBase childItem in navigationLinkWrapper.NestedItems) { ODataEntityReferenceLinkBase entityReferenceLink = childItem as ODataEntityReferenceLinkBase; if (entityReferenceLink != null) { // ignore links. continue; } ODataFeedWithEntries feed = childItem as ODataFeedWithEntries; if (feed != null) { ApplyFeedInNavigationProperty(navigationProperty, entityResource, feed, readContext); continue; } // It must be entry by now. ODataEntryWithNavigationLinks entry = (ODataEntryWithNavigationLinks)childItem; if (entry != null) { ApplyEntryInNavigationProperty(navigationProperty, entityResource, entry, readContext); } } }
public void ReadInline_Calls_ReadFeed() { // Arrange ODataDeserializerProvider deserializerProvider = new DefaultODataDeserializerProvider(); Mock<ODataFeedDeserializer> deserializer = new Mock<ODataFeedDeserializer>(deserializerProvider); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(new ODataFeed()); ODataDeserializerContext readContext = new ODataDeserializerContext(); IEnumerable expectedResult = new object[0]; deserializer.CallBase = true; deserializer.Setup(f => f.ReadFeed(feedWrapper, _customerType, readContext)).Returns(expectedResult).Verifiable(); // Act var result = deserializer.Object.ReadInline(feedWrapper, _customersType, readContext); // Assert deserializer.Verify(); Assert.Same(expectedResult, result); }
public void ReadInline_Calls_ReadFeed() { // Arrange ODataDeserializerProvider deserializerProvider = new DefaultODataDeserializerProvider(); Mock <ODataFeedDeserializer> deserializer = new Mock <ODataFeedDeserializer>(deserializerProvider); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(new ODataFeed()); ODataDeserializerContext readContext = new ODataDeserializerContext(); IEnumerable expectedResult = new object[0]; deserializer.CallBase = true; deserializer.Setup(f => f.ReadFeed(feedWrapper, _customerType, readContext)).Returns(expectedResult).Verifiable(); // Act var result = deserializer.Object.ReadInline(feedWrapper, _customersType, readContext); // Assert deserializer.Verify(); Assert.Same(expectedResult, result); }
public void ApplyNavigationProperty_UsesThePropertyAlias_ForFeed() { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); model.Model.SetAnnotationValue(model.Customer, new ClrTypeAnnotation(typeof(Customer))); model.Model.SetAnnotationValue(model.Order, new ClrTypeAnnotation(typeof(Order))); model.Model.SetAnnotationValue( model.Customer.FindProperty("Orders"), new ClrPropertyInfoAnnotation(typeof(Customer).GetProperty("AliasedOrders"))); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(new ODataFeed()); feedWrapper.Entries.Add(new ODataEntryWithNavigationLinks( new ODataEntry { Properties = new[] { new ODataProperty { Name = "ID", Value = 42 } } })); Customer customer = new Customer(); ODataNavigationLinkWithItems navLink = new ODataNavigationLinkWithItems(new ODataNavigationLink { Name = "Orders" }); navLink.NestedItems.Add(feedWrapper); ODataDeserializerContext context = new ODataDeserializerContext { Model = model.Model }; // Act new ODataEntityDeserializer(_deserializerProvider) .ApplyNavigationProperty(customer, navLink, model.Customer.AsReference(), context); // Assert Assert.Equal(1, customer.AliasedOrders.Count()); Assert.Equal(42, customer.AliasedOrders[0].ID); }
private void ApplyFeedInNavigationProperty(IEdmNavigationProperty navigationProperty, object entityResource, ODataFeedWithEntries feed, ODataDeserializerContext readContext) { Contract.Assert(navigationProperty != null && navigationProperty.PropertyKind == EdmPropertyKind.Navigation, "navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType"); Contract.Assert(entityResource != null, "entityResource != null"); if (readContext.IsDeltaOfT) { string message = Error.Format(SRResources.CannotPatchNavigationProperties, navigationProperty.Name, navigationProperty.DeclaringEntityType().FullName()); throw new ODataException(message); } ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(navigationProperty.Type); if (deserializer == null) { throw new SerializationException(Error.Format(SRResources.TypeCannotBeDeserialized, navigationProperty.Type.FullName(), typeof(ODataMediaTypeFormatter))); } object value = deserializer.ReadInline(feed, navigationProperty.Type, readContext); string propertyName = EdmLibHelpers.GetClrPropertyName(navigationProperty, readContext.Model); DeserializationHelpers.SetCollectionProperty(entityResource, navigationProperty, value, propertyName); }
/// <summary> /// Reads an ODataFeed or an ODataItem from the reader. /// </summary> /// <param name="reader">The OData reader to read from.</param> /// <returns>The read feed or entry.</returns> public static ODataItemBase ReadEntryOrFeed(ODataReader reader) { if (reader == null) { throw Error.ArgumentNull("odataReader"); } ODataItemBase topLevelItem = null; Stack<ODataItemBase> itemsStack = new Stack<ODataItemBase>(); while (reader.Read()) { switch (reader.State) { case ODataReaderState.EntryStart: ODataEntry entry = (ODataEntry)reader.Item; ODataEntryWithNavigationLinks entryWrapper = null; if (entry != null) { entryWrapper = new ODataEntryWithNavigationLinks(entry); } if (itemsStack.Count == 0) { Contract.Assert(entry != null, "The top-level entry can never be null."); topLevelItem = entryWrapper; } else { ODataItemBase parentItem = itemsStack.Peek(); ODataFeedWithEntries parentFeed = parentItem as ODataFeedWithEntries; if (parentFeed != null) { parentFeed.Entries.Add(entryWrapper); } else { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)parentItem; Contract.Assert(parentNavigationLink.NavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child."); Contract.Assert(parentNavigationLink.NestedItems.Count == 0, "Each navigation property can contain only one entry as its direct child."); parentNavigationLink.NestedItems.Add(entryWrapper); } } itemsStack.Push(entryWrapper); break; case ODataReaderState.EntryEnd: Contract.Assert(itemsStack.Count > 0 && (reader.Item == null || itemsStack.Peek().Item == reader.Item), "The entry which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.NavigationLinkStart: ODataNavigationLink navigationLink = (ODataNavigationLink)reader.Item; Contract.Assert(navigationLink != null, "Navigation link should never be null."); ODataNavigationLinkWithItems navigationLinkWrapper = new ODataNavigationLinkWithItems(navigationLink); Contract.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item."); { ODataEntryWithNavigationLinks parentEntry = (ODataEntryWithNavigationLinks)itemsStack.Peek(); parentEntry.NavigationLinks.Add(navigationLinkWrapper); } itemsStack.Push(navigationLinkWrapper); break; case ODataReaderState.NavigationLinkEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.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)reader.Item; Contract.Assert(feed != null, "Feed should never be null."); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(feed); if (itemsStack.Count > 0) { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)itemsStack.Peek(); Contract.Assert(parentNavigationLink != null, "this has to be an inner feed. inner feeds always have a navigation link."); Contract.Assert(parentNavigationLink.NavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child."); parentNavigationLink.NestedItems.Add(feedWrapper); } else { topLevelItem = feedWrapper; } itemsStack.Push(feedWrapper); break; case ODataReaderState.FeedEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The feed which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.EntityReferenceLink: ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)reader.Item; Contract.Assert(entityReferenceLink != null, "Entity reference link should never be null."); ODataEntityReferenceLinkBase entityReferenceLinkWrapper = new ODataEntityReferenceLinkBase(entityReferenceLink); Contract.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item."); { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)itemsStack.Peek(); parentNavigationLink.NestedItems.Add(entityReferenceLinkWrapper); } break; default: Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } } Contract.Assert(reader.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 ReadFeed_Calls_ReadInlineForEachEntry() { // Arrange Mock<ODataDeserializerProvider> deserializerProvider = new Mock<ODataDeserializerProvider>(); Mock<ODataEdmTypeDeserializer> entityDeserializer = new Mock<ODataEdmTypeDeserializer>(ODataPayloadKind.Entry); ODataFeedDeserializer deserializer = new ODataFeedDeserializer(deserializerProvider.Object); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(new ODataFeed()); feedWrapper.Entries.Add(new ODataEntryWithNavigationLinks(new ODataEntry { Id = new Uri("http://a1/") })); feedWrapper.Entries.Add(new ODataEntryWithNavigationLinks(new ODataEntry { Id = new Uri("http://a2/") })); ODataDeserializerContext readContext = new ODataDeserializerContext(); deserializerProvider.Setup(p => p.GetEdmTypeDeserializer(_customerType)).Returns(entityDeserializer.Object); entityDeserializer.Setup(d => d.ReadInline(feedWrapper.Entries[0], _customerType, readContext)).Returns("entry1").Verifiable(); entityDeserializer.Setup(d => d.ReadInline(feedWrapper.Entries[1], _customerType, readContext)).Returns("entry2").Verifiable(); // Act var result = deserializer.ReadFeed(feedWrapper, _customerType, readContext); // Assert Assert.Equal(new[] { "entry1", "entry2" }, result.OfType<String>()); entityDeserializer.Verify(); }
private void ApplyFeedInNavigationProperty(IEdmNavigationProperty navigationProperty, object entityResource, ODataFeedWithEntries feed, ODataDeserializerContext readContext) { Contract.Assert(navigationProperty != null && navigationProperty.PropertyKind == EdmPropertyKind.Navigation, "navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType"); Contract.Assert(entityResource != null, "entityResource != null"); if (readContext.IsDeltaOfT) { string message = Error.Format(SRResources.CannotPatchNavigationProperties, navigationProperty.Name, navigationProperty.DeclaringEntityType().FullName()); throw new ODataException(message); } ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(navigationProperty.Type); if (deserializer == null) { throw new SerializationException(Error.Format(SRResources.TypeCannotBeDeserialized, navigationProperty.Type.FullName(), typeof(ODataMediaTypeFormatter))); } object value = deserializer.ReadInline(feed, navigationProperty.Type, readContext); string propertyName = EdmLibHelpers.GetClrPropertyName(navigationProperty, readContext.Model); DeserializationHelpers.SetCollectionProperty(entityResource, navigationProperty, value, propertyName, readContext.TimeZoneInfo); }
/// <summary> /// Reads an ODataFeed or an ODataItem from the reader. /// </summary> /// <param name="reader">The OData reader to read from.</param> /// <returns>The read feed or entry.</returns> public static ODataItemBase ReadEntryOrFeed(ODataReader reader) { if (reader == null) { throw Error.ArgumentNull("odataReader"); } ODataItemBase topLevelItem = null; Stack <ODataItemBase> itemsStack = new Stack <ODataItemBase>(); while (reader.Read()) { switch (reader.State) { case ODataReaderState.EntryStart: ODataEntry entry = (ODataEntry)reader.Item; ODataEntryWithNavigationLinks entryWrapper = null; if (entry != null) { entryWrapper = new ODataEntryWithNavigationLinks(entry); } if (itemsStack.Count == 0) { Contract.Assert(entry != null, "The top-level entry can never be null."); topLevelItem = entryWrapper; } else { ODataItemBase parentItem = itemsStack.Peek(); ODataFeedWithEntries parentFeed = parentItem as ODataFeedWithEntries; if (parentFeed != null) { parentFeed.Entries.Add(entryWrapper); } else { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)parentItem; Contract.Assert(parentNavigationLink.NavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child."); Contract.Assert(parentNavigationLink.NestedItems.Count == 0, "Each navigation property can contain only one entry as its direct child."); parentNavigationLink.NestedItems.Add(entryWrapper); } } itemsStack.Push(entryWrapper); break; case ODataReaderState.EntryEnd: Contract.Assert(itemsStack.Count > 0 && (reader.Item == null || itemsStack.Peek().Item == reader.Item), "The entry which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.NavigationLinkStart: ODataNavigationLink navigationLink = (ODataNavigationLink)reader.Item; Contract.Assert(navigationLink != null, "Navigation link should never be null."); ODataNavigationLinkWithItems navigationLinkWrapper = new ODataNavigationLinkWithItems(navigationLink); Contract.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item."); { ODataEntryWithNavigationLinks parentEntry = (ODataEntryWithNavigationLinks)itemsStack.Peek(); parentEntry.NavigationLinks.Add(navigationLinkWrapper); } itemsStack.Push(navigationLinkWrapper); break; case ODataReaderState.NavigationLinkEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.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)reader.Item; Contract.Assert(feed != null, "Feed should never be null."); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(feed); if (itemsStack.Count > 0) { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)itemsStack.Peek(); Contract.Assert(parentNavigationLink != null, "this has to be an inner feed. inner feeds always have a navigation link."); Contract.Assert(parentNavigationLink.NavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child."); parentNavigationLink.NestedItems.Add(feedWrapper); } else { topLevelItem = feedWrapper; } itemsStack.Push(feedWrapper); break; case ODataReaderState.FeedEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The feed which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.EntityReferenceLink: ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)reader.Item; Contract.Assert(entityReferenceLink != null, "Entity reference link should never be null."); ODataEntityReferenceLinkBase entityReferenceLinkWrapper = new ODataEntityReferenceLinkBase(entityReferenceLink); Contract.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item."); { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)itemsStack.Peek(); parentNavigationLink.NestedItems.Add(entityReferenceLinkWrapper); } break; default: Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } } Contract.Assert(reader.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); }
internal static IEnumerable CovertFeedIds(IEnumerable sources, ODataFeedWithEntries feed, IEdmCollectionTypeReference collectionType, ODataDeserializerContext readContext) { IEdmEntityTypeReference entityTypeReference = collectionType.ElementType().AsEntity(); int i = 0; foreach (object item in sources) { object newItem = CovertEntityId(item, feed.Entries[i].Entry, entityTypeReference, readContext); i++; yield return newItem; } }