public void ReadEntry_SetsExpectedAndActualEdmType_OnCreatedEdmObject_TypelessMode() { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); IEdmEntityTypeReference customerType = EdmLibHelpers.ToEdmTypeReference(model.Customer, isNullable: false).AsEntity(); ODataDeserializerContext readContext = new ODataDeserializerContext { Model = model.Model, ResourceType = typeof(IEdmObject) }; ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = model.SpecialCustomer.FullName(), Properties = new ODataProperty[0] }); ODataEntityDeserializer deserializer = new ODataEntityDeserializer(_deserializerProvider); // Act var result = deserializer.ReadEntry(entry, customerType, readContext); // Assert EdmEntityObject resource = Assert.IsType <EdmEntityObject>(result); Assert.Equal(model.SpecialCustomer, resource.ActualEdmType); Assert.Equal(model.Customer, resource.ExpectedEdmType); }
/// <inheritdoc /> public override object Read(ODataMessageReader messageReader, ODataDeserializerContext readContext) { if (messageReader == null) { throw Error.ArgumentNull("messageReader"); } if (readContext == null) { throw Error.ArgumentNull("readContext"); } if (readContext.Path == null) { throw Error.Argument("readContext", SRResources.ODataPathMissing); } IEdmEntitySet entitySet = GetEntitySet(readContext.Path); if (entitySet == null) { throw new SerializationException(SRResources.EntitySetMissingDuringDeserialization); } ODataReader odataReader = messageReader.CreateODataEntryReader(entitySet, EntityType.EntityDefinition()); ODataEntryWithNavigationLinks topLevelEntry = ReadEntryOrFeed(odataReader) as ODataEntryWithNavigationLinks; Contract.Assert(topLevelEntry != null); return(ReadInline(topLevelEntry, readContext)); }
/// <summary> /// Deserializes the given <paramref name="entryWrapper"/> under the given <paramref name="readContext"/>. /// </summary> /// <param name="entryWrapper">The OData entry to deserialize.</param> /// <param name="entityType">The entity type of the entry to deserialize.</param> /// <param name="readContext">The deserializer context.</param> /// <returns>The deserialized entity.</returns> public virtual object ReadEntry(ODataEntryWithNavigationLinks entryWrapper, IEdmEntityTypeReference entityType, ODataDeserializerContext readContext) { if (entryWrapper == null) { throw Error.ArgumentNull("entryWrapper"); } if (readContext == null) { throw Error.ArgumentNull("readContext"); } if (!String.IsNullOrEmpty(entryWrapper.Entry.TypeName) && entityType.FullName() != entryWrapper.Entry.TypeName) { // received a derived type in a base type deserializer. delegate it to the appropriate derived type deserializer. IEdmModel model = readContext.Model; if (model == null) { throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext); } IEdmEntityType actualType = model.FindType(entryWrapper.Entry.TypeName) as IEdmEntityType; if (actualType == null) { throw new ODataException(Error.Format(SRResources.EntityTypeNotInModel, entryWrapper.Entry.TypeName)); } if (actualType.IsAbstract) { string message = Error.Format(SRResources.CannotInstantiateAbstractEntityType, entryWrapper.Entry.TypeName); throw new ODataException(message); } IEdmTypeReference actualEntityType = new EdmEntityTypeReference(actualType, isNullable: false); ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(actualEntityType); if (deserializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeDeserialized, actualEntityType.FullName(), typeof(ODataMediaTypeFormatter).Name)); } object resource = deserializer.ReadInline(entryWrapper, actualEntityType, readContext); EdmStructuredObject structuredObject = resource as EdmStructuredObject; if (structuredObject != null) { structuredObject.ExpectedEdmType = entityType.EntityDefinition(); } return(resource); } else { object resource = CreateEntityResource(entityType, readContext); ApplyEntityProperties(resource, entryWrapper, entityType, readContext); return(resource); } }
/// <inheritdoc /> public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext) { if (item == null) { throw Error.ArgumentNull("item"); } if (edmType == null) { throw Error.ArgumentNull("edmType"); } if (!edmType.IsEntity()) { throw Error.Argument("edmType", SRResources.ArgumentMustBeOfType, EdmTypeKind.Entity); } ODataEntryWithNavigationLinks entryWrapper = item as ODataEntryWithNavigationLinks; if (entryWrapper == null) { throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataEntry).Name); } // Recursion guard to avoid stack overflows RuntimeHelpers.EnsureSufficientExecutionStack(); return(ReadEntry(entryWrapper, edmType.AsEntity(), readContext)); }
public void ReadEntry_ThrowsArgumentNull_ReadContext() { var deserializer = new ODataEntityDeserializer(_deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry()); Assert.ThrowsArgumentNull( () => deserializer.ReadEntry(entry, entityType: _productEdmType, readContext: null), "readContext"); }
public void ReadEntry_ThrowsODataException_EntityTypeNotInModel() { var deserializer = new ODataEntityDeserializer(_deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = "MissingType" }); Assert.Throws <ODataException>( () => deserializer.ReadEntry(entry, _productEdmType, _readContext), "Cannot find the entity type 'MissingType' in the model."); }
/// <summary> /// Deserializes the structural properties from <paramref name="entryWrapper"/> into <paramref name="entityResource"/>. /// </summary> /// <param name="entityResource">The object into which the structural properties should be read.</param> /// <param name="entryWrapper">The entry object containing the structural properties.</param> /// <param name="readContext">The deserializer context.</param> public virtual void ApplyStructuralProperties(object entityResource, ODataEntryWithNavigationLinks entryWrapper, ODataDeserializerContext readContext) { if (entryWrapper == null) { throw Error.ArgumentNull("entryWrapper"); } foreach (ODataProperty property in entryWrapper.Entry.Properties) { ApplyStructuralProperty(entityResource, property, readContext); } }
public void ReadEntry_ThrowsArgument_ModelMissingFromReadContext() { var deserializer = new ODataEntityDeserializer(_deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = _supplierEdmType.FullName() }); Assert.ThrowsArgument( () => deserializer.ReadEntry(entry, _productEdmType, new ODataDeserializerContext()), "readContext", "The EDM model is missing on the read context. The model is required on the read context to deserialize the payload."); }
/// <summary> /// Deserializes the navigation properties from <paramref name="entryWrapper"/> into <paramref name="entityResource"/>. /// </summary> /// <param name="entityResource">The object into which the navigation properties should be read.</param> /// <param name="entryWrapper">The entry object containing the navigation properties.</param> /// <param name="readContext">The deserializer context.</param> public virtual void ApplyNavigationProperties(object entityResource, ODataEntryWithNavigationLinks entryWrapper, ODataDeserializerContext readContext) { if (entryWrapper == null) { throw Error.ArgumentNull("entryWrapper"); } foreach (ODataNavigationLinkWithItems navigationLink in entryWrapper.NavigationLinks) { ApplyNavigationProperty(entityResource, navigationLink, readContext); } }
public void ReadEntry_ThrowsSerializationException_TypeCannotBeDeserialized() { Mock <ODataDeserializerProvider> deserializerProvider = new Mock <ODataDeserializerProvider>(); deserializerProvider.Setup(d => d.GetEdmTypeDeserializer(It.IsAny <IEdmTypeReference>())).Returns <ODataEdmTypeDeserializer>(null); var deserializer = new ODataEntityDeserializer(deserializerProvider.Object); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = _supplierEdmType.FullName() }); Assert.Throws <SerializationException>( () => deserializer.ReadEntry(entry, _productEdmType, _readContext), "'ODataDemo.Supplier' cannot be deserialized using the ODataMediaTypeFormatter."); }
public void ReadInline_Calls_ReadEntry() { // Arrange var deserializer = new Mock <ODataEntityDeserializer>(_deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry()); ODataDeserializerContext readContext = new ODataDeserializerContext(); deserializer.CallBase = true; deserializer.Setup(d => d.ReadEntry(entry, _productEdmType, readContext)).Returns(42).Verifiable(); // Act var result = deserializer.Object.ReadInline(entry, _productEdmType, readContext); // Assert deserializer.Verify(); Assert.Equal(42, result); }
public void ReadEntry_ThrowsODataException_CannotInstantiateAbstractEntityType() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.Entity <BaseType>().Abstract(); IEdmModel model = builder.GetEdmModel(); var deserializer = new ODataEntityDeserializer(_deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = "System.Web.Http.OData.Formatter.Deserialization.BaseType" }); Assert.Throws <ODataException>( () => deserializer.ReadEntry(entry, _productEdmType, new ODataDeserializerContext { Model = model }), "An instance of the abstract entity type 'System.Web.Http.OData.Formatter.Deserialization.BaseType' was found. Abstract entity types cannot be instantiated."); }
/// <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 ReadEntry_Calls_ApplyNaviagationProperties() { // Arrange Mock <ODataEntityDeserializer> deserializer = new Mock <ODataEntityDeserializer>(_deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { Properties = Enumerable.Empty <ODataProperty>() }); deserializer.CallBase = true; deserializer.Setup(d => d.CreateEntityResource(_productEdmType, _readContext)).Returns(42); deserializer.Setup(d => d.ApplyNavigationProperties(42, entry, _productEdmType, _readContext)).Verifiable(); // Act deserializer.Object.ReadEntry(entry, _productEdmType, _readContext); // Assert deserializer.Verify(); }
/// <inheritdoc /> public sealed override object ReadInline(object item, ODataDeserializerContext readContext) { if (item == null) { throw Error.ArgumentNull("item"); } ODataEntryWithNavigationLinks entryWrapper = item as ODataEntryWithNavigationLinks; if (entryWrapper == null) { throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataEntry).Name); } // Recursion guard to avoid stack overflows EnsureStackHelper.EnsureStack(); return(ReadEntry(entryWrapper, readContext)); }
public void ReadEntry_DispatchesToRightDeserializer_IfEntityTypeNameIsDifferent() { // Arrange Mock <ODataEdmTypeDeserializer> supplierDeserializer = new Mock <ODataEdmTypeDeserializer>(_supplierEdmType, ODataPayloadKind.Entry); Mock <ODataDeserializerProvider> deserializerProvider = new Mock <ODataDeserializerProvider>(); var deserializer = new ODataEntityDeserializer(_productEdmType, deserializerProvider.Object); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = _supplierEdmType.FullName() }); deserializerProvider.Setup(d => d.GetEdmTypeDeserializer(It.IsAny <IEdmTypeReference>())).Returns(supplierDeserializer.Object); supplierDeserializer.Setup(d => d.ReadInline(entry, _readContext)).Returns(42).Verifiable(); // Act object result = deserializer.ReadEntry(entry, _readContext); // Assert Assert.Equal(42, result); supplierDeserializer.Verify(); }
public void ApplyStructuralProperties_Calls_ApplyStructuralPropertyOnEachPropertyInEntry() { // Arrange var deserializer = new Mock <ODataEntityDeserializer>(_deserializerProvider); ODataProperty[] properties = new[] { new ODataProperty(), new ODataProperty() }; ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { Properties = properties }); deserializer.CallBase = true; deserializer.Setup(d => d.ApplyStructuralProperty(42, properties[0], _productEdmType, _readContext)).Verifiable(); deserializer.Setup(d => d.ApplyStructuralProperty(42, properties[1], _productEdmType, _readContext)).Verifiable(); // Act deserializer.Object.ApplyStructuralProperties(42, entry, _productEdmType, _readContext); // Assert deserializer.Verify(); }
public void ApplyNavigationProperties_Calls_ApplyNavigationPropertyForEachNavigationLink() { // Arrange ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry()); entry.NavigationLinks.Add(new ODataNavigationLinkWithItems(new ODataNavigationLink())); entry.NavigationLinks.Add(new ODataNavigationLinkWithItems(new ODataNavigationLink())); Mock <ODataEntityDeserializer> deserializer = new Mock <ODataEntityDeserializer>(_deserializerProvider); deserializer.CallBase = true; deserializer.Setup(d => d.ApplyNavigationProperty(42, entry.NavigationLinks[0], _productEdmType, _readContext)).Verifiable(); deserializer.Setup(d => d.ApplyNavigationProperty(42, entry.NavigationLinks[1], _productEdmType, _readContext)).Verifiable(); // Act deserializer.Object.ApplyNavigationProperties(42, entry, _productEdmType, _readContext); // Assert deserializer.Verify(); }
private void ApplyEntryInNavigationProperty(IEdmNavigationProperty navigationProperty, object entityResource, ODataEntryWithNavigationLinks entry, 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(entry, navigationProperty.Type, readContext); DeserializationHelpers.SetProperty(entityResource, navigationProperty.Name, value); }
private void ApplyEntityProperties(object entityResource, ODataEntryWithNavigationLinks entryWrapper, IEdmEntityTypeReference entityType, ODataDeserializerContext readContext) { ApplyStructuralProperties(entityResource, entryWrapper, entityType, readContext); ApplyNavigationProperties(entityResource, entryWrapper, entityType, readContext); }
/// <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; }
/// <summary> /// Deserializes the structural properties from <paramref name="entryWrapper"/> into <paramref name="entityResource"/>. /// </summary> /// <param name="entityResource">The object into which the structural properties should be read.</param> /// <param name="entryWrapper">The entry object containing the structural properties.</param> /// <param name="entityType">The entity type of the entity resource.</param> /// <param name="readContext">The deserializer context.</param> public virtual void ApplyStructuralProperties(object entityResource, ODataEntryWithNavigationLinks entryWrapper, IEdmEntityTypeReference entityType, ODataDeserializerContext readContext) { if (entryWrapper == null) { throw Error.ArgumentNull("entryWrapper"); } foreach (ODataProperty property in entryWrapper.Entry.Properties) { ApplyStructuralProperty(entityResource, property, entityType, readContext); } }
/// <summary> /// Deserializes the navigation properties from <paramref name="entryWrapper"/> into <paramref name="entityResource"/>. /// </summary> /// <param name="entityResource">The object into which the navigation properties should be read.</param> /// <param name="entryWrapper">The entry object containing the navigation properties.</param> /// <param name="entityType">The entity type of the entity resource.</param> /// <param name="readContext">The deserializer context.</param> public virtual void ApplyNavigationProperties(object entityResource, ODataEntryWithNavigationLinks entryWrapper, IEdmEntityTypeReference entityType, ODataDeserializerContext readContext) { if (entryWrapper == null) { throw Error.ArgumentNull("entryWrapper"); } foreach (ODataNavigationLinkWithItems navigationLink in entryWrapper.NavigationLinks) { ApplyNavigationProperty(entityResource, navigationLink, entityType, readContext); } }
public void ReadEntry_ThrowsArgument_ModelMissingFromReadContext() { var deserializer = new ODataEntityDeserializer(_productEdmType, _deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = _supplierEdmType.FullName() }); Assert.ThrowsArgument( () => deserializer.ReadEntry(entry, new ODataDeserializerContext()), "readContext", "The EDM model is missing on the read context. The model is required on the read context to deserialize the payload."); }
/// <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 ReadEntry_Calls_ApplyNaviagationProperties() { // Arrange Mock<ODataEntityDeserializer> deserializer = new Mock<ODataEntityDeserializer>(_productEdmType, _deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { Properties = Enumerable.Empty<ODataProperty>() }); deserializer.CallBase = true; deserializer.Setup(d => d.CreateEntityResource(_readContext)).Returns(42); deserializer.Setup(d => d.ApplyNavigationProperties(42, entry, _readContext)).Verifiable(); // Act deserializer.Object.ReadEntry(entry, _readContext); // Assert deserializer.Verify(); }
public void ReadEntry_ThrowsSerializationException_TypeCannotBeDeserialized() { Mock<ODataDeserializerProvider> deserializerProvider = new Mock<ODataDeserializerProvider>(); deserializerProvider.Setup(d => d.GetEdmTypeDeserializer(It.IsAny<IEdmTypeReference>())).Returns<ODataEdmTypeDeserializer>(null); var deserializer = new ODataEntityDeserializer(_productEdmType, deserializerProvider.Object); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = _supplierEdmType.FullName() }); Assert.Throws<SerializationException>( () => deserializer.ReadEntry(entry, _readContext), "'ODataDemo.Supplier' cannot be deserialized using the ODataMediaTypeFormatter."); }
public void ApplyNavigationProperties_Calls_ApplyNavigationPropertyForEachNavigationLink() { // Arrange ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry()); entry.NavigationLinks.Add(new ODataNavigationLinkWithItems(new ODataNavigationLink())); entry.NavigationLinks.Add(new ODataNavigationLinkWithItems(new ODataNavigationLink())); Mock<ODataEntityDeserializer> deserializer = new Mock<ODataEntityDeserializer>(_productEdmType, _deserializerProvider); deserializer.CallBase = true; deserializer.Setup(d => d.ApplyNavigationProperty(42, entry.NavigationLinks[0], _readContext)).Verifiable(); deserializer.Setup(d => d.ApplyNavigationProperty(42, entry.NavigationLinks[1], _readContext)).Verifiable(); // Act deserializer.Object.ApplyNavigationProperties(42, entry, _readContext); // Assert deserializer.Verify(); }
public void ReadEntry_SetsExpectedAndActualEdmType_OnCreatedEdmObject_TypelessMode() { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); IEdmEntityTypeReference customerType = EdmLibHelpers.ToEdmTypeReference(model.Customer, isNullable: false).AsEntity(); ODataDeserializerContext readContext = new ODataDeserializerContext { Model = model.Model, ResourceType = typeof(IEdmObject) }; ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = model.SpecialCustomer.FullName(), Properties = new ODataProperty[0] }); ODataEntityDeserializer deserializer = new ODataEntityDeserializer(_deserializerProvider); // Act var result = deserializer.ReadEntry(entry, customerType, readContext); // Assert EdmEntityObject resource = Assert.IsType<EdmEntityObject>(result); Assert.Equal(model.SpecialCustomer, resource.ActualEdmType); Assert.Equal(model.Customer, resource.ExpectedEdmType); }
public void ApplyStructuralProperties_Calls_ApplyStructuralPropertyOnEachPropertyInEntry() { // Arrange var deserializer = new Mock<ODataEntityDeserializer>(_productEdmType, _deserializerProvider); ODataProperty[] properties = new[] { new ODataProperty(), new ODataProperty() }; ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { Properties = properties }); deserializer.CallBase = true; deserializer.Setup(d => d.ApplyStructuralProperty(42, properties[0], _readContext)).Verifiable(); deserializer.Setup(d => d.ApplyStructuralProperty(42, properties[1], _readContext)).Verifiable(); // Act deserializer.Object.ApplyStructuralProperties(42, entry, _readContext); // Assert deserializer.Verify(); }
public void ReadInline_Calls_ReadEntry() { // Arrange var deserializer = new Mock<ODataEntityDeserializer>(_productEdmType, _deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry()); ODataDeserializerContext readContext = new ODataDeserializerContext(); deserializer.CallBase = true; deserializer.Setup(d => d.ReadEntry(entry, readContext)).Returns(42).Verifiable(); // Act var result = deserializer.Object.ReadInline(entry, readContext); // Assert deserializer.Verify(); Assert.Equal(42, result); }
public void ReadEntry_DispatchesToRightDeserializer_IfEntityTypeNameIsDifferent() { // Arrange Mock<ODataEdmTypeDeserializer> supplierDeserializer = new Mock<ODataEdmTypeDeserializer>(_supplierEdmType, ODataPayloadKind.Entry); Mock<ODataDeserializerProvider> deserializerProvider = new Mock<ODataDeserializerProvider>(); var deserializer = new ODataEntityDeserializer(_productEdmType, deserializerProvider.Object); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = _supplierEdmType.FullName() }); deserializerProvider.Setup(d => d.GetEdmTypeDeserializer(It.IsAny<IEdmTypeReference>())).Returns(supplierDeserializer.Object); supplierDeserializer.Setup(d => d.ReadInline(entry, _readContext)).Returns(42).Verifiable(); // Act object result = deserializer.ReadEntry(entry, _readContext); // Assert Assert.Equal(42, result); supplierDeserializer.Verify(); }
/// <summary> /// Deserializes the given <paramref name="entryWrapper"/> under the given <paramref name="readContext"/>. /// </summary> /// <param name="entryWrapper">The OData entry to deserialize.</param> /// <param name="entityType">The entity type of the entry to deserialize.</param> /// <param name="readContext">The deserializer context.</param> /// <returns>The deserialized entity.</returns> public virtual object ReadEntry(ODataEntryWithNavigationLinks entryWrapper, IEdmEntityTypeReference entityType, ODataDeserializerContext readContext) { if (entryWrapper == null) { throw Error.ArgumentNull("entryWrapper"); } if (readContext == null) { throw Error.ArgumentNull("readContext"); } if (!String.IsNullOrEmpty(entryWrapper.Entry.TypeName) && entityType.FullName() != entryWrapper.Entry.TypeName) { // received a derived type in a base type deserializer. delegate it to the appropriate derived type deserializer. IEdmModel model = readContext.Model; if (model == null) { throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext); } IEdmEntityType actualType = model.FindType(entryWrapper.Entry.TypeName) as IEdmEntityType; if (actualType == null) { throw new ODataException(Error.Format(SRResources.EntityTypeNotInModel, entryWrapper.Entry.TypeName)); } if (actualType.IsAbstract) { string message = Error.Format(SRResources.CannotInstantiateAbstractEntityType, entryWrapper.Entry.TypeName); throw new ODataException(message); } IEdmTypeReference actualEntityType = new EdmEntityTypeReference(actualType, isNullable: false); ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(actualEntityType); if (deserializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeDeserialized, actualEntityType.FullName(), typeof(ODataMediaTypeFormatter).Name)); } object resource = deserializer.ReadInline(entryWrapper, actualEntityType, readContext); EdmStructuredObject structuredObject = resource as EdmStructuredObject; if (structuredObject != null) { structuredObject.ExpectedEdmType = entityType.EntityDefinition(); } return resource; } else { object resource = CreateEntityResource(entityType, readContext); ApplyEntityProperties(resource, entryWrapper, entityType, readContext); return resource; } }
public void ReadEntry_ThrowsODataException_EntityTypeNotInModel() { var deserializer = new ODataEntityDeserializer(_productEdmType, _deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = "MissingType" }); Assert.Throws<ODataException>( () => deserializer.ReadEntry(entry, _readContext), "Cannot find the entity type 'MissingType' in the model."); }
public void ReadEntry_ThrowsArgumentNull_ReadContext() { var deserializer = new ODataEntityDeserializer(_productEdmType, _deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry()); Assert.ThrowsArgumentNull( () => deserializer.ReadEntry(entry, readContext: null), "readContext"); }
public void ReadEntry_ThrowsODataException_CannotInstantiateAbstractEntityType() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.Entity<BaseType>().Abstract(); IEdmModel model = builder.GetEdmModel(); var deserializer = new ODataEntityDeserializer(_productEdmType, _deserializerProvider); ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(new ODataEntry { TypeName = "System.Web.Http.OData.Formatter.Deserialization.BaseType" }); Assert.Throws<ODataException>( () => deserializer.ReadEntry(entry, new ODataDeserializerContext { Model = model }), "An instance of the abstract entity type 'System.Web.Http.OData.Formatter.Deserialization.BaseType' was found. Abstract entity types cannot be instantiated."); }