Example #1
0
        /// <summary>
        /// Writes an OData feed.
        /// </summary>
        /// <param name="writer">The ODataWriter that will write the feed.</param>
        /// <param name="entityType">The type of the entity in the feed.</param>
        /// <param name="entries">The items from the data store to write to the feed.</param>
        /// <param name="entitySet">The entity set in the model that the feed belongs to.</param>
        /// <param name="targetVersion">The OData version this segment is targeting.</param>
        /// <param name="selectExpandClause">The SelectExpandClause.</param>
        public static void WriteFeed(ODataWriter writer, IEdmEntityType entityType, IEnumerable entries, IEdmEntitySetBase entitySet, ODataVersion targetVersion, SelectExpandClause selectExpandClause, long?count, Uri deltaLink, Uri nextPageLink, Dictionary <string, string> incomingHeaders = null)
        {
            var feed = new ODataFeed
            {
                Id           = entitySet == null ? null : new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name),
                DeltaLink    = deltaLink,
                NextPageLink = nextPageLink
            };

            if (entitySet == null)
            {
                feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceEntityTypeName = entityType.FullTypeName(),
                    NavigationSourceName           = null,
                    NavigationSourceKind           = EdmNavigationSourceKind.UnknownEntitySet,
                    IsFromCollection = true
                });
            }

            if (count.HasValue)
            {
                feed.Count = count;
            }

            writer.WriteStart(feed);

            foreach (var element in entries)
            {
                WriteEntry(writer, element, entitySet, targetVersion, selectExpandClause, incomingHeaders);
            }

            writer.WriteEnd();
        }
 public void ShouldBeAbleToSetTheFeedSerializationInfo()
 {
     ODataFeed feed = new ODataFeed();
     ODataFeedAndEntrySerializationInfo serializationInfo = new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "Set", NavigationSourceEntityTypeName = "ns.base", ExpectedTypeName = "ns.expected" };
     feed.SetSerializationInfo(serializationInfo);
     feed.SerializationInfo.Should().BeSameAs(serializationInfo);
 }
Example #3
0
        public void SetFeedSerializationInfoShouldThrowOnNullFeed()
        {
            ODataFeed feed   = null;
            Action    action = () => feed.SetSerializationInfo(null);

            action.ShouldThrow <ArgumentNullException>().WithMessage("feed", ComparisonMode.Substring);
        }
Example #4
0
        public void ShouldBeAbleToSetTheFeedSerializationInfo()
        {
            ODataFeed feed = new ODataFeed();
            ODataFeedAndEntrySerializationInfo serializationInfo = new ODataFeedAndEntrySerializationInfo {
                NavigationSourceName = "Set", NavigationSourceEntityTypeName = "ns.base", ExpectedTypeName = "ns.expected"
            };

            feed.SetSerializationInfo(serializationInfo);
            feed.SerializationInfo.Should().BeSameAs(serializationInfo);
        }
        private string WriteAndVerifyOrderFeed(StreamResponseMessage responseMessage, ODataWriter odataWriter,
                                               bool hasModel, string mimeType)
        {
            var orderFeed = new ODataFeed()
            {
                Id           = new Uri(this.ServiceUri + "Order"),
                NextPageLink = new Uri(this.ServiceUri + "Order?$skiptoken=-9"),
            };

            if (!hasModel)
            {
                orderFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceName = "Order", NavigationSourceEntityTypeName = NameSpace + "Order"
                });
            }

            odataWriter.WriteStart(orderFeed);

            var orderEntry1 = WritePayloadHelper.CreateOrderEntry1(hasModel);

            odataWriter.WriteStart(orderEntry1);

            var orderEntry1Navigation1 = new ODataNavigationLink()
            {
                Name         = "Customer",
                IsCollection = false,
                Url          = new Uri(this.ServiceUri + "Order(-10)/Customer")
            };

            odataWriter.WriteStart(orderEntry1Navigation1);
            odataWriter.WriteEnd();

            var orderEntry1Navigation2 = new ODataNavigationLink()
            {
                Name         = "Login",
                IsCollection = false,
                Url          = new Uri(this.ServiceUri + "Order(-10)/Login")
            };

            odataWriter.WriteStart(orderEntry1Navigation2);
            odataWriter.WriteEnd();

            // Finish writing orderEntry1.
            odataWriter.WriteEnd();

            var orderEntry2 = WritePayloadHelper.CreateOrderEntry2(hasModel);

            odataWriter.WriteStart(orderEntry2);

            var orderEntry2Navigation1 = new ODataNavigationLink()
            {
                Name         = "Customer",
                IsCollection = false,
                Url          = new Uri(this.ServiceUri + "Order(-9)/Customer")
            };

            odataWriter.WriteStart(orderEntry2Navigation1);
            odataWriter.WriteEnd();

            var orderEntry2Navigation2 = new ODataNavigationLink()
            {
                Name         = "Login",
                IsCollection = false,
                Url          = new Uri(this.ServiceUri + "Order(-9)/Login")
            };

            odataWriter.WriteStart(orderEntry2Navigation2);
            odataWriter.WriteEnd();

            // Finish writing orderEntry2.
            odataWriter.WriteEnd();

            // Finish writing the feed.
            odataWriter.WriteEnd();

            // Some very basic verification for the payload.
            bool verifyFeedCalled         = false;
            bool verifyEntryCalled        = false;
            bool verifyNavigationCalled   = false;
            Action <ODataFeed> verifyFeed = (feed) =>
            {
                Assert.IsNotNull(feed.NextPageLink, "feed.NextPageLink");
                verifyFeedCalled = true;
            };
            Action <ODataEntry> verifyEntry = (entry) =>
            {
                Assert.AreEqual(3, entry.Properties.Count(), "entry.Properties.Count");
                verifyEntryCalled = true;
            };
            Action <ODataNavigationLink> verifyNavigation = (navigation) =>
            {
                Assert.IsTrue(navigation.Name == "Customer" || navigation.Name == "Login", "navigation.Name");
                verifyNavigationCalled = true;
            };

            Stream stream = responseMessage.GetStream();

            if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
            {
                stream.Seek(0, SeekOrigin.Begin);
                WritePayloadHelper.ReadAndVerifyFeedEntryMessage(true, responseMessage, WritePayloadHelper.OrderSet, WritePayloadHelper.OrderType, verifyFeed,
                                                                 verifyEntry, verifyNavigation);
                Assert.IsTrue(verifyFeedCalled && verifyEntryCalled && verifyNavigationCalled,
                              "Verification action not called.");
            }

            return(WritePayloadHelper.ReadStreamContent(stream));
        }
        public void ShouldBeAbleToWriteFeedAndEntryResponseInJsonLightWithoutModel()
        {
            const string expectedPayload =
                "{" +
                    "\"@odata.context\":\"http://www.example.com/$metadata#Customers/NS.VIPCustomer\"," +
                    "\"value\":[" +
                        "{" +
                            "\"Name\":\"Bob\"," +
                            "\"[email protected]\":\"MostRecentOrder\"," +
                            "\"MostRecentOrder\":{\"OrderId\":101}" +
                        "}" +
                    "]" +
                "}";

            var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true };
            writerSettings.SetContentType(ODataFormat.Json);
            writerSettings.ODataUri = new ODataUri() { ServiceRoot = new Uri("http://www.example.com") };

            MemoryStream stream = new MemoryStream();
            IODataResponseMessage responseMessage = new InMemoryMessage { StatusCode = 200, Stream = stream };

            // Write payload
            using (var messageWriter = new ODataMessageWriter(responseMessage, writerSettings))
            {
                var odataWriter = messageWriter.CreateODataFeedWriter();

                // Create customers feed with serializtion info to write odata.metadata.
                var customersFeed = new ODataFeed();
                customersFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "Customers", NavigationSourceEntityTypeName = "NS.Customer", ExpectedTypeName = "NS.VIPCustomer" });

                // Write customers feed.
                odataWriter.WriteStart(customersFeed);

                // Write VIP customer
                {
                    // Create VIP customer, don't need to pass in serialization info since the writer knows the context from the feed scope.
                    var vipCustomer = new ODataEntry { TypeName = "NS.VIPCustomer" };

                    var customerKey = new ODataProperty { Name = "Name", Value = "Bob" };

                    // Provide serialization info at the property level to compute the edit link.
                    customerKey.SetSerializationInfo(new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.Key });
                    vipCustomer.Properties = new[] { customerKey };

                    // Write customer entry.
                    odataWriter.WriteStart(vipCustomer);

                    // Write expanded most recent order
                    {
                        // No API to set serialization info on ODataNavigationLink since what we are adding on ODataFeed and ODataEntry should be sufficient for the 5.5 release.
                        var navigationLink = new ODataNavigationLink { Name = "MostRecentOrder", IsCollection = false, Url = new Uri("MostRecentOrder", UriKind.Relative) };
                        odataWriter.WriteStart(navigationLink);

                        // Write the most recent customer.
                        {
                            var mostRecentOrder = new ODataEntry { TypeName = "NS.Order" };

                            // Add serialization info so we can computer links.
                            mostRecentOrder.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "Orders", NavigationSourceEntityTypeName = "NS.Order", ExpectedTypeName = "NS.Order" });

                            var orderKey = new ODataProperty { Name = "OrderId", Value = 101 };

                            // Provide serialization info at the property level to compute the edit link.
                            orderKey.SetSerializationInfo(new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.Key });
                            mostRecentOrder.Properties = new[] { orderKey };

                            // Write order entry.
                            odataWriter.WriteStart(mostRecentOrder);
                            odataWriter.WriteEnd();
                        }

                        // End navigationLink.
                        odataWriter.WriteEnd();
                    }

                    // End customer entry.
                    odataWriter.WriteEnd();
                }

                // End customers feed.
                odataWriter.WriteEnd();
            }

            stream.Position = 0;
            string payload = (new StreamReader(stream)).ReadToEnd();
            payload.Should().Be(expectedPayload);
        }
        public void WritingInMinimalMetadataModeWithExpandAndProjectionWithModelWhenAutoComputePayloadMetadataInJsonIsTrue()
        {
            const string expectedPayload =
                "{" +
                    "\"@odata.context\":\"http://example.com/$metadata#EntitySet(StreamProp1,Namespace.AlwaysBindableAction1,Namespace.AlwaysBindableFunction1,DeferredNavLink,ExpandedNavLink,ExpandedNavLink(StreamProp1,Namespace.AlwaysBindableAction1,ExpandedNavLink,ExpandedNavLink(StreamProp2,Namespace.AlwaysBindableAction1)))\"," +
                    "\"value\":[" +
                    "{" +
                        "\"ID\":123," +
                        "\"Name\":\"Bob\"," +
                        "\"[email protected]\":\"http://example.com/expanded/association\"," +
                        "\"[email protected]\":\"http://example.com/expanded/navigation\"," +
                        "\"ExpandedNavLink\":[" +
                        "{" +
                            "\"ID\":234," +
                            "\"Name\":\"Foo\"," +
                            "\"ExpandedNavLink\":[" +
                            "{" +
                                "\"ID\":345," +
                                "\"Name\":\"Bar\"," +
                                "\"#Container.AlwaysBindableAction1\":{}" +
                            "}]," +
                            "\"#Container.AlwaysBindableAction1\":{}" +
                        "}]," +
                        "\"#Container.AlwaysBindableAction1\":{}," +
                        "\"#Container.AlwaysBindableFunction1\":{}" +
                    "}]" +
                "}";

            ODataFeedAndEntrySerializationInfo serializationInfo = new ODataFeedAndEntrySerializationInfo { NavigationSourceName = EntitySet.Name, NavigationSourceEntityTypeName = EntityType.FullName(), ExpectedTypeName = EntityType.FullName() };

            var feed = new ODataFeed();
            feed.SetSerializationInfo(serializationInfo);

            this.entryWithOnlyData = new ODataEntry
            {
                TypeName = EntityType.FullName(),
                MediaResource = new ODataStreamReferenceValue(),
                Properties = new[]
                {
                    new ODataProperty { Name = "ID", Value = 123, SerializationInfo = new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.Key }},
                    new ODataProperty { Name = "Name", Value = "Bob", SerializationInfo = new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.ETag }},
                    new ODataProperty { Name = "StreamProp1", Value = new ODataStreamReferenceValue() }
                },
            };
            this.entryWithOnlyData.AddAction(new ODataAction { Metadata = new Uri("http://example.com/$metadata#Container.AlwaysBindableAction1") });
            this.entryWithOnlyData.AddFunction(new ODataFunction { Metadata = new Uri("#Container.AlwaysBindableFunction1", UriKind.Relative) });

            this.entryWithOnlyData2 = new ODataEntry
            {
                TypeName = EntityType.FullName(),
                MediaResource = new ODataStreamReferenceValue(),
                Properties = new[]
                {
                    new ODataProperty { Name = "ID", Value = 234, SerializationInfo = new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.Key }},
                    new ODataProperty { Name = "Name", Value = "Foo", SerializationInfo = new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.ETag }},
                    new ODataProperty { Name = "StreamProp1", Value = new ODataStreamReferenceValue() }
                },
            };
            this.entryWithOnlyData2.AddAction(new ODataAction { Metadata = new Uri("http://example.com/$metadata#Container.AlwaysBindableAction1") });

            this.entryWithOnlyData3 = new ODataEntry
            {
                TypeName = EntityType.FullName(),
                MediaResource = new ODataStreamReferenceValue(),
                Properties = new[]
                {
                    new ODataProperty { Name = "ID", Value = 345, SerializationInfo = new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.Key }},
                    new ODataProperty { Name = "Name", Value = "Bar", SerializationInfo = new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.ETag }},
                    new ODataProperty { Name = "StreamProp2", Value = new ODataStreamReferenceValue() }
                },
            };
            this.entryWithOnlyData3.AddAction(new ODataAction { Metadata = new Uri("http://example.com/$metadata#Container.AlwaysBindableAction1") });

            ODataItem[] itemsToWrite = new ODataItem[]
            {
                feed, this.entryWithOnlyData,
                this.expandedNavLinkWithPayloadMetadata, feed, this.entryWithOnlyData2, this.navLinkWithoutPayloadMetadata,
                this.expandedNavLinkWithoutPayloadMetadata, feed, this.entryWithOnlyData3
            };

            const string selectClause = "StreamProp1,Namespace.AlwaysBindableAction1,Namespace.AlwaysBindableFunction1,DeferredNavLink";
            const string expandClause = "ExpandedNavLink($select=StreamProp1,Namespace.AlwaysBindableAction1;$expand=ExpandedNavLink($select=StreamProp2,Namespace.AlwaysBindableAction1))";
            this.GetWriterOutputForContentTypeAndKnobValue("application/json;odata.metadata=minimal", true, itemsToWrite, edmModel: Model, edmEntitySet: null, edmEntityType: EntityType, selectClause: selectClause, expandClause: expandClause)
                .Should().Be(expectedPayload);
        }
        public void WritingInFullMetadataModeWithExpandAndProjectionWithMissingStreamAndActionAndFunctionWhenAutoComputePayloadMetadataInJsonIsTrue()
        {
            const string expectedPayload =
                "{" +
                    "\"@odata.context\":\"http://example.com/$metadata#EntitySet(StreamProp1,Namespace.AlwaysBindableAction1,Namespace.AlwaysBindableFunction1,DeferredNavLink,ExpandedNavLink,ExpandedNavLink(StreamProp1,Namespace.AlwaysBindableAction1,ExpandedNavLink,ExpandedNavLink(StreamProp2,Namespace.AlwaysBindableAction1)))\"," +
                    "\"value\":[" +
                    "{" +
                        "\"@odata.type\":\"#Namespace.EntityType\"," +
                        "\"@odata.id\":\"EntitySet(123)\"," +
                        "\"@odata.etag\":\"W/\\\"'Bob'\\\"\"," +
                        "\"@odata.editLink\":\"EntitySet(123)\"," +
                        "\"@odata.mediaEditLink\":\"EntitySet(123)/$value\"," +
                        "\"ID\":123," +
                        "\"Name\":\"Bob\"," +
                        "\"[email protected]\":\"http://example.com/expanded/association\"," +
                        "\"[email protected]\":\"http://example.com/expanded/navigation\"," +
                        "\"ExpandedNavLink\":[" +
                        "{" +
                            "\"@odata.type\":\"#Namespace.EntityType\"," +
                            "\"@odata.id\":\"EntitySet(234)\"," +
                            "\"@odata.etag\":\"W/\\\"'Foo'\\\"\"," +
                            "\"@odata.editLink\":\"EntitySet(234)\"," +
                            "\"@odata.mediaEditLink\":\"EntitySet(234)/$value\"," +
                            "\"ID\":234," +
                            "\"Name\":\"Foo\"," +
                            "\"[email protected]\":\"http://example.com/EntitySet(234)/DeferredNavLink/$ref\"," +
                            "\"[email protected]\":\"http://example.com/EntitySet(234)/DeferredNavLink\"," +
                            "\"[email protected]\":\"http://example.com/EntitySet(234)/ExpandedNavLink/$ref\"," +
                            "\"[email protected]\":\"http://example.com/EntitySet(234)/ExpandedNavLink\"," +
                            "\"ExpandedNavLink\":[" +
                            "{" +
                                "\"@odata.type\":\"#Namespace.EntityType\"," +
                                "\"@odata.id\":\"EntitySet(345)\"," +
                                "\"@odata.etag\":\"W/\\\"'Bar'\\\"\"," +
                                "\"@odata.editLink\":\"EntitySet(345)\"," +
                                "\"@odata.mediaEditLink\":\"EntitySet(345)/$value\"," +
                                "\"ID\":345," +
                                "\"Name\":\"Bar\"" +
                            "}]" +
                        "}]" +
                    "}]" +
                "}";

            ODataFeedAndEntrySerializationInfo serializationInfo = new ODataFeedAndEntrySerializationInfo { NavigationSourceName = EntitySet.Name, NavigationSourceEntityTypeName = EntityType.FullName(), ExpectedTypeName = EntityType.FullName() };

            var feed = new ODataFeed();
            feed.SetSerializationInfo(serializationInfo);
            this.entryWithOnlyData.TypeName = EntityType.FullName();
            this.entryWithOnlyData.MediaResource = new ODataStreamReferenceValue();
            this.entryWithOnlyData.Properties.First(p => p.Name == "ID").SetSerializationInfo(new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.Key });
            this.entryWithOnlyData.Properties.First(p => p.Name == "Name").SetSerializationInfo(new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.ETag });
            this.entryWithOnlyData2.TypeName = EntityType.FullName();
            this.entryWithOnlyData2.MediaResource = new ODataStreamReferenceValue();
            this.entryWithOnlyData2.Properties.First(p => p.Name == "ID").SetSerializationInfo(new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.Key });
            this.entryWithOnlyData2.Properties.First(p => p.Name == "Name").SetSerializationInfo(new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.ETag });
            this.entryWithOnlyData3.TypeName = EntityType.FullName();
            this.entryWithOnlyData3.MediaResource = new ODataStreamReferenceValue();
            this.entryWithOnlyData3.Properties.First(p => p.Name == "ID").SetSerializationInfo(new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.Key });
            this.entryWithOnlyData3.Properties.First(p => p.Name == "Name").SetSerializationInfo(new ODataPropertySerializationInfo { PropertyKind = ODataPropertyKind.ETag });

            ODataItem[] itemsToWrite = new ODataItem[]
            {
                feed, this.entryWithOnlyData,
                this.expandedNavLinkWithPayloadMetadata, feed, this.entryWithOnlyData2, this.navLinkWithoutPayloadMetadata,
                this.expandedNavLinkWithoutPayloadMetadata, feed, this.entryWithOnlyData3
            };

            const string selectClause = "StreamProp1,Namespace.AlwaysBindableAction1,Namespace.AlwaysBindableFunction1,DeferredNavLink";
            const string expandClause = "ExpandedNavLink($select=StreamProp1,Namespace.AlwaysBindableAction1;$expand=ExpandedNavLink($select=StreamProp2,Namespace.AlwaysBindableAction1))";
            this.GetWriterOutputForContentTypeAndKnobValue("application/json;odata.metadata=full", true, itemsToWrite, edmModel: Model, edmEntitySet: null, edmEntityType: EntityType, selectClause: selectClause, expandClause: expandClause)
                .Should().Be(expectedPayload);
        }
 public void ShouldWritePayloadWhenExpandedFeedAndEntryHasSerializationInfo()
 {
     List<ODataItem> itemsToWrite = new List<ODataItem>();
     var entry1 = new ODataEntry();
     entry1.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "MySet", NavigationSourceEntityTypeName = "NS.MyEntityType" });
     itemsToWrite.Add(entry1);
     itemsToWrite.Add(new ODataNavigationLink { Name = "EntitySetReferenceProperty", IsCollection = true });
     var feed = new ODataFeed();
     feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "MySet", NavigationSourceEntityTypeName = "NS.MyEntityType" });
     itemsToWrite.Add(feed);
     var entry2 = new ODataEntry();
     entry2.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "MySet2", NavigationSourceEntityTypeName = "NS.MyEntityType2" });
     itemsToWrite.Add(entry2);
     const string expectedPayload = "{\"@odata.context\":\"http://odata.org/test/$metadata#MySet/$entity\",\"EntitySetReferenceProperty\":[{}]}";
     this.WriteNestedItemsAndValidatePayload(entitySetFullName: null, derivedEntityTypeFullName: null, nestedItemToWrite: itemsToWrite.ToArray(), expectedPayload: expectedPayload, writingResponse: true);
 }
Example #10
0
        private void WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer,
                               ODataSerializerContext writeContext)
        {
            Contract.Assert(writer != null);
            Contract.Assert(writeContext != null);
            Contract.Assert(enumerable != null);
            Contract.Assert(feedType != null);

            IEdmEntityTypeReference elementType = GetEntityType(feedType);
            ODataFeed feed = CreateODataFeed(enumerable, feedType.AsCollection(), writeContext);

            if (feed == null)
            {
                throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, Feed));
            }

            IEdmEntitySetBase entitySet = writeContext.NavigationSource as IEdmEntitySetBase;

            if (entitySet == null)
            {
                feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo
                {
                    IsFromCollection = true,
                    NavigationSourceEntityTypeName = elementType.FullName(),
                    NavigationSourceKind           = EdmNavigationSourceKind.UnknownEntitySet,
                    NavigationSourceName           = null
                });
            }

            ODataEdmTypeSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(elementType);

            if (entrySerializer == null)
            {
                throw new SerializationException(
                          Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName(), typeof(ODataMediaTypeFormatter).Name));
            }

            // save this for later to support JSON odata.streaming.
            Uri nextPageLink = feed.NextPageLink;

            feed.NextPageLink = null;

            writer.WriteStart(feed);

            foreach (object entry in enumerable)
            {
                if (entry == null)
                {
                    throw new SerializationException(SRResources.NullElementInCollection);
                }

                entrySerializer.WriteObjectInline(entry, elementType, writer, writeContext);
            }

            // Subtle and suprising 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)
            {
                feed.NextPageLink = nextPageLink;
            }

            writer.WriteEnd();
        }
Example #11
0
        private string WriteAndVerifyEmployeeFeed(ODataMessageWriterSettings settings, string mimeType, bool hasModel)
        {
            // create a feed with two entries
            var employeeFeed = new ODataFeed();

            if (mimeType == MimeTypes.ApplicationAtomXml)
            {
                employeeFeed.Id = new Uri(this.ServiceUri + "Person/" + NameSpace + "Employee");
            }

            if (!hasModel)
            {
                employeeFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceName = "Person", NavigationSourceEntityTypeName = NameSpace + "Person", ExpectedTypeName = NameSpace + "Employee"
                });
            }

            ODataEntry employeeEntry        = WritePayloadHelper.CreateEmployeeEntryNoMetadata(false);
            ODataEntry specialEmployeeEntry = WritePayloadHelper.CreateSpecialEmployeeEntryNoMetadata(false);

            // expected result with AutoGeneratedUrlsShouldPutKeyValueInDedicatedSegment
            Dictionary <string, object> expectedEmployeeObject        = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.EmployeeType, "Person/-3", employeeEntry, hasModel, true);
            Dictionary <string, object> expectedSpecialEmployeeObject = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.SpecialEmployeeType, "Person/-10", specialEmployeeEntry, hasModel, true);

            // write the response message and read using ODL reader
            var responseMessage = new StreamResponseMessage(new MemoryStream());

            responseMessage.SetHeader("Content-Type", mimeType);
            string result = string.Empty;

            using (var messageWriter = this.CreateODataMessageWriter(responseMessage, settings, hasModel))
            {
                var odataWriter = this.CreateODataFeedWriter(messageWriter, WritePayloadHelper.PersonSet, WritePayloadHelper.EmployeeType, hasModel);
                odataWriter.WriteStart(employeeFeed);

                odataWriter.WriteStart(employeeEntry);
                odataWriter.WriteEnd();

                // toggle AutoComputePayloadMetadataInJson, this should not affect the writing result
                settings.AutoComputePayloadMetadataInJson = !settings.AutoComputePayloadMetadataInJson;

                odataWriter.WriteStart(specialEmployeeEntry);
                odataWriter.WriteEnd();

                odataWriter.WriteEnd();

                result = this.ReadFeedEntryMessage(true, responseMessage, mimeType, WritePayloadHelper.PersonSet, WritePayloadHelper.PersonType);
            }

            // For Json light, verify the resulting metadata is as expected
            if (mimeType != MimeTypes.ApplicationAtomXml)
            {
                JavaScriptSerializer        jScriptSerializer = new JavaScriptSerializer();
                Dictionary <string, object> resultObject      = jScriptSerializer.DeserializeObject(result) as Dictionary <string, object>;

                VerifyODataContextAnnotation(this.ServiceUri + "$metadata#Person/" + NameSpace + "Employee", resultObject, mimeType);

                settings.AutoComputePayloadMetadataInJson = !settings.AutoComputePayloadMetadataInJson;
                VerifyEntry(expectedEmployeeObject, employeeEntry, new ODataNavigationLink[] { }, new ODataProperty[] { }, (resultObject.Last().Value as object[]).First() as Dictionary <string, object>, mimeType, settings.AutoComputePayloadMetadataInJson);
                VerifyEntry(expectedSpecialEmployeeObject, specialEmployeeEntry, new ODataNavigationLink[] { }, new ODataProperty[] { }, (resultObject.Last().Value as object[]).Last() as Dictionary <string, object>, mimeType, settings.AutoComputePayloadMetadataInJson);
            }

            return(result);
        }
Example #12
0
        private string WriteAndVerifyPersonFeed(ODataMessageWriterSettings settings, string mimeType, bool hasModel)
        {
            // create a Person feed containing a person, an employee, a special employee
            var personFeed = new ODataFeed();

            if (mimeType == MimeTypes.ApplicationAtomXml)
            {
                personFeed.Id = new Uri(this.ServiceUri + "Person");
            }

            if (!hasModel)
            {
                personFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceName = "Person", NavigationSourceEntityTypeName = NameSpace + "Person"
                });
            }

            ODataEntry personEntry = WritePayloadHelper.CreatePersonEntryNoMetadata(hasModel);
            Dictionary <string, object> expectedPersonObject = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.PersonType, "Person(-5)", personEntry, hasModel);

            ODataEntry employeeEntry = WritePayloadHelper.CreateEmployeeEntryNoMetadata(hasModel);
            Dictionary <string, object> expectedEmployeeObject = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.EmployeeType, "Person(-3)", employeeEntry, hasModel, true);

            ODataEntry specialEmployeeEntry = WritePayloadHelper.CreateSpecialEmployeeEntryNoMetadata(hasModel);
            Dictionary <string, object> expectedSpecialEmployeeObject = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.SpecialEmployeeType, "Person(-10)", specialEmployeeEntry, hasModel, true);

            // write the response message and read using ODL reader
            var responseMessage = new StreamResponseMessage(new MemoryStream());

            responseMessage.SetHeader("Content-Type", mimeType);
            string result = string.Empty;

            using (var messageWriter = this.CreateODataMessageWriter(responseMessage, settings, hasModel))
            {
                var odataWriter = this.CreateODataFeedWriter(messageWriter, WritePayloadHelper.PersonSet, WritePayloadHelper.PersonType, hasModel);
                odataWriter.WriteStart(personFeed);

                odataWriter.WriteStart(personEntry);
                odataWriter.WriteEnd();

                odataWriter.WriteStart(employeeEntry);
                odataWriter.WriteEnd();

                odataWriter.WriteStart(specialEmployeeEntry);
                odataWriter.WriteEnd();

                // Finish writing the feed.
                odataWriter.WriteEnd();

                result = this.ReadFeedEntryMessage(true, responseMessage, mimeType, WritePayloadHelper.PersonSet, WritePayloadHelper.PersonType);
            }

            // For Json light, verify the resulting metadata is as expected
            if (mimeType != MimeTypes.ApplicationAtomXml)
            {
                JavaScriptSerializer        jScriptSerializer = new JavaScriptSerializer();
                Dictionary <string, object> resultObject      = jScriptSerializer.DeserializeObject(result) as Dictionary <string, object>;

                VerifyODataContextAnnotation(this.ServiceUri + "$metadata#Person", resultObject, mimeType);

                VerifyEntry(expectedPersonObject, personEntry, new ODataNavigationLink[] { }, new ODataProperty[] { }, (resultObject.Last().Value as object[]).ElementAt(0) as Dictionary <string, object>, mimeType, settings.AutoComputePayloadMetadataInJson);
                VerifyEntry(expectedEmployeeObject, employeeEntry, new ODataNavigationLink[] { }, new ODataProperty[] { }, (resultObject.Last().Value as object[]).ElementAt(1) as Dictionary <string, object>, mimeType, settings.AutoComputePayloadMetadataInJson);
                VerifyEntry(expectedSpecialEmployeeObject, specialEmployeeEntry, new ODataNavigationLink[] { }, new ODataProperty[] { }, (resultObject.Last().Value as object[]).ElementAt(2) as Dictionary <string, object>, mimeType, settings.AutoComputePayloadMetadataInJson);
            }

            return(result);
        }
Example #13
0
        private string WriteAndVerifyExpandedCustomerEntry(ODataMessageWriterSettings settings, string mimeType, string expectedProjectionClause, bool hasModel)
        {
            ODataEntry customerEntry = WritePayloadHelper.CreateCustomerEntryNoMetadata(hasModel);
            Dictionary <string, object> expectedCustomerObject = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.CustomerType, "Customer(-9)", customerEntry, hasModel);
            var thumbnailProperty = WritePayloadHelper.AddCustomerMediaProperty(customerEntry, expectedCustomerObject);

            // order navigation
            var orderNavigation = WritePayloadHelper.CreateCustomerOrderNavigation(expectedCustomerObject);

            // expanded logins navigation containing a Login instance
            var expandedLoginsNavigation = WritePayloadHelper.CreateExpandedCustomerLoginsNavigation(expectedCustomerObject);
            var loginFeed = new ODataFeed();

            if (mimeType == MimeTypes.ApplicationAtomXml)
            {
                loginFeed.Id = new Uri(this.ServiceUri + "Customer(-9)/Logins");
            }

            if (!hasModel)
            {
                loginFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceName = "Login", NavigationSourceEntityTypeName = NameSpace + "Login"
                });
            }

            var loginEntry = WritePayloadHelper.CreateLoginEntryNoMetadata(hasModel);
            Dictionary <string, object> expectedLoginObject = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.LoginType, "Login('2')", loginEntry, hasModel);

            this.RemoveNonSelectedMetadataFromExpected(expectedCustomerObject, expectedLoginObject, hasModel);

            // write the response message and read using ODL reader
            var responseMessage = new StreamResponseMessage(new MemoryStream());

            responseMessage.SetHeader("Content-Type", mimeType);
            string result = string.Empty;

            using (var messageWriter = this.CreateODataMessageWriter(responseMessage, settings, hasModel))
            {
                var odataWriter = this.CreateODataEntryWriter(messageWriter, WritePayloadHelper.CustomerSet, WritePayloadHelper.CustomerType, hasModel);

                odataWriter.WriteStart(customerEntry);

                odataWriter.WriteStart(orderNavigation);
                odataWriter.WriteEnd();

                // write expanded navigation
                odataWriter.WriteStart(expandedLoginsNavigation);

                odataWriter.WriteStart(loginFeed);
                odataWriter.WriteStart(loginEntry);
                odataWriter.WriteEnd();
                odataWriter.WriteEnd();

                // Finish writing expandedNavigation.
                odataWriter.WriteEnd();

                // Finish writing customerEntry.
                odataWriter.WriteEnd();

                result = this.ReadFeedEntryMessage(false, responseMessage, mimeType, WritePayloadHelper.CustomerSet, WritePayloadHelper.CustomerType);
            }

            // For Json light, verify the resulting metadata is as expected
            if (mimeType != MimeTypes.ApplicationAtomXml)
            {
                JavaScriptSerializer        jScriptSerializer = new JavaScriptSerializer();
                Dictionary <string, object> resultObject      = jScriptSerializer.DeserializeObject(result) as Dictionary <string, object>;

                VerifyODataContextAnnotation(this.ServiceUri + "$metadata#Customer(" + expectedProjectionClause + ")/$entity", resultObject, mimeType);

                VerifyEntry(expectedCustomerObject, customerEntry, new ODataNavigationLink[] { orderNavigation, expandedLoginsNavigation }, new ODataProperty[] { thumbnailProperty }, resultObject, mimeType, settings.AutoComputePayloadMetadataInJson);
                VerifyEntry(expectedLoginObject, loginEntry, new ODataNavigationLink[] { }, new ODataProperty[] { }, (resultObject["Logins"] as object[]).Single() as Dictionary <string, object>, mimeType, settings.AutoComputePayloadMetadataInJson);
            }

            return(result);
        }
        public void ShouldBeAbleToWriteFeedAndEntryResponseInJsonLightWithoutModel()
        {
            const string expectedPayload =
                "{" +
                "\"@odata.context\":\"http://www.example.com/$metadata#Customers/NS.VIPCustomer\"," +
                "\"value\":[" +
                "{" +
                "\"Name\":\"Bob\"," +
                "\"[email protected]\":\"MostRecentOrder\"," +
                "\"MostRecentOrder\":{\"OrderId\":101}" +
                "}" +
                "]" +
                "}";

            var writerSettings = new ODataMessageWriterSettings {
                DisableMessageStreamDisposal = true
            };

            writerSettings.SetContentType(ODataFormat.Json);
            writerSettings.ODataUri = new ODataUri()
            {
                ServiceRoot = new Uri("http://www.example.com")
            };

            MemoryStream          stream          = new MemoryStream();
            IODataResponseMessage responseMessage = new InMemoryMessage {
                StatusCode = 200, Stream = stream
            };

            // Write payload
            using (var messageWriter = new ODataMessageWriter(responseMessage, writerSettings))
            {
                var odataWriter = messageWriter.CreateODataFeedWriter();

                // Create customers feed with serializtion info to write odata.metadata.
                var customersFeed = new ODataFeed();
                customersFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo {
                    NavigationSourceName = "Customers", NavigationSourceEntityTypeName = "NS.Customer", ExpectedTypeName = "NS.VIPCustomer"
                });

                // Write customers feed.
                odataWriter.WriteStart(customersFeed);

                // Write VIP customer
                {
                    // Create VIP customer, don't need to pass in serialization info since the writer knows the context from the feed scope.
                    var vipCustomer = new ODataEntry {
                        TypeName = "NS.VIPCustomer"
                    };

                    var customerKey = new ODataProperty {
                        Name = "Name", Value = "Bob"
                    };

                    // Provide serialization info at the property level to compute the edit link.
                    customerKey.SetSerializationInfo(new ODataPropertySerializationInfo {
                        PropertyKind = ODataPropertyKind.Key
                    });
                    vipCustomer.Properties = new[] { customerKey };

                    // Write customer entry.
                    odataWriter.WriteStart(vipCustomer);

                    // Write expanded most recent order
                    {
                        // No API to set serialization info on ODataNavigationLink since what we are adding on ODataFeed and ODataEntry should be sufficient for the 5.5 release.
                        var navigationLink = new ODataNavigationLink {
                            Name = "MostRecentOrder", IsCollection = false, Url = new Uri("MostRecentOrder", UriKind.Relative)
                        };
                        odataWriter.WriteStart(navigationLink);

                        // Write the most recent customer.
                        {
                            var mostRecentOrder = new ODataEntry {
                                TypeName = "NS.Order"
                            };

                            // Add serialization info so we can computer links.
                            mostRecentOrder.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo {
                                NavigationSourceName = "Orders", NavigationSourceEntityTypeName = "NS.Order", ExpectedTypeName = "NS.Order"
                            });

                            var orderKey = new ODataProperty {
                                Name = "OrderId", Value = 101
                            };

                            // Provide serialization info at the property level to compute the edit link.
                            orderKey.SetSerializationInfo(new ODataPropertySerializationInfo {
                                PropertyKind = ODataPropertyKind.Key
                            });
                            mostRecentOrder.Properties = new[] { orderKey };

                            // Write order entry.
                            odataWriter.WriteStart(mostRecentOrder);
                            odataWriter.WriteEnd();
                        }

                        // End navigationLink.
                        odataWriter.WriteEnd();
                    }

                    // End customer entry.
                    odataWriter.WriteEnd();
                }

                // End customers feed.
                odataWriter.WriteEnd();
            }

            stream.Position = 0;
            string payload = (new StreamReader(stream)).ReadToEnd();

            payload.Should().Be(expectedPayload);
        }
        private string WriteAndVerifyExpandedCustomerEntry(StreamResponseMessage responseMessage,
                                                           ODataWriter odataWriter, bool hasModel, string mimeType)
        {
            ODataEntry customerEntry = WritePayloadHelper.CreateCustomerEntry(hasModel);

            odataWriter.WriteStart(customerEntry);

            // write non-expanded navigations
            foreach (var navigation in WritePayloadHelper.CreateCustomerNavigationLinks())
            {
                odataWriter.WriteStart(navigation);
                odataWriter.WriteEnd();
            }

            // write expanded navigation
            var expandedNavigation = new ODataNavigationLink()
            {
                Name         = "Logins",
                IsCollection = true,
                Url          = new Uri(this.ServiceUri + "Customer(-9)/Logins")
            };

            odataWriter.WriteStart(expandedNavigation);

            var loginFeed = new ODataFeed()
            {
                Id = new Uri(this.ServiceUri + "Customer(-9)/Logins")
            };

            if (!hasModel)
            {
                loginFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceName = "Login", NavigationSourceEntityTypeName = NameSpace + "Login"
                });
            }

            odataWriter.WriteStart(loginFeed);

            var loginEntry = WritePayloadHelper.CreateLoginEntry(hasModel);

            odataWriter.WriteStart(loginEntry);

            foreach (var navigation in WritePayloadHelper.CreateLoginNavigationLinks())
            {
                odataWriter.WriteStart(navigation);
                odataWriter.WriteEnd();
            }

            // Finish writing loginEntry.
            odataWriter.WriteEnd();

            // Finish writing the loginFeed.
            odataWriter.WriteEnd();

            // Finish writing expandedNavigation.
            odataWriter.WriteEnd();

            // Finish writing customerEntry.
            odataWriter.WriteEnd();

            // Some very basic verification for the payload.
            bool verifyFeedCalled         = false;
            int  verifyEntryCalled        = 0;
            bool verifyNavigationCalled   = false;
            Action <ODataFeed> verifyFeed = (feed) =>
            {
                verifyFeedCalled = true;
            };

            Action <ODataEntry> verifyEntry = (entry) =>
            {
                if (entry.TypeName.Contains("Customer"))
                {
                    Assert.AreEqual(7, entry.Properties.Count());
                }

                if (entry.TypeName.Contains("Login"))
                {
                    Assert.AreEqual(2, entry.Properties.Count());
                }

                verifyEntryCalled++;
            };

            Action <ODataNavigationLink> verifyNavigation = (navigation) =>
            {
                Assert.IsNotNull(navigation.Name);
                verifyNavigationCalled = true;
            };

            Stream stream = responseMessage.GetStream();

            if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
            {
                stream.Seek(0, SeekOrigin.Begin);
                WritePayloadHelper.ReadAndVerifyFeedEntryMessage(false, responseMessage, WritePayloadHelper.CustomerSet, WritePayloadHelper.CustomerType,
                                                                 verifyFeed, verifyEntry, verifyNavigation);
                Assert.IsTrue(verifyFeedCalled && verifyEntryCalled == 2 && verifyNavigationCalled,
                              "Verification action not called.");
            }

            return(WritePayloadHelper.ReadStreamContent(stream));
        }
Example #16
0
        private string WriteAndVerifyOrderFeed(ODataMessageWriterSettings settings, string mimeType, bool hasModel)
        {
            // create a feed with two entries
            var orderFeed = new ODataFeed()
            {
                NextPageLink = new Uri(this.ServiceUri + "Order?$skiptoken=-9"),
                Count        = 9999
            };

            if (mimeType == MimeTypes.ApplicationAtomXml)
            {
                orderFeed.Id = new Uri(this.ServiceUri + "Order");
            }

            if (!hasModel)
            {
                orderFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceName = "Order", NavigationSourceEntityTypeName = NameSpace + "Order"
                });
            }

            var orderEntry1 = WritePayloadHelper.CreateOrderEntry1NoMetadata(hasModel);
            Dictionary <string, object> expectedOrderObject1 = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.OrderType, "Order(-10)", orderEntry1, hasModel);

            var orderEntry2 = WritePayloadHelper.CreateOrderEntry2NoMetadata(hasModel);
            Dictionary <string, object> expectedOrderObject2 = WritePayloadHelper.ComputeExpectedFullMetadataEntryObject(WritePayloadHelper.OrderType, "Order(-9)", orderEntry2, hasModel);
            var orderEntry2Navigation = WritePayloadHelper.AddOrderEntryCustomNavigation(orderEntry2, expectedOrderObject2, hasModel);

            // write the response message and read using ODL reader
            var responseMessage = new StreamResponseMessage(new MemoryStream());

            responseMessage.SetHeader("Content-Type", mimeType);
            string result = string.Empty;

            using (var messageWriter = this.CreateODataMessageWriter(responseMessage, settings, hasModel))
            {
                var odataWriter = this.CreateODataFeedWriter(messageWriter, WritePayloadHelper.OrderSet, WritePayloadHelper.OrderType, hasModel);

                odataWriter.WriteStart(orderFeed);

                odataWriter.WriteStart(orderEntry1);
                odataWriter.WriteEnd();

                odataWriter.WriteStart(orderEntry2);
                odataWriter.WriteStart(orderEntry2Navigation);
                odataWriter.WriteEnd();
                odataWriter.WriteEnd();

                // Finish writing the feed.
                odataWriter.WriteEnd();

                result = this.ReadFeedEntryMessage(true, responseMessage, mimeType, WritePayloadHelper.OrderSet, WritePayloadHelper.OrderType);
            }

            if (mimeType != MimeTypes.ApplicationAtomXml)
            {
                JavaScriptSerializer        jScriptSerializer = new JavaScriptSerializer();
                Dictionary <string, object> resultObject      = jScriptSerializer.DeserializeObject(result) as Dictionary <string, object>;

                Assert.AreEqual(this.ServiceUri + "Order?$skiptoken=-9", resultObject.Single(e => e.Key == (JsonLightConstants.ODataNextLinkAnnotationName)).Value, "Feed next link");
                Assert.AreEqual(9999, resultObject.Single(e => e.Key == (JsonLightConstants.ODataCountAnnotationName)).Value, "Feed count");
                resultObject.Remove(JsonLightConstants.ODataNextLinkAnnotationName);
                resultObject.Remove(JsonLightConstants.ODataCountAnnotationName);

                VerifyODataContextAnnotation(this.ServiceUri + "$metadata#Order", resultObject, mimeType);

                VerifyEntry(expectedOrderObject1, orderEntry1, new ODataNavigationLink[] { }, new ODataProperty[] { }, (resultObject.Last().Value as object[]).First() as Dictionary <string, object>, mimeType, settings.AutoComputePayloadMetadataInJson);
                VerifyEntry(expectedOrderObject2, orderEntry2, new ODataNavigationLink[] { orderEntry2Navigation }, new ODataProperty[] { }, (resultObject.Last().Value as object[]).Last() as Dictionary <string, object>, mimeType, settings.AutoComputePayloadMetadataInJson);
            }

            return(result);
        }
        private string WriteAndVerifyPersonFeed(StreamResponseMessage responseMessage, ODataWriter odataWriter,
                                                bool hasModel, string mimeType)
        {
            var personFeed = new ODataFeed()
            {
                Id        = new Uri(this.ServiceUri + "Person"),
                DeltaLink = new Uri(this.ServiceUri + "Person")
            };

            if (!hasModel)
            {
                personFeed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceName = "Person", NavigationSourceEntityTypeName = NameSpace + "Person"
                });
            }

            odataWriter.WriteStart(personFeed);

            ODataEntry personEntry = WritePayloadHelper.CreatePersonEntry(hasModel);

            odataWriter.WriteStart(personEntry);

            var personNavigation = new ODataNavigationLink()
            {
                Name         = "PersonMetadata",
                IsCollection = true,
                Url          = new Uri("Person(-5)/PersonMetadata", UriKind.Relative)
            };

            odataWriter.WriteStart(personNavigation);
            odataWriter.WriteEnd();

            // Finish writing personEntry.
            odataWriter.WriteEnd();

            ODataEntry employeeEntry = WritePayloadHelper.CreateEmployeeEntry(hasModel);

            odataWriter.WriteStart(employeeEntry);

            var employeeNavigation1 = new ODataNavigationLink()
            {
                Name         = "PersonMetadata",
                IsCollection = true,
                Url          = new Uri("Person(-3)/" + NameSpace + "Employee" + "/PersonMetadata", UriKind.Relative)
            };

            odataWriter.WriteStart(employeeNavigation1);
            odataWriter.WriteEnd();

            var employeeNavigation2 = new ODataNavigationLink()
            {
                Name         = "Manager",
                IsCollection = false,
                Url          = new Uri("Person(-3)/" + NameSpace + "Employee" + "/Manager", UriKind.Relative)
            };

            odataWriter.WriteStart(employeeNavigation2);
            odataWriter.WriteEnd();

            // Finish writing employeeEntry.
            odataWriter.WriteEnd();

            ODataEntry specialEmployeeEntry = WritePayloadHelper.CreateSpecialEmployeeEntry(hasModel);

            odataWriter.WriteStart(specialEmployeeEntry);

            var specialEmployeeNavigation1 = new ODataNavigationLink()
            {
                Name         = "PersonMetadata",
                IsCollection = true,
                Url          = new Uri("Person(-10)/" + NameSpace + "SpecialEmployee" + "/PersonMetadata", UriKind.Relative)
            };

            odataWriter.WriteStart(specialEmployeeNavigation1);
            odataWriter.WriteEnd();

            var specialEmployeeNavigation2 = new ODataNavigationLink()
            {
                Name         = "Manager",
                IsCollection = false,
                Url          = new Uri("Person(-10)/" + NameSpace + "SpecialEmployee" + "/Manager", UriKind.Relative)
            };

            odataWriter.WriteStart(specialEmployeeNavigation2);
            odataWriter.WriteEnd();

            var specialEmployeeNavigation3 = new ODataNavigationLink()
            {
                Name         = "Car",
                IsCollection = false,
                Url          = new Uri("Person(-10)/" + NameSpace + "SpecialEmployee" + "/Manager", UriKind.Relative)
            };

            odataWriter.WriteStart(specialEmployeeNavigation3);
            odataWriter.WriteEnd();

            // Finish writing specialEmployeeEntry.
            odataWriter.WriteEnd();

            // Finish writing the feed.
            odataWriter.WriteEnd();

            // Some very basic verification for the payload.
            bool verifyFeedCalled         = false;
            bool verifyEntryCalled        = false;
            bool verifyNavigationCalled   = false;
            Action <ODataFeed> verifyFeed = (feed) =>
            {
                if (mimeType != MimeTypes.ApplicationAtomXml)
                {
                    Assert.IsTrue(feed.DeltaLink.AbsoluteUri.Contains("Person"));
                }
                verifyFeedCalled = true;
            };
            Action <ODataEntry> verifyEntry = (entry) =>
            {
                Assert.IsTrue(entry.EditLink.AbsoluteUri.EndsWith("Person(-5)") ||
                              entry.EditLink.AbsoluteUri.EndsWith("Person(-3)/" + NameSpace + "Employee") ||
                              entry.EditLink.AbsoluteUri.EndsWith("Person(-10)/" + NameSpace + "SpecialEmployee"));
                verifyEntryCalled = true;
            };
            Action <ODataNavigationLink> verifyNavigation = (navigation) =>
            {
                Assert.IsTrue(navigation.Name == "PersonMetadata" || navigation.Name == "Manager" || navigation.Name == "Car");
                verifyNavigationCalled = true;
            };

            Stream stream = responseMessage.GetStream();

            if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
            {
                stream.Seek(0, SeekOrigin.Begin);
                WritePayloadHelper.ReadAndVerifyFeedEntryMessage(true, responseMessage, WritePayloadHelper.PersonSet, WritePayloadHelper.PersonType, verifyFeed,
                                                                 verifyEntry, verifyNavigation);
                Assert.IsTrue(verifyFeedCalled && verifyEntryCalled && verifyNavigationCalled,
                              "Verification action not called.");
            }

            return(WritePayloadHelper.ReadStreamContent(stream));
        }
Example #18
0
        public static void FeedWriteReadNormal()
        {
            ODataFeed Feed = new ODataFeed();

            Feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
            {
                NavigationSourceName           = "Mails",
                NavigationSourceEntityTypeName = "NS.Mail",
                NavigationSourceKind           = EdmNavigationSourceKind.ContainedEntitySet
            });

            ODataEntry Entry = new ODataEntry()
            {
                Properties = new[]
                {
                    new ODataProperty()
                    {
                        Name = "Id", Value = 2
                    },
                },
                EditLink = new Uri("http://example/Web/Users(3)"),
            };

            Entry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
            {
                NavigationSourceName           = "MyLogin",
                NavigationSourceEntityTypeName = "NS.Person",
                NavigationSourceKind           = EdmNavigationSourceKind.ContainedEntitySet
            });

            // Parse the full request Uri
            ODataPath path = new ODataUriParser(
                CraftModel.Model,
                new Uri("http://example.org/svc/"),
                new Uri("http://example.org/svc/MyLogin/Mails")).ParsePath();

            // Alternatively, construct the normal path for the contained entity manually.
            //ODataPath path = new ODataPath(
            //    new ODataPathSegment[]
            //    {
            //        new SingletonSegment(CraftModel.MyLogin), new NavigationPropertySegment(CraftModel.MailBox, CraftModel.MyLogin)
            //    });

            var stream = new MemoryStream();

            var wsetting = new ODataMessageWriterSettings()
            {
                DisableMessageStreamDisposal = true,

                ODataUri = new ODataUri()
                {
                    ServiceRoot = new Uri("http://example.org/svc/"),
                    Path        = path
                }
            };
            IODataResponseMessage msg = new Message()
            {
                Stream = stream,
            };

            var omw    = new ODataMessageWriter(msg, wsetting);
            var writer = omw.CreateODataFeedWriter();

            writer.WriteStart(Feed);
            writer.WriteStart(Entry);
            writer.WriteEnd();
            writer.WriteEnd();

            stream.Seek(0, SeekOrigin.Begin);
            var payload = new StreamReader(stream).ReadToEnd();

            // {"@odata.context":"http://example.org/svc/$metadata#Web/Items","value":[{"@odata.editLink":"http://example/Web/Users(3)","Id":2}]}
            Console.WriteLine(payload);

            //Read
            ODataEntry entry = null;

            stream.Seek(0, SeekOrigin.Begin);
            var rsetting = new ODataMessageReaderSettings();
            var omr      = new ODataMessageReader(msg, rsetting, CraftModel.Model);
            var reader   = omr.CreateODataFeedReader();

            while (reader.Read())
            {
                if (reader.State == ODataReaderState.EntryEnd)
                {
                    entry = (ODataEntry)reader.Item;
                    break;
                }
            }

            //Id=2
            foreach (var prop in entry.Properties)
            {
                Console.WriteLine("{0}={1}", prop.Name, prop.Value);
            }
        }
Example #19
0
        /// <summary>
        /// Writes the feed element for the atom payload.
        /// </summary>
        /// <param name="expanded">Expanded properties for the result.</param>
        /// <param name="elements">Collection of entries in the feed element.</param>
        /// <param name="expectedType">ExpectedType of the elements in the collection.</param>
        /// <param name="title">Title of the feed element.</param>
        /// <param name="getRelativeUri">Callback to get the relative uri of the feed.</param>
        /// <param name="getAbsoluteUri">Callback to get the absolute uri of the feed.</param>
        /// <param name="topLevel">True if the feed is the top level feed, otherwise false for the inner expanded feed.</param>
        private void WriteFeedElements(
            IExpandedResult expanded,
            QueryResultInfo elements,
            ResourceType expectedType,
            string title,
            Func <Uri> getRelativeUri,
            Func <Uri> getAbsoluteUri,
            bool topLevel)
        {
            Debug.Assert(elements != null, "elements != null");
            Debug.Assert(expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType, "expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType");
            Debug.Assert(!string.IsNullOrEmpty(title), "!string.IsNullOrEmpty(title)");

            ODataFeed feed = new ODataFeed();

            feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo {
                NavigationSourceName = this.CurrentContainer.Name, NavigationSourceEntityTypeName = this.CurrentContainer.ResourceType.FullName, ExpectedTypeName = expectedType.FullName
            });

            // Write the other elements for the feed
            this.PayloadMetadataPropertyManager.SetId(feed, () => getAbsoluteUri());

#pragma warning disable 618
            if (this.contentFormat == ODataFormat.Atom)
#pragma warning restore 618
            {
                // Create the atom feed metadata and set the self link and title value.
                AtomFeedMetadata feedMetadata = new AtomFeedMetadata();
                feed.SetAnnotation(feedMetadata);
                feedMetadata.Title = new AtomTextConstruct {
                    Text = title
                };
                feedMetadata.SelfLink = new AtomLinkMetadata {
                    Href = getRelativeUri(), Title = title
                };
            }

            // support for $count
            // in ATOM we write it at the beginning (we always have)
            //   in JSON for backward compatiblity reasons we write it at the end, so we must not fill it here.
            if (topLevel && this.RequestDescription.CountOption == RequestQueryCountOption.CountQuery)
            {
                feed.Count = this.RequestDescription.CountValue;
            }

            var feedArgs = elements.GetDataServiceODataWriterFeedArgs(feed, this.Service.OperationContext);
            this.dataServicesODataWriter.WriteStart(feedArgs);
            object          lastObject            = null;
            IExpandedResult lastExpandedSkipToken = null;
            while (elements.HasMoved)
            {
                object          o         = elements.Current;
                IExpandedResult skipToken = this.GetSkipToken(expanded);

                if (o != null)
                {
                    IExpandedResult expandedO = o as IExpandedResult;
                    if (expandedO != null)
                    {
                        expanded  = expandedO;
                        o         = GetExpandedElement(expanded);
                        skipToken = this.GetSkipToken(expanded);
                    }

                    this.WriteEntry(expanded, o, true /*resourceInstanceInFeed*/, expectedType);
                }

                elements.MoveNext();
                lastObject            = o;
                lastExpandedSkipToken = skipToken;
            }

            // After looping through the objects in the sequence, decide if we need to write the next
            // page link and if yes, write it by invoking the delegate
            if (this.NeedNextPageLink(elements))
            {
                this.PayloadMetadataPropertyManager.SetNextPageLink(
                    feed,
                    this.AbsoluteServiceUri,
                    this.GetNextLinkUri(lastObject, lastExpandedSkipToken, getAbsoluteUri()));
            }

            this.dataServicesODataWriter.WriteEnd(feedArgs);
#if ASTORIA_FF_CALLBACKS
            this.Service.InternalOnWriteFeed(feed);
#endif
        }
 public void ShouldWritePayloadWhenFeedAndEntryHasSerializationInfo()
 {
     var feed = new ODataFeed();
     feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "MySet", NavigationSourceEntityTypeName = "NS.MyEntityType" });
     var entry = new ODataEntry();
     entry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "MySet2", NavigationSourceEntityTypeName = "NS.MyEntityType2" });
     List<ODataItem> itemsToWrite = new List<ODataItem>() { feed, entry };
     const string expectedPayload = "{\"@odata.context\":\"http://odata.org/test/$metadata#MySet\",\"value\":[{}]}";
     this.WriteNestedItemsAndValidatePayload(entitySetFullName: null, derivedEntityTypeFullName: null, nestedItemToWrite: itemsToWrite.ToArray(), expectedPayload: expectedPayload, writingResponse: true);
 }