public void WriteDeltaFeedInline_Sets_DeltaLink() { // Arrange IEnumerable instance = new object[0]; ODataDeltaFeed deltafeed = new ODataDeltaFeed { DeltaLink = new Uri("http://deltalink.com/") }; Mock <ODataDeltaFeedSerializer> serializer = new Mock <ODataDeltaFeedSerializer>(new DefaultODataSerializerProvider()); serializer.CallBase = true; serializer.Setup(s => s.CreateODataDeltaFeed(instance, _customersType, _writeContext)).Returns(deltafeed); var mockWriter = new Mock <ODataDeltaWriter>(); mockWriter.Setup(m => m.WriteStart(deltafeed)); mockWriter .Setup(m => m.WriteEnd()) .Callback(() => { Assert.Equal("http://deltalink.com/", deltafeed.DeltaLink.AbsoluteUri); }) .Verifiable(); // Act serializer.Object.WriteDeltaFeedInline(instance, _customersType, mockWriter.Object, _writeContext); // Assert mockWriter.Verify(); }
public void WriteDerivedEntity() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry derivedEntity = new ODataEntry() { TypeName = "MyNS.PhysicalProduct", Properties = new[] { new ODataProperty { Name = "Id", Value = new ODataPrimitiveValue(1) }, new ODataProperty { Name = "Name", Value = new ODataPrimitiveValue("car") }, new ODataProperty { Name = "Material", Value = new ODataPrimitiveValue("gold") }, }, }; ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType()); writer.WriteStart(feed); writer.WriteStart(derivedEntity); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); string payload = this.TestFinish(); payload.Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products/$delta\",\"value\":[{\"@odata.type\":\"#MyNS.PhysicalProduct\",\"Id\":1,\"Name\":\"car\",\"Material\":\"gold\"}]}"); }
public void WriteContainedEntityInDeltaFeed() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry containedEntry = new ODataEntry() { TypeName = "MyNS.ProductDetail", Properties = new[] { new ODataProperty { Name = "Id", Value = new ODataPrimitiveValue(1) }, new ODataProperty { Name = "Detail", Value = new ODataPrimitiveValue("made in china") }, }, }; containedEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = "MyNS.ProductDetail", NavigationSourceName = "Products(1)/Details", NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet }); ODataEntry containedInContainedEntity = new ODataEntry() { TypeName = "MyNS.ProductDetailItem", Properties = new[] { new ODataProperty { Name = "ItemId", Value = new ODataPrimitiveValue(1) }, new ODataProperty { Name = "Description", Value = new ODataPrimitiveValue("made by HCC") }, }, }; containedInContainedEntity.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = "MyNS.ProductDetailItem", NavigationSourceName = "Products(1)/Details(1)/Items", NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet }); ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType()); writer.WriteStart(feed); writer.WriteStart(containedEntry); writer.WriteEnd(); writer.WriteStart(containedInContainedEntity); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); this.TestPayload().Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Products(1)/Details/$entity\",\"Id\":1,\"Detail\":\"made in china\"},{\"@odata.context\":\"http://host/service/$metadata#Products(1)/Details(1)/Items/$entity\",\"ItemId\":1,\"Description\":\"made by HCC\"}]}"); }
public void WriteEntityInDeltaFeedWithSelectExpand() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry orderEntry = new ODataEntry() { Properties = new List <ODataProperty> { new ODataProperty { Name = "ShippingAddress", Value = new ODataComplexValue { Properties = new List <ODataProperty> { new ODataProperty { Name = "City", Value = "Shanghai" }, } } } }, SerializationInfo = new ODataFeedAndEntrySerializationInfo { NavigationSourceEntityTypeName = "Order", NavigationSourceKind = EdmNavigationSourceKind.EntitySet, NavigationSourceName = "Orders" }, }; var result = new ODataQueryOptionParser(this.GetModel(), this.GetCustomerType(), this.GetCustomers(), new Dictionary <string, string> { { "$expand", "Orders($select=ShippingAddress)" }, { "$select", "ContactName" } }).ParseSelectAndExpand(); ODataUri odataUri = new ODataUri() { ServiceRoot = new Uri("http://host/service"), SelectAndExpand = result }; var outputContext = CreateJsonLightOutputContext(this.stream, this.GetModel(), odataUri); ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType()); writer.WriteStart(feed); writer.WriteStart(orderEntry); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); string payload = this.TestFinish(); payload.Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products(ContactName,Orders,Orders(ShippingAddress))/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Orders/$entity\",\"ShippingAddress\":{\"City\":\"Shanghai\"}}]}"); }
public void CreateODataDeltaFeed_Sets_NextPageLinkForPageResult() { // Arrange ODataDeltaFeedSerializer serializer = new ODataDeltaFeedSerializer(new DefaultODataSerializerProvider()); Uri expectedNextLink = new Uri("http://nextlink.com"); const long ExpectedCountValue = 1000; var result = new PageResult <Customer>(_customers, expectedNextLink, ExpectedCountValue); // Act ODataDeltaFeed feed = serializer.CreateODataDeltaFeed(result, _customersType, new ODataSerializerContext()); // Assert Assert.Equal(expectedNextLink, feed.NextPageLink); }
public void WriteDeltaFeedInline_Writes_CreateODataFeedOutput() { // Arrange IEnumerable instance = new object[0]; ODataDeltaFeed deltafeed = new ODataDeltaFeed(); Mock <ODataDeltaFeedSerializer> serializer = new Mock <ODataDeltaFeedSerializer>(new DefaultODataSerializerProvider()); serializer.CallBase = true; serializer.Setup(s => s.CreateODataDeltaFeed(instance, _customersType, _writeContext)).Returns(deltafeed); Mock <ODataDeltaWriter> writer = new Mock <ODataDeltaWriter>(); writer.Setup(s => s.WriteStart(deltafeed)).Verifiable(); // Act serializer.Object.WriteDeltaFeedInline(instance, _customersType, writer.Object, _writeContext); // Assert writer.Verify(); }
public static void WriteDeltaFeed(ODataDeltaWriter deltaWriter, List <ODataItem> items, bool?countOption, Uri newDeltaLink) { var deltaFeed = new ODataDeltaFeed { DeltaLink = newDeltaLink }; if (countOption == true) { deltaFeed.Count = items.Cast <object>().Count(); } deltaWriter.WriteStart(deltaFeed); foreach (ODataItem item in items) { var entry = item as ODataEntry; var deletedEntry = item as ODataDeltaDeletedEntry; var deltaLink = item as ODataDeltaLink; var deltaDeletedLink = item as ODataDeltaDeletedLink; if (entry != null) { deltaWriter.WriteStart(entry); deltaWriter.WriteEnd(); } else if (deletedEntry != null) { deltaWriter.WriteDeltaDeletedEntry(deletedEntry); } else if (deltaLink != null) { deltaWriter.WriteDeltaLink(deltaLink); } else if (deltaDeletedLink != null) { deltaWriter.WriteDeltaDeletedLink(deltaDeletedLink); } } deltaWriter.WriteEnd(); }
public void WriteDerivedEntityWithSerilizationInfo() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry derivedEntity = new ODataEntry() { TypeName = "MyNS.PhysicalProduct", Properties = new[] { new ODataProperty { Name = "Id", Value = new ODataPrimitiveValue(1) }, new ODataProperty { Name = "Name", Value = new ODataPrimitiveValue("car") }, new ODataProperty { Name = "Material", Value = new ODataPrimitiveValue("gold") }, }, SerializationInfo = new ODataFeedAndEntrySerializationInfo() { ExpectedTypeName = "MyNS.Product", NavigationSourceEntityTypeName = "MyNS.Product", NavigationSourceName = "Products", } }; ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetCustomers(), this.GetCustomerType()); writer.WriteStart(feed); writer.WriteStart(derivedEntity); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); this.TestPayload().Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Customers/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Products/$entity\",\"@odata.type\":\"#MyNS.PhysicalProduct\",\"Id\":1,\"Name\":\"car\",\"Material\":\"gold\"}]}"); }
public void RequestDeltaLink() { var customersSet = Model.FindDeclaredEntitySet("Customers"); var customerType = customersSet.EntityType(); ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings() { BaseUri = ServiceBaseUri }; foreach (var mimeType in deltaMimeTypes) { var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + "$delta", UriKind.Absolute)); requestMessage.SetHeader("Accept", mimeType); var responseMessage = requestMessage.GetResponse(); Assert.AreEqual(200, responseMessage.StatusCode); if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata)) { using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, Model)) { var deltaReader = messageReader.CreateODataDeltaReader(customersSet, customerType); while (deltaReader.Read()) { if (deltaReader.State == ODataDeltaReaderState.DeltaEntryEnd) { ODataEntry entry = deltaReader.Item as ODataEntry; } else if (deltaReader.State == ODataDeltaReaderState.FeedEnd) { ODataDeltaFeed feed = deltaReader.Item as ODataDeltaFeed; } } Assert.AreEqual(ODataDeltaReaderState.Completed, deltaReader.State); } } } }
/// <summary> /// Create the <see cref="ODataDeltaFeed"/> 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="ODataDeltaFeed"/> object.</returns> public virtual ODataDeltaFeed CreateODataDeltaFeed(IEnumerable feedInstance, IEdmCollectionTypeReference feedType, ODataSerializerContext writeContext) { ODataDeltaFeed feed = new ODataDeltaFeed(); 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; feed.DeltaLink = writeContext.Request.ODataProperties().DeltaLink; 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); }
/// <summary> /// Start writing a delta feed. /// </summary> /// <param name="deltaFeed">Delta feed/collection to write.</param> public override void WriteStart(ODataDeltaFeed deltaFeed) { this.VerifyCanWriteStartDeltaFeed(true, deltaFeed); this.WriteStartDeltaFeedImplementation(deltaFeed); }
/// <summary> /// Finish writing a delta feed. /// </summary> /// <param name="feed">The feed to write.</param> private void EndDeltaFeed(ODataDeltaFeed feed) { Debug.Assert(feed != null, "feed != null"); // End the array which holds the entries in the feed. this.jsonWriter.EndArrayScope(); // Write custom instance annotations this.jsonLightEntryAndFeedSerializer.InstanceAnnotationWriter.WriteInstanceAnnotations(feed.InstanceAnnotations, this.CurrentDeltaFeedScope.InstanceAnnotationWriteTracker); // Write the next link if it's available. this.WriteDeltaFeedNextLink(feed); // Write the delta link if it's available. this.WriteDeltaFeedDeltaLink(feed); // Close the object wrapper. this.jsonWriter.EndObjectScope(); }
/// <summary> /// Convert DeltaFeed to ODataFeed. /// </summary> /// <param name="deltaFeed">The DeltaFeed to convert.</param> /// <returns>The converted Feed.</returns> internal static ODataFeed ToODataFeed(ODataDeltaFeed deltaFeed) { Debug.Assert(deltaFeed != null, "deltaFeed != null"); var result = Clone(deltaFeed); result.SetSerializationInfo(ToFeedAndEntrySerializationInfo(deltaFeed.SerializationInfo)); return result; }
public void WriteDerivedEntityWithSerilizationInfo() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry derivedEntity = new ODataEntry() { TypeName = "MyNS.PhysicalProduct", Properties = new[] { new ODataProperty {Name = "Id", Value = new ODataPrimitiveValue(1)}, new ODataProperty {Name = "Name", Value = new ODataPrimitiveValue("car")}, new ODataProperty {Name = "Material", Value = new ODataPrimitiveValue("gold")}, }, SerializationInfo = new ODataFeedAndEntrySerializationInfo() { ExpectedTypeName = "MyNS.Product", NavigationSourceEntityTypeName = "MyNS.Product", NavigationSourceName = "Products", } }; ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetCustomers(), this.GetCustomerType()); writer.WriteStart(feed); writer.WriteStart(derivedEntity); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); this.TestPayload().Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Customers/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Products/$entity\",\"@odata.type\":\"#MyNS.PhysicalProduct\",\"Id\":1,\"Name\":\"car\",\"Material\":\"gold\"}]}"); }
/// <summary> /// Start writing a delta feed. /// </summary> /// <param name="feed">The feed to write.</param> private void StartDeltaFeed(ODataDeltaFeed feed) { Debug.Assert(feed != null, "feed != null"); Debug.Assert(this.IsTopLevel, "Delta feed must be on top level."); this.jsonWriter.StartObjectScope(); this.WriteDeltaFeedContextUri(); this.WriteDeltaFeedCount(feed); this.WriteDeltaFeedNextLink(feed); this.WriteDeltaFeedDeltaLink(feed); this.WriteDeltaFeedInstanceAnnotations(feed); this.WriteDeltaFeedValueStart(); }
/// <summary> /// Provide additional serialization information to the <see cref="ODataDeltaWriter"/> for <paramref name="deltaFeed"/>. /// </summary> /// <param name="deltaFeed">The instance to set the serialization info.</param> /// <param name="serializationInfo">The serialization info to set.</param> public static void SetSerializationInfo(this ODataDeltaFeed deltaFeed, ODataDeltaFeedSerializationInfo serializationInfo) { ExceptionUtils.CheckArgumentNotNull(deltaFeed, "deltaFeed"); deltaFeed.SerializationInfo = serializationInfo; }
public void WriteEntityInDeltaFeedWithSelectExpand() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry orderEntry= new ODataEntry() { Properties = new List<ODataProperty> { new ODataProperty { Name = "ShippingAddress", Value = new ODataComplexValue { Properties = new List<ODataProperty> { new ODataProperty { Name = "City", Value = "Shanghai" }, } } } }, SerializationInfo = new ODataFeedAndEntrySerializationInfo { NavigationSourceEntityTypeName = "Order", NavigationSourceKind = EdmNavigationSourceKind.EntitySet, NavigationSourceName = "Orders" }, }; var result = new ODataQueryOptionParser(this.GetModel(), this.GetCustomerType(), this.GetCustomers(), new Dictionary<string, string> { { "$expand", "Orders($select=ShippingAddress)" }, { "$select", "ContactName" } }).ParseSelectAndExpand(); ODataUri odataUri = new ODataUri() { ServiceRoot = new Uri("http://host/service"), SelectAndExpand = result }; var outputContext = CreateJsonLightOutputContext(this.stream, this.GetModel(), false, odataUri); ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType()); writer.WriteStart(feed); writer.WriteStart(orderEntry); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); this.TestPayload().Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products(ContactName,Orders,Orders(ShippingAddress))/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Orders/$entity\",\"ShippingAddress\":{\"City\":\"Shanghai\"}}]}"); }
private void WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataDeltaWriter writer, ODataSerializerContext writeContext) { Contract.Assert(writer != null); Contract.Assert(writeContext != null); Contract.Assert(enumerable != null); Contract.Assert(feedType != null); ODataDeltaFeed deltaFeed = CreateODataDeltaFeed(enumerable, feedType.AsCollection(), writeContext); if (deltaFeed == null) { throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, DeltaFeed)); } // save this for later to support JSON odata.streaming. Uri nextPageLink = deltaFeed.NextPageLink; deltaFeed.NextPageLink = null; //Start writing of the Delta Feed writer.WriteStart(deltaFeed); //Iterate over all the entries present and select the appropriate write method. //Write method creates ODataDeltaDeletedEntry / ODataDeltaDeletedLink / ODataDeltaLink or ODataEntry. foreach (object entry in enumerable) { if (entry == null) { throw new SerializationException(SRResources.NullElementInCollection); } IEdmChangedObject edmChangedObject = entry as IEdmChangedObject; if (edmChangedObject == null) { throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, enumerable.GetType().FullName)); } switch (edmChangedObject.DeltaKind) { case EdmDeltaEntityKind.DeletedEntry: WriteDeltaDeletedEntry(entry, writer, writeContext); break; case EdmDeltaEntityKind.DeletedLinkEntry: WriteDeltaDeletedLink(entry, writer, writeContext); break; case EdmDeltaEntityKind.LinkEntry: WriteDeltaLink(entry, writer, writeContext); break; case EdmDeltaEntityKind.Entry: { IEdmEntityTypeReference elementType = GetEntityType(feedType); ODataEntityTypeSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(elementType) as ODataEntityTypeSerializer; if (entrySerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName(), typeof(ODataMediaTypeFormatter).Name)); } entrySerializer.WriteDeltaObjectInline(entry, elementType, writer, writeContext); break; } default: break; } } // Subtle and surprising behavior: If the NextPageLink property is set before calling WriteStart(feed), // the next page link will be written early in a manner not compatible with odata.streaming=true. Instead, if // the next page link is not set when calling WriteStart(feed) but is instead set later on that feed // object before calling WriteEnd(), the next page link will be written at the end, as required for // odata.streaming=true support. if (nextPageLink != null) { deltaFeed.NextPageLink = nextPageLink; } //End Writing of the Delta Feed writer.WriteEnd(); }
public void WriteContainedEntityInDeltaFeed() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry containedEntry = new ODataEntry() { TypeName = "MyNS.ProductDetail", Properties = new[] { new ODataProperty {Name = "Id", Value = new ODataPrimitiveValue(1)}, new ODataProperty {Name = "Detail", Value = new ODataPrimitiveValue("made in china")}, }, }; containedEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = "MyNS.ProductDetail", NavigationSourceName = "Products(1)/Details", NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet }); ODataEntry containedInContainedEntity = new ODataEntry() { TypeName = "MyNS.ProductDetailItem", Properties = new[] { new ODataProperty {Name = "ItemId", Value = new ODataPrimitiveValue(1)}, new ODataProperty {Name = "Description", Value = new ODataPrimitiveValue("made by HCC")}, }, }; containedInContainedEntity.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = "MyNS.ProductDetailItem", NavigationSourceName = "Products(1)/Details(1)/Items", NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet }); ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType()); writer.WriteStart(feed); writer.WriteStart(containedEntry); writer.WriteEnd(); writer.WriteStart(containedInContainedEntity); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); this.TestPayload().Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Products(1)/Details/$entity\",\"Id\":1,\"Detail\":\"made in china\"},{\"@odata.context\":\"http://host/service/$metadata#Products(1)/Details(1)/Items/$entity\",\"ItemId\":1,\"Description\":\"made by HCC\"}]}"); }
/// <summary> /// Writes the odata.deltaLink annotation for a delta feed if the delta link is specified on the feed. /// </summary> /// <param name="feed">The feed to write the delta link for.</param> private void WriteDeltaFeedDeltaLink(ODataDeltaFeed feed) { Debug.Assert(feed != null, "feed != null"); // If we haven't written the delta link yet and it's available, write it. Uri deltaLink = feed.DeltaLink; if (deltaLink != null && !this.CurrentDeltaFeedScope.DeltaLinkWritten) { this.odataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataDeltaLink); this.jsonWriter.WriteValue(this.jsonLightEntryAndFeedSerializer.UriToString(deltaLink)); this.CurrentDeltaFeedScope.DeltaLinkWritten = true; } }
public void WriteDerivedEntity() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry derivedEntity = new ODataEntry() { TypeName = "MyNS.PhysicalProduct", Properties = new[] { new ODataProperty {Name = "Id", Value = new ODataPrimitiveValue(1)}, new ODataProperty {Name = "Name", Value = new ODataPrimitiveValue("car")}, new ODataProperty {Name = "Material", Value = new ODataPrimitiveValue("gold")}, }, }; ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType()); writer.WriteStart(feed); writer.WriteStart(derivedEntity); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); string payload = this.TestFinish(); payload.Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products/$delta\",\"value\":[{\"@odata.type\":\"#MyNS.PhysicalProduct\",\"Id\":1,\"Name\":\"car\",\"Material\":\"gold\"}]}"); }
/// <summary> /// Start writing a delta feed - implementation of the actual functionality. /// </summary> /// <param name="feed">The feed to write.</param> private void WriteStartDeltaFeedImplementation(ODataDeltaFeed feed) { this.EnterScope(WriterState.DeltaFeed, feed); this.InterceptException(() => this.StartDeltaFeed(feed)); }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { var token = HttpUtility.ParseQueryString(RequestUri.Query).Get("$token"); if (string.IsNullOrEmpty(token)) { deltaToken = "common"; } else { deltaToken = token; } if (deltaToken == "common") { originalUri = new Uri(ServiceConstants.ServiceBaseUri, "Customers?$expand=Orders"); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { var entitySet = this.DataSource.Model.FindDeclaredEntitySet("Customers"); var entityType = entitySet.EntityType(); ODataDeltaWriter deltaWriter = messageWriter.CreateODataDeltaWriter(entitySet, entityType); var deltaFeed = new ODataDeltaFeed(); var deltaEntry = new ODataEntry { Id = new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name + "(1)"), Properties = new[] { new ODataProperty { Name = "FirstName", Value = "GGGG" } } }; var deletedLink = new ODataDeltaDeletedLink( new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name + "(1)"), new Uri(ServiceConstants.ServiceBaseUri, "Orders(8)"), "Orders"); var addedLink = new ODataDeltaLink( new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name + "(1)"), new Uri(ServiceConstants.ServiceBaseUri, "Orders(7)"), "Orders"); var navigationEntry = new ODataEntry { Id = new Uri(ServiceConstants.ServiceBaseUri, "Orders(100)"), TypeName = "Microsoft.Test.OData.Services.ODataWCFService.Order", Properties = new[] { new ODataProperty { Name = "OrderID", Value = 100 }, new ODataProperty { Name = "OrderDate", Value = new DateTimeOffset(DateTime.Now) } } }; navigationEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceEntityTypeName = "Microsoft.Test.OData.Services.ODataWCFService.Order", NavigationSourceKind = EdmNavigationSourceKind.EntitySet, NavigationSourceName = "Orders" }); var deletedEntry = new ODataDeltaDeletedEntry( new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name + "(2)").AbsoluteUri, DeltaDeletedEntryReason.Deleted); deltaFeed.DeltaLink = new Uri(ServiceConstants.ServiceBaseUri, "$delta?$token=common"); deltaWriter.WriteStart(deltaFeed); deltaWriter.WriteStart(deltaEntry); deltaWriter.WriteEnd(); deltaWriter.WriteDeltaDeletedLink(deletedLink); deltaWriter.WriteDeltaLink(addedLink); deltaWriter.WriteStart(navigationEntry); deltaWriter.WriteEnd(); deltaWriter.WriteDeltaDeletedEntry(deletedEntry); deltaWriter.WriteEnd(); } } else if (deltaToken == "containment") { originalUri = new Uri(ServiceConstants.ServiceBaseUri, "Accounts(103)/MyPaymentInstruments?$expand=BillingStatements"); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { var accountsSet = this.DataSource.Model.FindDeclaredEntitySet("Accounts"); var accountType = accountsSet.EntityType(); var myPisNav = accountType.FindProperty("MyPaymentInstruments") as IEdmNavigationProperty; var piSet = accountsSet.FindNavigationTarget(myPisNav); var piType = piSet.EntityType(); ODataDeltaWriter deltaWriter = messageWriter.CreateODataDeltaWriter(piSet as IEdmContainedEntitySet, piType); var deltaFeed = new ODataDeltaFeed(); var deltaEntry = new ODataEntry { Id = new Uri(ServiceConstants.ServiceBaseUri, "Accounts(103)/MyPaymentInstruments(103901)"), Properties = new[] { new ODataProperty { Name = "FriendlyName", Value = "GGGG" } } }; var deletedEntry = new ODataDeltaDeletedEntry( new Uri(ServiceConstants.ServiceBaseUri, "Accounts(103)/MyPaymentInstruments(103901)/BillingStatements(103901001)").AbsoluteUri, DeltaDeletedEntryReason.Deleted); deletedEntry.SetSerializationInfo(new ODataDeltaSerializationInfo() { NavigationSourceName = "Accounts(103)/MyPaymentInstruments(103901)/BillingStatements" }); var deletedLink = new ODataDeltaDeletedLink( new Uri(ServiceConstants.ServiceBaseUri, "Accounts(103)/MyPaymentInstruments(103901)"), new Uri(ServiceConstants.ServiceBaseUri, "Accounts(103)/MyPaymentInstruments(103901)/BillingStatements(103901001)"), "BillingStatements"); var navigationEntry = new ODataEntry { Id = new Uri(ServiceConstants.ServiceBaseUri, "Accounts(103)/MyPaymentInstruments(103901)/BillingStatements(103901005)"), TypeName = "Microsoft.Test.OData.Services.ODataWCFService.Statement", Properties = new[] { new ODataProperty { Name = "TransactionType", Value = "OnlinePurchase" }, new ODataProperty { Name = "TransactionDescription", Value = "unknown purchase" }, new ODataProperty { Name = "Amount", Value = 32.1 } } }; navigationEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceEntityTypeName = "Microsoft.Test.OData.Services.ODataWCFService.Statement", NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet, NavigationSourceName = "Accounts(103)/MyPaymentInstruments(103901)/BillingStatements" }); var addedLink = new ODataDeltaLink( new Uri(ServiceConstants.ServiceBaseUri, "Accounts(103)/MyPaymentInstruments(103901)"), new Uri(ServiceConstants.ServiceBaseUri, "Accounts(103)/MyPaymentInstruments(103901)/BillingStatements(103901005)"), "BillingStatements"); deltaWriter.WriteStart(deltaFeed); deltaWriter.WriteStart(deltaEntry); deltaWriter.WriteEnd(); deltaWriter.WriteDeltaDeletedEntry(deletedEntry); deltaWriter.WriteDeltaDeletedLink(deletedLink); deltaWriter.WriteStart(navigationEntry); deltaWriter.WriteEnd(); deltaWriter.WriteDeltaLink(addedLink); deltaWriter.WriteEnd(); } } else if (deltaToken == "derived") { originalUri = new Uri(ServiceConstants.ServiceBaseUri, "People?$expand=Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders"); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { var peopleSet = this.DataSource.Model.FindDeclaredEntitySet("People"); var personType = peopleSet.EntityType(); ODataDeltaWriter deltaWriter = messageWriter.CreateODataDeltaWriter(peopleSet, personType); var deltaFeed = new ODataDeltaFeed(); var deltaEntry = new ODataEntry { Id = new Uri(ServiceConstants.ServiceBaseUri, "People(1)"), TypeName = "Microsoft.Test.OData.Services.ODataWCFService.Customer", Properties = new[] { new ODataProperty { Name = "City", Value = "GGGG" } } }; var addedLink = new ODataDeltaLink( new Uri(ServiceConstants.ServiceBaseUri, "People(1)"), new Uri(ServiceConstants.ServiceBaseUri, "Orders(7)"), "Orders"); var deletedEntry = new ODataDeltaDeletedEntry( new Uri(ServiceConstants.ServiceBaseUri, "People(2)").AbsoluteUri, DeltaDeletedEntryReason.Changed); var deletedLink = new ODataDeltaDeletedLink( new Uri(ServiceConstants.ServiceBaseUri, "People(1)"), new Uri(ServiceConstants.ServiceBaseUri, "Orders(8)"), "Orders"); var navigationEntry = new ODataEntry { Id = new Uri(ServiceConstants.ServiceBaseUri, "Orders(100)"), TypeName = "Microsoft.Test.OData.Services.ODataWCFService.Order", Properties = new[] { new ODataProperty { Name = "OrderID", Value = 100 }, new ODataProperty { Name = "OrderDate", Value = new DateTimeOffset(DateTime.Now) } } }; navigationEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceEntityTypeName = "Microsoft.Test.OData.Services.ODataWCFService.Order", NavigationSourceKind = EdmNavigationSourceKind.EntitySet, NavigationSourceName = "Orders" }); deltaWriter.WriteStart(deltaFeed); deltaWriter.WriteStart(deltaEntry); deltaWriter.WriteEnd(); deltaWriter.WriteDeltaDeletedLink(deletedLink); deltaWriter.WriteDeltaLink(addedLink); deltaWriter.WriteStart(navigationEntry); deltaWriter.WriteEnd(); deltaWriter.WriteDeltaDeletedEntry(deletedEntry); deltaWriter.WriteEnd(); } } else if (deltaToken == "projection") { originalUri = new Uri(ServiceConstants.ServiceBaseUri, "Customers?$select=PersonID,FirstName,LastName&$expand=Orders($select=OrderID,OrderDate)"); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { var entitySet = this.DataSource.Model.FindDeclaredEntitySet("Customers"); var entityType = entitySet.EntityType(); ODataDeltaWriter deltaWriter = messageWriter.CreateODataDeltaWriter(entitySet, entityType); var deltaFeed = new ODataDeltaFeed(); var deltaEntry1 = new ODataEntry { Properties = new[] { new ODataProperty { Name = "PersonID", Value = 1 }, new ODataProperty { Name = "FirstName", Value = "FFFF" }, new ODataProperty { Name = "LastName", Value = "LLLL" }, new ODataProperty { Name = "City", Value = "Beijing" } } }; var deletedLink = new ODataDeltaDeletedLink( new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name + "(1)"), new Uri(ServiceConstants.ServiceBaseUri, "Orders(8)"), "Orders"); var addedLink = new ODataDeltaLink( new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name + "(1)"), new Uri(ServiceConstants.ServiceBaseUri, "Orders(7)"), "Orders"); var navigationEntry = new ODataEntry { Id = new Uri(ServiceConstants.ServiceBaseUri, "Orders(100)"), TypeName = "Microsoft.Test.OData.Services.ODataWCFService.Order", Properties = new[] { new ODataProperty { Name = "OrderID", Value = 100 }, new ODataProperty { Name = "OrderDate", Value = new DateTimeOffset(DateTime.Now) } } }; navigationEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceEntityTypeName = "Microsoft.Test.OData.Services.ODataWCFService.Order", NavigationSourceKind = EdmNavigationSourceKind.EntitySet, NavigationSourceName = "Orders" }); var deletedOrderEntry = new ODataDeltaDeletedEntry( new Uri(ServiceConstants.ServiceBaseUri, "Orders(20)").AbsoluteUri, DeltaDeletedEntryReason.Deleted); deletedOrderEntry.SetSerializationInfo(new ODataDeltaSerializationInfo() { NavigationSourceName = "Orders" }); var deltaEntry2 = new ODataEntry { Properties = new[] { new ODataProperty { Name = "PersonID", Value = 2 }, new ODataProperty { Name = "FirstName", Value = "AAAA" }, } }; deltaWriter.WriteStart(deltaFeed); deltaWriter.WriteStart(deltaEntry1); deltaWriter.WriteEnd(); deltaWriter.WriteDeltaDeletedLink(deletedLink); deltaWriter.WriteDeltaLink(addedLink); deltaWriter.WriteStart(navigationEntry); deltaWriter.WriteEnd(); deltaWriter.WriteDeltaDeletedEntry(deletedOrderEntry); deltaWriter.WriteStart(deltaEntry2); deltaWriter.WriteEnd(); deltaWriter.WriteEnd(); } } }
private void ValidateTuples(IEnumerable <Tuple <ODataItem, ODataDeltaReaderState> > tuples, Uri nextLink = null, Uri feedDeltaLink = null) { foreach (var tuple in tuples) { switch (tuple.Item2) { case ODataDeltaReaderState.DeltaFeedStart: ODataDeltaFeed deltaFeed = tuple.Item1 as ODataDeltaFeed; Assert.NotNull(deltaFeed); if (deltaFeed.Count.HasValue) { Assert.Equal(deltaFeed.Count, feed.Count); } break; case ODataDeltaReaderState.FeedEnd: Assert.NotNull(tuple.Item1 as ODataDeltaFeed); if (nextLink != null) { Assert.Equal(nextLink, ((ODataDeltaFeed)tuple.Item1).NextPageLink); } if (feedDeltaLink != null) { Assert.Equal(feedDeltaLink, ((ODataDeltaFeed)tuple.Item1).DeltaLink); } break; case ODataDeltaReaderState.DeltaEntryStart: Assert.True(tuple.Item1 is ODataEntry); break; case ODataDeltaReaderState.DeltaEntryEnd: var deltaEntry = tuple.Item1 as ODataEntry; Assert.NotNull(deltaEntry); Assert.NotNull(deltaEntry.Id); if (this.IdEqual(deltaEntry.Id, customerUpdated.Id)) { Assert.True(PropertiesEqual(deltaEntry.Properties, customerUpdated.Properties)); } else if (this.IdEqual(deltaEntry.Id, order10643.Id)) { Assert.True(this.PropertiesEqual(deltaEntry.Properties, order10643.Properties)); } else { Assert.True(false, "Invalid id read."); } break; case ODataDeltaReaderState.DeltaDeletedEntry: var deltaDeletedEntry = tuple.Item1 as ODataDeltaDeletedEntry; Assert.NotNull(deltaDeletedEntry); Assert.True(deltaDeletedEntry.Id.EndsWith(customerDeleted.Id)); Assert.Equal(deltaDeletedEntry.Reason, customerDeleted.Reason); break; case ODataDeltaReaderState.DeltaLink: var deltaLink = tuple.Item1 as ODataDeltaLink; Assert.NotNull(deltaLink); Assert.True(this.IdEqual(deltaLink.Source, linkToOrder10645.Source)); Assert.Equal(deltaLink.Relationship, linkToOrder10645.Relationship); Assert.True(this.IdEqual(deltaLink.Target, linkToOrder10645.Target)); break; case ODataDeltaReaderState.DeltaDeletedLink: var deltaDeletedLink = tuple.Item1 as ODataDeltaDeletedLink; Assert.NotNull(deltaDeletedLink); Assert.True(this.IdEqual(deltaDeletedLink.Source, linkToOrder10643.Source)); Assert.Equal(deltaDeletedLink.Relationship, linkToOrder10643.Relationship); Assert.True(this.IdEqual(deltaDeletedLink.Target, linkToOrder10643.Target)); break; default: Assert.True(false, "Wrong reader state."); break; } } }
/// <summary> /// Asynchronously start writing a delta feed. /// </summary> /// <param name="deltaFeed">Delta feed/collection to write.</param> /// <returns>A task instance that represents the asynchronous write operation.</returns> public override Task WriteStartAsync(ODataDeltaFeed deltaFeed) { this.VerifyCanWriteStartDeltaFeed(false, deltaFeed); return TaskUtils.GetTaskForSynchronousOperation(() => this.WriteStartDeltaFeedImplementation(deltaFeed)); }
public void WriteContainedEntityInDeltaFeedWithSelectExpand() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry entry = new ODataEntry() { TypeName = "MyNS.Product", Properties = new[] { new ODataProperty {Name = "Id", Value = new ODataPrimitiveValue(1)}, new ODataProperty {Name = "Name", Value = new ODataPrimitiveValue("Car")}, }, }; ODataEntry containedEntry = new ODataEntry() { TypeName = "MyNS.ProductDetail", Properties = new[] { new ODataProperty {Name = "Id", Value = new ODataPrimitiveValue(1)}, new ODataProperty {Name = "Detail", Value = new ODataPrimitiveValue("made in china")}, }, }; containedEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = "MyNS.ProductDetail", NavigationSourceName = "Products(1)/Details", NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet }); var result = new ODataQueryOptionParser(this.GetModel(), this.GetProductType(), this.GetProducts(), new Dictionary<string, string> { { "$expand", "Details($select=Detail)" }, { "$select", "Name" } }).ParseSelectAndExpand(); ODataUri odataUri = new ODataUri() { ServiceRoot = new Uri("http://host/service"), SelectAndExpand = result }; var outputContext = CreateJsonLightOutputContext(this.stream, this.GetModel(), false, odataUri); ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType()); writer.WriteStart(feed); writer.WriteStart(containedEntry); writer.WriteEnd(); writer.WriteStart(entry); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); this.TestPayload().Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products(Name,Details,Details(Detail))/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Products(1)/Details/$entity\",\"Id\":1,\"Detail\":\"made in china\"},{\"Id\":1,\"Name\":\"Car\"}]}"); }
/// <summary> /// Verifies that calling WriteStart delta feed is valid. /// </summary> /// <param name="synchronousCall">true if the call is to be synchronous; false otherwise.</param> /// <param name="deltaFeed">Feed/collection to write.</param> private void VerifyCanWriteStartDeltaFeed(bool synchronousCall, ODataDeltaFeed deltaFeed) { ExceptionUtils.CheckArgumentNotNull(deltaFeed, " delta feed"); this.VerifyNotDisposed(); this.VerifyCallAllowed(synchronousCall); this.StartPayloadInStartState(); }
public void WriteContainedEntityInDeltaFeedWithSelectExpand() { this.TestInit(this.GetModel()); ODataDeltaFeed feed = new ODataDeltaFeed(); ODataEntry entry = new ODataEntry() { TypeName = "MyNS.Product", Properties = new[] { new ODataProperty { Name = "Id", Value = new ODataPrimitiveValue(1) }, new ODataProperty { Name = "Name", Value = new ODataPrimitiveValue("Car") }, }, }; ODataEntry containedEntry = new ODataEntry() { TypeName = "MyNS.ProductDetail", Properties = new[] { new ODataProperty { Name = "Id", Value = new ODataPrimitiveValue(1) }, new ODataProperty { Name = "Detail", Value = new ODataPrimitiveValue("made in china") }, }, }; containedEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = "MyNS.ProductDetail", NavigationSourceName = "Products(1)/Details", NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet }); var result = new ODataQueryOptionParser(this.GetModel(), this.GetProductType(), this.GetProducts(), new Dictionary <string, string> { { "$expand", "Details($select=Detail)" }, { "$select", "Name" } }).ParseSelectAndExpand(); ODataUri odataUri = new ODataUri() { ServiceRoot = new Uri("http://host/service"), SelectAndExpand = result }; var outputContext = CreateJsonLightOutputContext(this.stream, this.GetModel(), odataUri); ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType()); writer.WriteStart(feed); writer.WriteStart(containedEntry); writer.WriteEnd(); writer.WriteStart(entry); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); string payload = this.TestFinish(); payload.Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products(Name,Details,Details(Detail))/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Products(1)/Details/$entity\",\"Id\":1,\"Detail\":\"made in china\"},{\"Id\":1,\"Name\":\"Car\"}]}"); }
/// <summary> /// Writes the odata.count annotation for a feed if it has not been written yet (and the count is specified on the feed). /// </summary> /// <param name="feed">The feed to write the count for.</param> private void WriteDeltaFeedCount(ODataDeltaFeed feed) { Debug.Assert(feed != null, "feed != null"); // If we haven't written the count yet and it's available, write it. long? count = feed.Count; if (count.HasValue) { this.odataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataCount); this.jsonWriter.WriteValue(count.Value); } }
private void WriteAnnotationAtEndInDeltaFeed(string expectedPayload, long? count, Uri nextLink, Uri deltaLink) { Action<ODataDeltaWriter> action = (odataWriter) => { var feedToWrite = new ODataDeltaFeed { Id = new Uri("urn:feedId") }; odataWriter.WriteStart(feedToWrite); feedToWrite.InstanceAnnotations.Add(new ODataInstanceAnnotation("Custom.EndAnnotation", PrimitiveValue1)); feedToWrite.Count = count; feedToWrite.NextPageLink = nextLink; feedToWrite.DeltaLink = deltaLink; odataWriter.WriteEnd(); }; WriteDeltaFeedAnnotationsAndValidatePayload(action, EntitySet, expectedPayload); }
/// <summary> /// Writes the instance annotions for a delta feed. /// </summary> /// <param name="feed">The feed to write instance annotations for.</param> private void WriteDeltaFeedInstanceAnnotations(ODataDeltaFeed feed) { Debug.Assert(feed != null, "feed != null"); this.jsonLightEntryAndFeedSerializer.InstanceAnnotationWriter.WriteInstanceAnnotations(feed.InstanceAnnotations, this.CurrentDeltaFeedScope.InstanceAnnotationWriteTracker); }
private void ValidateTuples(IEnumerable <Tuple <ODataItem, ODataDeltaReaderState, ODataReaderState> > tuples, Uri nextLink = null, Uri feedDeltaLink = null) { foreach (var tuple in tuples) { switch (tuple.Item2) { case ODataDeltaReaderState.DeltaFeedStart: ODataDeltaFeed deltaFeed = tuple.Item1 as ODataDeltaFeed; Assert.NotNull(deltaFeed); if (deltaFeed.Count.HasValue) { Assert.Equal(deltaFeed.Count, feed.Count); } break; case ODataDeltaReaderState.FeedEnd: Assert.NotNull(tuple.Item1 as ODataDeltaFeed); if (nextLink != null) { Assert.Equal(nextLink, ((ODataDeltaFeed)tuple.Item1).NextPageLink); } if (feedDeltaLink != null) { Assert.Equal(feedDeltaLink, ((ODataDeltaFeed)tuple.Item1).DeltaLink); } break; case ODataDeltaReaderState.DeltaEntryStart: Assert.True(tuple.Item1 is ODataEntry); break; case ODataDeltaReaderState.DeltaEntryEnd: var deltaEntry = tuple.Item1 as ODataEntry; Assert.NotNull(deltaEntry); Assert.NotNull(deltaEntry.Id); if (this.IdEqual(deltaEntry.Id, customerUpdated.Id)) { Assert.True(PropertiesEqual(deltaEntry.Properties, customerUpdated.Properties)); } else if (this.IdEqual(deltaEntry.Id, order10643.Id)) { Assert.True(this.PropertiesEqual(deltaEntry.Properties, order10643.Properties)); } else { Assert.True(false, "Invalid id read."); } break; case ODataDeltaReaderState.DeltaDeletedEntry: var deltaDeletedEntry = tuple.Item1 as ODataDeltaDeletedEntry; Assert.NotNull(deltaDeletedEntry); Assert.True(deltaDeletedEntry.Id.EndsWith(customerDeleted.Id)); Assert.Equal(deltaDeletedEntry.Reason, customerDeleted.Reason); break; case ODataDeltaReaderState.DeltaLink: var deltaLink = tuple.Item1 as ODataDeltaLink; Assert.NotNull(deltaLink); Assert.True(this.IdEqual(deltaLink.Source, linkToOrder10645.Source)); Assert.Equal(deltaLink.Relationship, linkToOrder10645.Relationship); Assert.True(this.IdEqual(deltaLink.Target, linkToOrder10645.Target)); break; case ODataDeltaReaderState.DeltaDeletedLink: var deltaDeletedLink = tuple.Item1 as ODataDeltaDeletedLink; Assert.NotNull(deltaDeletedLink); Assert.True(this.IdEqual(deltaDeletedLink.Source, linkToOrder10643.Source)); Assert.Equal(deltaDeletedLink.Relationship, linkToOrder10643.Relationship); Assert.True(this.IdEqual(deltaDeletedLink.Target, linkToOrder10643.Target)); break; case ODataDeltaReaderState.ExpandedNavigationProperty: switch (tuple.Item3) { case ODataReaderState.Completed: case ODataReaderState.Start: break; case ODataReaderState.EntityReferenceLink: break; case ODataReaderState.EntryEnd: ODataEntry entry = tuple.Item1 as ODataEntry; Assert.NotNull(entry); if (entry.TypeName == "MyNS.Order") { Assert.Equal(10643, entry.Properties.Single(p => p.Name == "Id").Value); } else if (entry.TypeName == "MyNS.Product") { Assert.Equal(1, entry.Properties.Single(p => p.Name == "Id").Value); } else if (entry.TypeName == "MyNS.ProductDetail") { Assert.Equal(1, entry.Properties.Single(p => p.Name == "Id").Value); } break; case ODataReaderState.EntryStart: Assert.NotNull(tuple.Item1 as ODataEntry); break; case ODataReaderState.FeedEnd: Assert.NotNull(tuple.Item1 as ODataFeed); break; case ODataReaderState.FeedStart: Assert.NotNull(tuple.Item1 as ODataFeed); break; case ODataReaderState.NavigationLinkEnd: Assert.NotNull(tuple.Item1 as ODataNavigationLink); break; case ODataReaderState.NavigationLinkStart: ODataNavigationLink navigationLink = tuple.Item1 as ODataNavigationLink; Assert.NotNull(navigationLink); Assert.Equal("Details", navigationLink.Name); break; default: Assert.True(false, "Wrong reader sub state."); break; } break; default: Assert.True(false, "Wrong reader state."); break; } } }