public void WriteDeltaFeedInline_Sets_DeltaLink() { // Arrange IEnumerable instance = new object[0]; ODataDeltaResourceSet deltafeed = new ODataDeltaResourceSet { DeltaLink = new Uri("http://deltalink.com/") }; Mock <ODataDeltaFeedSerializer> serializer = new Mock <ODataDeltaFeedSerializer>(_serializerProvider); serializer.CallBase = true; serializer.Setup(s => s.CreateODataDeltaFeed(instance, _customersType, _writeContext)).Returns(deltafeed); var mockWriter = new Mock <ODataWriter>(); 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()); ODataDeltaResourceSet feed = new ODataDeltaResourceSet(); ODataResource derivedEntity = new ODataResource() { 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(); this.TestPayload().Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products/$delta\",\"value\":[{\"@odata.type\":\"#MyNS.PhysicalProduct\",\"Id\":1,\"Name\":\"car\",\"Material\":\"gold\"}]}"); }
public async Task WriteObjectInlineAsync_Sets_DeltaLink() { // Arrange IEnumerable instance = new object[0]; ODataDeltaResourceSet deltaResourceSet = new ODataDeltaResourceSet { DeltaLink = new Uri("http://deltalink.com/") }; Mock <IODataSerializerProvider> serializeProvider = new Mock <IODataSerializerProvider>(); Mock <ODataDeltaResourceSetSerializer> serializer = new Mock <ODataDeltaResourceSetSerializer>(serializeProvider.Object); serializer.CallBase = true; serializer.Setup(s => s.CreateODataDeltaResourceSet(instance, _customersType, _writeContext)).Returns(deltaResourceSet); var mockWriter = new Mock <ODataWriter>(); mockWriter.Setup(m => m.WriteStartAsync(deltaResourceSet)); mockWriter .Setup(m => m.WriteEndAsync()) .Callback(() => { Assert.Equal("http://deltalink.com/", deltaResourceSet.DeltaLink.AbsoluteUri); }) .Returns(Task.CompletedTask) .Verifiable(); // Act await serializer.Object.WriteObjectInlineAsync(instance, _customersType, mockWriter.Object, _writeContext); // Assert mockWriter.Verify(); }
/// <summary> /// Read the delta resource set. /// </summary> /// <param name="reader">The OData reader.</param> /// <param name="itemsStack">The item stack.</param> /// <param name="topLevelItem">The top level item.</param> private static void ReadDeltaResourceSet(ODataReader reader, Stack <ODataItemWrapper> itemsStack, ref ODataItemWrapper topLevelItem) { Contract.Assert(reader != null); Contract.Assert(itemsStack != null); Contract.Assert(ODataReaderState.DeltaResourceSetStart == reader.State); ODataDeltaResourceSet deltaResourceSet = (ODataDeltaResourceSet)reader.Item; Contract.Assert(deltaResourceSet != null, "Delta ResourceSet should never be null."); ODataDeltaResourceSetWrapper deltaResourceSetWrapper = new ODataDeltaResourceSetWrapper(deltaResourceSet); if (itemsStack.Count > 0) { ODataNestedResourceInfoWrapper parentNestedResourceInfo = (ODataNestedResourceInfoWrapper)itemsStack.Peek(); Contract.Assert(parentNestedResourceInfo != null, "this has to be an inner delta resource set. inner delta resource sets always have a nested resource info."); Contract.Assert(parentNestedResourceInfo.NestedResourceInfo.IsCollection == true, "Only collection nested properties can contain delta resource set as their child."); Contract.Assert(parentNestedResourceInfo.NestedItems.Count == 0, "Each nested property can contain only one delta resource set as its direct child."); parentNestedResourceInfo.NestedItems.Add(deltaResourceSetWrapper); } else { topLevelItem = deltaResourceSetWrapper; } itemsStack.Push(deltaResourceSetWrapper); }
public async Task WriteDeltaFeedInlineAsync_Sets_NextPageLink_OnWriteEndAsync() { // Arrange IEnumerable instance = new object[0]; ODataDeltaResourceSet deltafeed = new ODataDeltaResourceSet { NextPageLink = new Uri("http://nextlink.com/") }; Mock <ODataSerializerProvider> serializeProvider = new Mock <ODataSerializerProvider>(); Mock <ODataDeltaFeedSerializer> serializer = new Mock <ODataDeltaFeedSerializer>(serializeProvider.Object); serializer.CallBase = true; serializer.Setup(s => s.CreateODataDeltaFeed(instance, _customersType, _writeContext)).Returns(deltafeed); var mockWriter = new Mock <ODataWriter>(); mockWriter.Setup(m => m.WriteStartAsync(It.Is <ODataDeltaResourceSet>(f => f.NextPageLink == null))).Verifiable(); mockWriter .Setup(m => m.WriteEndAsync()) .Callback(() => { Assert.Equal("http://nextlink.com/", deltafeed.NextPageLink.AbsoluteUri); }) .Returns(Task.CompletedTask) .Verifiable(); // Act await serializer.Object.WriteDeltaFeedInlineAsync(instance, _customersType, mockWriter.Object, _writeContext); // Assert mockWriter.Verify(); }
/// <summary> /// Create the <see cref="ODataDeltaResourceSet"/> 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="ODataDeltaResourceSet"/> object.</returns> public virtual ODataDeltaResourceSet CreateODataDeltaFeed(IEnumerable feedInstance, IEdmCollectionTypeReference feedType, ODataSerializerContext writeContext) { ODataDeltaResourceSet feed = new ODataDeltaResourceSet(); if (writeContext.ExpandedResource == 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.InternalRequest.Context.NextLink; feed.DeltaLink = writeContext.InternalRequest.Context.DeltaLink; long?countValue = writeContext.InternalRequest.Context.TotalCount; if (countValue.HasValue) { feed.Count = countValue.Value; } } } return(feed); }
public void WriteContainedEntityInDeltaFeed() { this.TestInit(this.GetModel()); ODataDeltaResourceSet feed = new ODataDeltaResourceSet(); ODataResource containedEntry = new ODataResource() { 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 ODataResourceSerializationInfo() { NavigationSourceEntityTypeName = "MyNS.ProductDetail", NavigationSourceName = "Products(1)/Details", NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet }); ODataResource containedInContainedEntity = new ODataResource() { 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 ODataResourceSerializationInfo() { 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()); ODataDeltaResourceSet feed = new ODataDeltaResourceSet(); ODataResource orderEntry = new ODataResource() { SerializationInfo = new ODataResourceSerializationInfo { NavigationSourceEntityTypeName = "Order", NavigationSourceKind = EdmNavigationSourceKind.EntitySet, NavigationSourceName = "Orders" }, }; ODataNestedResourceInfo shippingAddressInfo = new ODataNestedResourceInfo { Name = "ShippingAddress", IsCollection = false }; ODataResource shippingAddress = new ODataResource { Properties = new List <ODataProperty> { new ODataProperty { Name = "City", Value = "Shanghai" }, } }; 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.WriteStart(shippingAddressInfo); writer.WriteStart(shippingAddress); writer.WriteEnd(); writer.WriteEnd(); writer.WriteEnd(); writer.WriteEnd(); writer.Flush(); this.TestPayload().Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products(ContactName,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(_serializerProvider); Uri expectedNextLink = new Uri("http://nextlink.com"); const long ExpectedCountValue = 1000; var result = new PageResult <Customer>(_customers, expectedNextLink, ExpectedCountValue); // Act ODataDeltaResourceSet feed = serializer.CreateODataDeltaFeed(result, _customersType, new ODataSerializerContext()); // Assert Assert.Equal(expectedNextLink, feed.NextPageLink); }
public void CreateODataDeltaResourceSet_Sets_CountValueForPageResult() { // Arrange Mock <ODataSerializerProvider> serializeProvider = new Mock <ODataSerializerProvider>(); ODataDeltaResourceSetSerializer serializer = new ODataDeltaResourceSetSerializer(serializeProvider.Object); Uri expectedNextLink = new Uri("http://nextlink.com"); const long ExpectedCountValue = 1000; var result = new PageResult <Customer>(_customers, expectedNextLink, ExpectedCountValue); // Act ODataDeltaResourceSet feed = serializer.CreateODataDeltaResourceSet(result, _customersType, new ODataSerializerContext()); // Assert Assert.Equal(ExpectedCountValue, feed.Count); }
private void WriteAnnotationAtEndInDeltaFeed(string expectedPayload, long?count, Uri nextLink, Uri deltaLink) { Action <ODataWriter> action = (odataWriter) => { var feedToWrite = new ODataDeltaResourceSet { 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); }
public void WriteDeltaFeedInline_Writes_CreateODataFeedOutput() { // Arrange IEnumerable instance = new object[0]; ODataDeltaResourceSet deltafeed = new ODataDeltaResourceSet(); Mock <ODataDeltaFeedSerializer> serializer = new Mock <ODataDeltaFeedSerializer>(_serializerProvider); serializer.CallBase = true; serializer.Setup(s => s.CreateODataDeltaFeed(instance, _customersType, _writeContext)).Returns(deltafeed); Mock <ODataWriter> writer = new Mock <ODataWriter>(); writer.Setup(s => s.WriteStart(deltafeed)).Verifiable(); // Act serializer.Object.WriteDeltaFeedInline(instance, _customersType, writer.Object, _writeContext); // Assert writer.Verify(); }
public async Task WriteObjectInlineAsync_Writes_CreateODataFeedOutput() { // Arrange IEnumerable instance = new object[0]; ODataDeltaResourceSet deltaResourceSet = new ODataDeltaResourceSet(); Mock <ODataSerializerProvider> provider = new Mock <ODataSerializerProvider>(); Mock <ODataDeltaResourceSetSerializer> serializer = new Mock <ODataDeltaResourceSetSerializer>(provider.Object); serializer.CallBase = true; serializer.Setup(s => s.CreateODataDeltaResourceSet(instance, _customersType, _writeContext)).Returns(deltaResourceSet); Mock <ODataWriter> writer = new Mock <ODataWriter>(); writer.Setup(s => s.WriteStartAsync(deltaResourceSet)).Verifiable(); // Act await serializer.Object.WriteObjectInlineAsync(instance, _customersType, writer.Object, _writeContext); // Assert writer.Verify(); }
public static void WriteDeltaFeed(ODataDeltaWriter deltaWriter, List <ODataItem> items, bool?countOption, Uri newDeltaLink) { var deltaFeed = new ODataDeltaResourceSet { DeltaLink = newDeltaLink }; if (countOption == true) { deltaFeed.Count = items.Cast <object>().Count(); } deltaWriter.WriteStart(deltaFeed); foreach (ODataItem item in items) { var entry = item as ODataResource; 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 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.Equal(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.DeltaResourceEnd) { ODataResource entry = deltaReader.Item as ODataResource; } else if (deltaReader.State == ODataDeltaReaderState.DeltaResourceSetEnd) { ODataDeltaResourceSet feed = deltaReader.Item as ODataDeltaResourceSet; } } Assert.Equal(ODataDeltaReaderState.Completed, deltaReader.State); } } } }
/// <summary> /// Create the <see cref="ODataDeltaResourceSet"/> 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="ODataDeltaResourceSet"/> object.</returns> public virtual ODataDeltaResourceSet CreateODataDeltaFeed(IEnumerable feedInstance, IEdmCollectionTypeReference feedType, ODataSerializerContext writeContext) { ODataDeltaResourceSet feed = new ODataDeltaResourceSet(); if (writeContext.ExpandedResource == 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> /// Asynchronously start writing a delta resource set. /// </summary> /// <param name="deltaResourceSet">Delta resource set/collection to write.</param> /// <returns>A task instance that represents the asynchronous write operation.</returns> public override Task WriteStartAsync(ODataDeltaResourceSet deltaResourceSet) { return(this.resourceWriter.WriteStartAsync(deltaResourceSet)); }
/// <summary> /// Initializes a new instance of <see cref="ODataDeltaResourceSetWrapper"/>. /// </summary> /// <param name="deltaResourceSet">The wrapped delta resource set item.</param> public ODataDeltaResourceSetWrapper(ODataDeltaResourceSet deltaResourceSet) { DeltaResourceSet = deltaResourceSet; DeltaItems = new List <ODataItemWrapper>(); }
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 ODataDeltaResourceSet(); var deltaEntry = new ODataResource { 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 ODataResource { 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 ODataResourceSerializationInfo { 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 ODataDeltaResourceSet(); var deltaEntry = new ODataResource { 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 ODataResource { 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 ODataResourceSerializationInfo { 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 ODataDeltaResourceSet(); var deltaEntry = new ODataResource { 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 ODataResource { 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 ODataResourceSerializationInfo { 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 == "expanded") { originalUri = new Uri(ServiceConstants.ServiceBaseUri, "Customers?$expand=Orders"); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { var customerSet = this.DataSource.Model.FindDeclaredEntitySet("Customers"); var orderSet = this.DataSource.Model.FindDeclaredEntitySet("Orders"); var peopleSet = this.DataSource.Model.FindDeclaredEntitySet("People"); var customerType = customerSet.EntityType(); ODataDeltaWriter deltaWriter = messageWriter.CreateODataDeltaWriter(customerSet, customerType); // Delta feed and entry var deltaFeed = new ODataDeltaResourceSet { DeltaLink = new Uri(ServiceConstants.ServiceBaseUri, "$delta?$token=expanded") }; var deltaEntry = new ODataResource { Id = new Uri(ServiceConstants.ServiceBaseUri, customerSet.Name + "(1)"), Properties = new[] { new ODataProperty { Name = "FirstName", Value = "GGGG" } } }; var nestedResourceInfoIndeltaEntry = new ODataNestedResourceInfo { Name = "HomeAddress", IsCollection = false, }; var nestedResource = new ODataResource { Properties = new[] { new ODataProperty { Name = "Street", Value = "Zixing Road" }, new ODataProperty { Name = "City", Value = "Shanghai" }, new ODataProperty { Name = "PostalCode", Value = "200001" }, } }; var nestedResourceInfoInExpanded = new ODataNestedResourceInfo { Name = "InfoFromCustomer", IsCollection = false, }; var nestedResourceInExpanded = new ODataResource { Properties = new[] { new ODataProperty { Name = "CustomerMessage", Value = "XXL" }, } }; // Expanded feed var navigationLink = new ODataNestedResourceInfo() { Name = "Orders", IsCollection = true, }; var expandedFeed = new ODataResourceSet(); var expandedEntry = new ODataResource { Id = new Uri(ServiceConstants.ServiceBaseUri, orderSet.Name + "(8)"), Properties = new[] { new ODataProperty { Name = "OrderDate", Value = new DateTimeOffset(2011, 3, 4, 16, 03, 57, TimeSpan.FromHours(-8)) }, new ODataProperty { Name = "OrderID", Value = 8 }, new ODataProperty { Name = "OrderShelfLifes", Value = new ODataCollectionValue { Items = new object[] { new TimeSpan(1) } } }, new ODataProperty { Name = "ShelfLife", Value = new TimeSpan(1) }, new ODataProperty { Name = "ShipDate", Value = new Date(2014, 8, 12) }, new ODataProperty { Name = "ShipTime", Value = new TimeOfDay(6, 5, 30, 0) }, } }; // Expanded entry var navigationLinkSingle = new ODataNestedResourceInfo() { Name = "Parent", IsCollection = false, }; var expandedEntrySingle = new ODataResource { Id = new Uri(ServiceConstants.ServiceBaseUri, peopleSet.Name + "(2)"), Properties = new[] { new ODataProperty { Name = "FirstName", Value = "Jill" }, new ODataProperty { Name = "LastName", Value = "Jones" }, new ODataProperty { Name = "Numbers", Value = new ODataCollectionValue() }, new ODataProperty { Name = "Emails", Value = new ODataCollectionValue() }, new ODataProperty { Name = "PersonID", Value = 2 }, new ODataProperty { Name = "Home", Value = GeographyPoint.Create(15.0, 161.8) }, } }; // Delta feed and entry deltaWriter.WriteStart(deltaFeed); deltaWriter.WriteStart(deltaEntry); deltaWriter.WriteStart(nestedResourceInfoIndeltaEntry); deltaWriter.WriteStart(nestedResource); deltaWriter.WriteEnd(); deltaWriter.WriteEnd(); // Expanded feed deltaWriter.WriteStart(navigationLink); deltaWriter.WriteStart(expandedFeed); deltaWriter.WriteStart(expandedEntry); deltaWriter.WriteStart(nestedResourceInfoInExpanded); deltaWriter.WriteStart(nestedResourceInExpanded); deltaWriter.WriteEnd(); deltaWriter.WriteEnd(); deltaWriter.WriteEnd(); deltaWriter.WriteEnd(); deltaWriter.WriteEnd(); // Expanded entry deltaWriter.WriteStart(navigationLinkSingle); deltaWriter.WriteStart(expandedEntrySingle); deltaWriter.WriteEnd(); deltaWriter.WriteEnd(); // Delta feed and entry deltaWriter.WriteEnd(); 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 ODataDeltaResourceSet(); var deltaEntry1 = new ODataResource { 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 ODataResource { 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 ODataResourceSerializationInfo { 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 ODataResource { 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 static void ReadCollectionItem(ODataReader reader, Stack <ODataItemBase> itemsStack, ref ODataItemBase topLevelItem) { switch (reader.State) { case ODataReaderState.ResourceStart: ODataResource resource = (ODataResource)reader.Item; ODataResourceWrapper resourceWrapper = null; if (resource != null) { resourceWrapper = new ODataResourceWrapper(resource); } if (itemsStack.Count == 0) { Contract.Assert(resource != null, "The top-level resource can never be null."); topLevelItem = resourceWrapper; } else { ODataItemBase parentItem = itemsStack.Peek(); ODataResourceSetWrapper parentResourceSet = parentItem as ODataResourceSetWrapper; if (parentResourceSet != null) { parentResourceSet.Resources.Add(resourceWrapper); } else { ODataNestedResourceInfoWrapper parentNestedResource = parentItem as ODataNestedResourceInfoWrapper; if (parentNestedResource != null) { Contract.Assert(parentNestedResource.NestedResourceInfo.IsCollection == false, "Only singleton nested properties can contain resource as their child."); Contract.Assert(parentNestedResource.NestedItems.Count == 0, "Each nested property can contain only one resource as its direct child."); parentNestedResource.NestedItems.Add(resourceWrapper); } else { ODataDeltaResourceSetWrapper parentDeltaSetResource = (ODataDeltaResourceSetWrapper)parentItem; parentDeltaSetResource.Resources.Add(resourceWrapper); } } } itemsStack.Push(resourceWrapper); break; case ODataReaderState.ResourceEnd: Contract.Assert( itemsStack.Count > 0 && (reader.Item == null || itemsStack.Peek().Item == reader.Item), "The resource which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.NestedResourceInfoStart: ODataNestedResourceInfo nestedResourceInfo = (ODataNestedResourceInfo)reader.Item; Contract.Assert(nestedResourceInfo != null, "nested resource info should never be null."); ODataNestedResourceInfoWrapper nestedResourceInfoWrapper = new ODataNestedResourceInfoWrapper(nestedResourceInfo); Contract.Assert(itemsStack.Count > 0, "nested resource info can't appear as top-level item."); { ODataResourceWrapper parentResource = (ODataResourceWrapper)itemsStack.Peek(); parentResource.NestedResourceInfos.Add(nestedResourceInfoWrapper); } itemsStack.Push(nestedResourceInfoWrapper); break; case ODataReaderState.NestedResourceInfoEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The nested resource info which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.ResourceSetStart: ODataResourceSet resourceSet = (ODataResourceSet)reader.Item; Contract.Assert(resourceSet != null, "ResourceSet should never be null."); ODataResourceSetWrapper resourceSetWrapper = new ODataResourceSetWrapper(resourceSet); if (itemsStack.Count > 0) { ODataNestedResourceInfoWrapper parentNestedResourceInfo = (ODataNestedResourceInfoWrapper)itemsStack.Peek(); Contract.Assert(parentNestedResourceInfo != null, "this has to be an inner resource set. inner resource sets always have a nested resource info."); Contract.Assert(parentNestedResourceInfo.NestedResourceInfo.IsCollection == true, "Only collection nested properties can contain resource set as their child."); parentNestedResourceInfo.NestedItems.Add(resourceSetWrapper); } else { topLevelItem = resourceSetWrapper; } itemsStack.Push(resourceSetWrapper); break; case ODataReaderState.ResourceSetEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The resource set 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."); { ODataNestedResourceInfoWrapper parentNavigationLink = (ODataNestedResourceInfoWrapper)itemsStack.Peek(); parentNavigationLink.NestedItems.Add(entityReferenceLinkWrapper); } break; case ODataReaderState.DeltaResourceSetStart: ODataDeltaResourceSet deltaResourceSet = (ODataDeltaResourceSet)reader.Item; Contract.Assert(deltaResourceSet != null, "ResourceSet should never be null."); ODataDeltaResourceSetWrapper deltaResourceSetWrapper = new ODataDeltaResourceSetWrapper(deltaResourceSet); if (itemsStack.Count > 0) { ODataNestedResourceInfoWrapper parentNestedResourceInfo = (ODataNestedResourceInfoWrapper)itemsStack.Peek(); Contract.Assert(parentNestedResourceInfo != null, "this has to be an inner resource set. inner resource sets always have a nested resource info."); Contract.Assert(parentNestedResourceInfo.NestedResourceInfo.IsCollection == true, "Only collection nested properties can contain resource set as their child."); parentNestedResourceInfo.NestedItems.Add(deltaResourceSetWrapper); } else { topLevelItem = deltaResourceSetWrapper; } itemsStack.Push(deltaResourceSetWrapper); break; case ODataReaderState.DeltaResourceSetEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The resource set which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.DeletedResourceStart: ODataDeletedResource deletedResource = (ODataDeletedResource)reader.Item; if (deletedResource != null) { // Note: I expect that deleted resourced will not have other nested resources ODataDeletedResourceWrapper deletedResourceWrapper = new ODataDeletedResourceWrapper(deletedResource); ODataItemBase parentItem = itemsStack.Peek(); ODataDeltaResourceSetWrapper parentDeltaSetResource = parentItem as ODataDeltaResourceSetWrapper; if (parentDeltaSetResource != null) { parentDeltaSetResource.DeletedResources.Add(deletedResourceWrapper); } } break; case ODataReaderState.DeletedResourceEnd: break; default: Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } }
public void WriteContainedEntityInDeltaFeedWithSelectExpand() { this.TestInit(this.GetModel()); ODataDeltaResourceSet feed = new ODataDeltaResourceSet(); ODataResource entry = new ODataResource() { TypeName = "MyNS.Product", Properties = new[] { new ODataProperty { Name = "Id", Value = new ODataPrimitiveValue(1) }, new ODataProperty { Name = "Name", Value = new ODataPrimitiveValue("Car") }, }, }; ODataResource containedEntry = new ODataResource() { 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 ODataResourceSerializationInfo() { 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(Detail))/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Products(1)/Details/$entity\",\"Id\":1,\"Detail\":\"made in china\"},{\"Id\":1,\"Name\":\"Car\"}]}"); }
/// <summary> /// Initializes a new instance of <see cref="ODataDeltaResourceSetWrapper"/>. /// </summary> /// <param name="deltaResourceSet">The wrapped delta resource set item.</param> public ODataDeltaResourceSetWrapper(ODataDeltaResourceSet deltaResourceSet) { ResourceBases = new List <ODataResourceBaseWrapper>(); DeltaLinks = new List <ODataDeltaLinkBaseWrapper>(); DeltaResourceSet = deltaResourceSet; }
private async Task 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); ODataDeltaResourceSet 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); ODataResourceSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(writeContext.Context, elementType) as ODataResourceSerializer; if (entrySerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName(), typeof(ODataOutputFormatter).Name)); } await 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(); }
/// <summary> /// Creates a function that takes in an object and generates nextlink uri. /// </summary> /// <param name="deltaFeed">The resource set describing a collection of structured objects.</param> /// <param name="enumerable">>The instance representing the resourceSet being written.</param> /// <param name="writeContext">The serializer context.</param> /// <returns>The function that generates the NextLink from an object.</returns> /// <returns></returns> internal static Func <object, Uri> GetNextLinkGenerator(ODataDeltaResourceSet deltaFeed, IEnumerable enumerable, ODataSerializerContext writeContext) { return(ODataResourceSetSerializer.GetNextLinkGenerator(deltaFeed, enumerable, writeContext)); }
private async Task WriteFeedAsync(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer, ODataSerializerContext writeContext) { Contract.Assert(writer != null); Contract.Assert(writeContext != null); Contract.Assert(enumerable != null); Contract.Assert(feedType != null); IEdmStructuredTypeReference elementType = GetResourceType(feedType); if (elementType.IsComplex()) { ODataResourceSet resourceSet = new ODataResourceSet() { TypeName = feedType.FullName() }; await writer.WriteStartAsync(resourceSet).ConfigureAwait(false); ODataResourceSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(elementType) as ODataResourceSerializer; if (entrySerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName())); } foreach (object entry in enumerable) { await entrySerializer.WriteDeltaObjectInlineAsync(entry, elementType, writer, writeContext).ConfigureAwait(false); } } else { ODataDeltaResourceSet deltaFeed = CreateODataDeltaFeed(enumerable, feedType.AsCollection(), writeContext); if (deltaFeed == null) { throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, DeltaFeed)); } // save the next page link for later to support JSON odata.streaming. Func <object, Uri> nextLinkGenerator = GetNextLinkGenerator(deltaFeed, enumerable, writeContext); deltaFeed.NextPageLink = null; //Start writing of the Delta Feed await writer.WriteStartAsync(deltaFeed).ConfigureAwait(false); object lastResource = null; //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); } lastResource = entry; 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: await WriteDeltaDeletedEntryAsync(entry, writer, writeContext).ConfigureAwait(false); break; case EdmDeltaEntityKind.DeletedLinkEntry: await WriteDeltaDeletedLinkAsync(entry, writer, writeContext).ConfigureAwait(false); break; case EdmDeltaEntityKind.LinkEntry: await WriteDeltaLinkAsync(entry, writer, writeContext).ConfigureAwait(false); break; case EdmDeltaEntityKind.Entry: { ODataResourceSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(elementType) as ODataResourceSerializer; if (entrySerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName())); } await entrySerializer.WriteDeltaObjectInlineAsync(entry, elementType, writer, writeContext) .ConfigureAwait(false); 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. deltaFeed.NextPageLink = nextLinkGenerator(lastResource); } //End Writing of the Delta Feed await writer.WriteEndAsync().ConfigureAwait(false); }
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.DeltaResourceSetStart: ODataDeltaResourceSet deltaFeed = tuple.Item1 as ODataDeltaResourceSet; Assert.NotNull(deltaFeed); if (deltaFeed.Count.HasValue) { Assert.Equal(deltaFeed.Count, feed.Count); } break; case ODataDeltaReaderState.DeltaResourceSetEnd: Assert.NotNull(tuple.Item1 as ODataDeltaResourceSet); if (nextLink != null) { Assert.Equal(nextLink, ((ODataDeltaResourceSet)tuple.Item1).NextPageLink); } if (feedDeltaLink != null) { Assert.Equal(feedDeltaLink, ((ODataDeltaResourceSet)tuple.Item1).DeltaLink); } break; case ODataDeltaReaderState.DeltaResourceStart: Assert.True(tuple.Item1 is ODataResource); break; case ODataDeltaReaderState.DeltaResourceEnd: var deltaResource = tuple.Item1 as ODataResource; Assert.NotNull(deltaResource); Assert.NotNull(deltaResource.Id); if (this.IdEqual(deltaResource.Id, customerUpdated.Id)) { Assert.True(PropertiesEqual(deltaResource.Properties, customerUpdated.Properties)); } else if (this.IdEqual(deltaResource.Id, order10643.Id)) { Assert.True(this.PropertiesEqual(deltaResource.Properties, order10643.Properties)); } else { Assert.True(this.PropertiesEqual(deltaResource.Properties, complexPropertyInOrder10643.Properties)); } 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.NestedResource: switch (tuple.Item3) { case ODataReaderState.Completed: case ODataReaderState.Start: ODataNestedResourceInfo nestedResource = tuple.Item1 as ODataNestedResourceInfo; Assert.NotNull(nestedResource); break; case ODataReaderState.EntityReferenceLink: break; case ODataReaderState.ResourceEnd: ODataResource entry = tuple.Item1 as ODataResource; 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); } else if (entry.TypeName == "MyNS.Address") { Assert.NotNull(entry.Properties.Single(p => p.Name == "Street").Value); } else if (entry.TypeName == "MyNS.City") { Assert.NotNull(entry.Properties.Single(p => p.Name == "CityName").Value); } break; case ODataReaderState.ResourceStart: Assert.NotNull(tuple.Item1 as ODataResource); break; case ODataReaderState.ResourceSetEnd: Assert.NotNull(tuple.Item1 as ODataResourceSet); break; case ODataReaderState.ResourceSetStart: Assert.NotNull(tuple.Item1 as ODataResourceSet); break; case ODataReaderState.NestedResourceInfoEnd: Assert.NotNull(tuple.Item1 as ODataNestedResourceInfo); break; case ODataReaderState.NestedResourceInfoStart: ODataNestedResourceInfo nestedResourceInfo = tuple.Item1 as ODataNestedResourceInfo; Assert.NotNull(nestedResourceInfo); Assert.True(nestedResourceInfo.Name.Equals("Details") || nestedResourceInfo.Name.Equals("Address") || nestedResourceInfo.Name.Equals("City")); break; default: Assert.True(false, "Wrong reader sub state."); break; } break; default: Assert.True(false, "Wrong reader state."); break; } } }
/// <summary> /// Asynchronously start writing a delta resource set. /// </summary> /// <param name="deltaResourceSet">Delta resource set/collection to write.</param> /// <returns>A task instance that represents the asynchronous write operation.</returns> public override Task WriteStartAsync(ODataDeltaResourceSet deltaResourceSet) { return(TaskUtils.GetTaskForSynchronousOperation(() => this.resourceWriter.WriteStart(deltaResourceSet))); }
/// <summary> /// Start writing a delta resource set. /// </summary> /// <param name="deltaResourceSet">Delta resource set/collection to write.</param> public override void WriteStart(ODataDeltaResourceSet deltaResourceSet) { this.resourceWriter.WriteStart(deltaResourceSet); }
/// <summary> /// Initializes a new instance of <see cref="ODataResourceSetWrapper"/>. /// </summary> /// <param name="item">The wrapped item.</param> public ODataDeltaResourceSetWrapper(ODataDeltaResourceSet item) : base(item) { Resources = new List <ODataResourceWrapper>(); DeletedResources = new List <ODataDeletedResourceWrapper>(); }