public void BuildUrlWithNewODataUri()
        {
            ODataUri uri = new ODataUri();
            uri.ServiceRoot = new Uri("http://gobbledygook/");
            uri.Skip = 4;
            uri.Top = 5;
            uri.Path = new ODataPath(new EntitySetSegment(HardCodedTestModel.GetPeopleSet()));
            Assert.AreEqual(uri.ParameterAliasNodes.Count, 0);

            ODataUriBuilder builder = new ODataUriBuilder(ODataUrlConventions.Default, uri);
            Uri res = builder.BuildUri();
            Assert.AreEqual(new Uri("http://gobbledygook/People?$top=5&$skip=4"), res);
        }
 public void BuildPathWithFunctionImport()
 {
     ODataUri odataUri = new ODataUri();
     odataUri.ServiceRoot = new Uri("http://gobbledygook/");
     IEdmOperationImport functionImport = HardCodedTestModel.TestModel.EntityContainer.FindOperationImports("GetPet1").Single();
     IEdmEntitySetReferenceExpression reference = functionImport.EntitySet as IEdmEntitySetReferenceExpression;
     OperationSegmentParameter[] parameters = new OperationSegmentParameter[] { new OperationSegmentParameter("id", new ConstantNode(1, "1")) };
     odataUri.Path = new ODataPath(new OperationImportSegment(
         new IEdmOperationImport[] { functionImport },
         reference.ReferencedEntitySet,
         parameters));
     ODataUriBuilder odataUriBuilder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri);
     Uri actual = odataUriBuilder.BuildUri();
     Assert.AreEqual(new Uri("http://gobbledygook/GetPet1(id=1)"), actual);
 }
Exemple #3
0
            internal Scope(ODataReaderState state, ODataItem item, IEdmNavigationSource navigationSource, IEdmEntityType expectedEntityType, ODataUri odataUri)
            {
                Debug.Assert(
                    state == ODataReaderState.Exception && item == null ||
                    state == ODataReaderState.EntryStart && (item == null || item is ODataEntry) ||
                    state == ODataReaderState.EntryEnd && (item == null || item is ODataEntry) ||
                    state == ODataReaderState.FeedStart && item is ODataFeed ||
                    state == ODataReaderState.FeedEnd && item is ODataFeed ||
                    state == ODataReaderState.NavigationLinkStart && item is ODataNavigationLink ||
                    state == ODataReaderState.NavigationLinkEnd && item is ODataNavigationLink ||
                    state == ODataReaderState.EntityReferenceLink && item is ODataEntityReferenceLink ||
                    state == ODataReaderState.Start && item == null ||
                    state == ODataReaderState.Completed && item == null,
                    "Reader state and associated item do not match.");

                this.state            = state;
                this.item             = item;
                this.EntityType       = expectedEntityType;
                this.NavigationSource = navigationSource;
                this.odataUri         = odataUri;
            }
        public void WriteContainedEntitySet()
        {
            EdmModel model = new EdmModel();
            EdmEntityType entityType = GetEntityType();
            model.AddElement(entityType);
            IEdmNavigationSource containedEntitySet = GetContainedEntitySet(model, entityType);
            var requestUri = new Uri("http://temp.org/FakeSet('parent')/nav");
            var odataUri = new ODataUri { RequestUri = requestUri };
            odataUri.Path = new ODataUriParser(model, new Uri("http://temp.org/"), requestUri).ParsePath();

            ODataEntry entry = new ODataEntry() { Properties = new[] { new ODataProperty { Name = "Key", Value = "son" }, } };
            var actual = WriteJsonLightEntry(
                isRequest: false,
                serviceDocumentUri: new Uri("http://temp.org/"),
                specifySet: true,
                odataEntry: entry,
                entitySet: containedEntitySet,
                entityType: containedEntitySet.Type as IEdmEntityType,
                odataUri: odataUri);
            actual.Should().Contain("\"@odata.id\":\"FakeSet('parent')/nav('son')\"");
        }
Exemple #5
0
        private static void BuildOrderBy()
        {
            var productTypeRef = new EdmEntityTypeReference(V4Model.Product, false);
            var supplierProperty = (IEdmNavigationProperty)V4Model.Product.FindProperty("Supplier");
            var nameProperty = V4Model.Supplier.FindProperty("Name");

            var topIt = new EntityRangeVariable("$it", productTypeRef, V4Model.ProductsSet);
            var topItRef = new EntityRangeVariableReferenceNode("$it", topIt);
            var supplierNavNode = new SingleNavigationNode(supplierProperty, topItRef);
            var nameNode = new SingleValuePropertyAccessNode(supplierNavNode, nameProperty);

            var orderby = new OrderByClause(null, nameNode, OrderByDirection.Ascending, topIt);
            var odataUri = new ODataUri
            {
                Path = new ODataPath(new EntitySetSegment(V4Model.ProductsSet)),
                ServiceRoot = V4Root,
                OrderBy = orderby
            };
            var builder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri);
            Console.WriteLine(builder.BuildUri());
            // http://services.odata.org/V4/OData/OData.svc/Products?$orderby=Supplier%2FName
        }
            /// <summary>
            /// Constructor to create a new entry scope.
            /// </summary>
            /// <param name="entry">The entry for the new scope.</param>
            /// <param name="serializationInfo">The serialization info for the current entry.</param>
            /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
            /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
            /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
            /// <param name="writingResponse">true if we are writing a response, false if it's a request.</param>
            /// <param name="writerBehavior">The <see cref="ODataWriterBehavior"/> instance controlling the behavior of the writer.</param>
            /// <param name="selectedProperties">The selected properties of this scope.</param>
            /// <param name="odataUri">The ODataUri info of this scope.</param>
            /// <param name="enableValidation">Enable validation or not.</param>
            internal EntryScope(ODataEntry entry, ODataFeedAndEntrySerializationInfo serializationInfo, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, bool writingResponse, ODataWriterBehavior writerBehavior, SelectedPropertiesNode selectedProperties, ODataUri odataUri, bool enableValidation = true)
                : base(WriterState.Entry, entry, navigationSource, entityType, skipWriting, selectedProperties, odataUri)
            {
                Debug.Assert(writerBehavior != null, "writerBehavior != null");

                if (entry != null)
                {
                    this.duplicatePropertyNamesChecker = new DuplicatePropertyNamesChecker(writerBehavior.AllowDuplicatePropertyNames, writingResponse, !enableValidation);
                }

                this.serializationInfo = serializationInfo;
            }
 /// <summary>
 /// Constructor to create a new feed scope.
 /// </summary>
 /// <param name="feed">The feed for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 internal FeedScope(ODataFeed feed, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
     : base(WriterState.Feed, feed, navigationSource, entityType, skipWriting, selectedProperties, odataUri)
 {
     this.serializationInfo = feed.SerializationInfo;
 }
        public void WriteContainedEntityInDeltaFeedWithSelectExpand()
        {
            this.TestInit(this.GetModel());

            ODataDeltaFeed feed = new ODataDeltaFeed();

            ODataEntry entry = new ODataEntry()
            {
                TypeName = "MyNS.Product",
                Properties = new[]
                {
                    new ODataProperty {Name = "Id", Value = new ODataPrimitiveValue(1)}, 
                    new ODataProperty {Name = "Name", Value = new ODataPrimitiveValue("Car")},
                },
            };

            ODataEntry containedEntry = new ODataEntry()
            {
                TypeName = "MyNS.ProductDetail",
                Properties = new[]
                {
                    new ODataProperty {Name = "Id", Value = new ODataPrimitiveValue(1)}, 
                    new ODataProperty {Name = "Detail", Value = new ODataPrimitiveValue("made in china")},
                },
            };

            containedEntry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
            {
                NavigationSourceEntityTypeName = "MyNS.ProductDetail",
                NavigationSourceName = "Products(1)/Details",
                NavigationSourceKind = EdmNavigationSourceKind.ContainedEntitySet
            });


            var result = new ODataQueryOptionParser(this.GetModel(), this.GetProductType(), this.GetProducts(), new Dictionary<string, string> { { "$expand", "Details($select=Detail)" }, { "$select", "Name" } }).ParseSelectAndExpand();

            ODataUri odataUri = new ODataUri()
            {
                ServiceRoot = new Uri("http://host/service"),
                SelectAndExpand = result
            };

            var outputContext = CreateJsonLightOutputContext(this.stream, this.GetModel(), odataUri);
            ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType());
            writer.WriteStart(feed);
            writer.WriteStart(containedEntry);
            writer.WriteEnd();
            writer.WriteStart(entry);
            writer.WriteEnd();
            writer.WriteEnd();
            writer.Flush();

            string payload = this.TestFinish();
            payload.Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products(Name,Details,Details(Detail))/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Products(1)/Details/$entity\",\"Id\":1,\"Detail\":\"made in china\"},{\"Id\":1,\"Name\":\"Car\"}]}");
        }
        /// <summary>
        /// Create ODataContextUrlInfo from ODataFeedAndEntryTypeContext
        /// </summary>
        /// <param name="typeContext">The ODataFeedAndEntryTypeContext to be used.</param>
        /// <param name="isSingle">Whether target is single item.</param>
        /// <param name="odataUri">The odata uri info for current query.</param>
        /// <returns>The generated ODataContextUrlInfo.</returns>
        internal static ODataContextUrlInfo Create(ODataFeedAndEntryTypeContext typeContext, bool isSingle, ODataUri odataUri = null)
        {
            Debug.Assert(typeContext != null, "typeContext != null");

            return new ODataContextUrlInfo()
                {
                    isContained = typeContext.NavigationSourceKind == EdmNavigationSourceKind.ContainedEntitySet,
                    IsUnknownEntitySet = typeContext.NavigationSourceKind == EdmNavigationSourceKind.UnknownEntitySet,
                    navigationSource = typeContext.NavigationSourceName,
                    TypeCast = typeContext.NavigationSourceEntityTypeName == typeContext.ExpectedEntityTypeName ? null : typeContext.ExpectedEntityTypeName,
                    TypeName = typeContext.NavigationSourceFullTypeName,
                    IncludeFragmentItemSelector = isSingle && typeContext.NavigationSourceKind != EdmNavigationSourceKind.Singleton,
                    odataUri = odataUri
                };
        }
 /// <summary>
 /// Create ODataContextUrlInfo for OdataValue.
 /// </summary>
 /// <param name="value">The ODataValue to be used.</param>
 /// <param name="odataUri">The odata uri info for current query.</param>
 /// <param name="model">The model used to handle unsigned int conversions.</param>
 /// <returns>The generated ODataContextUrlInfo.</returns>
 internal static ODataContextUrlInfo Create(ODataValue value, ODataUri odataUri = null, IEdmModel model = null)
 {
     return new ODataContextUrlInfo()
     {
         TypeName = GetTypeNameForValue(value, model),
         odataUri = odataUri
     };
 }
        /// <summary>
        /// Create ODataContextUrlInfo from ODataFeedAndEntryTypeContext
        /// </summary>
        /// <param name="typeContext">The ODataFeedAndEntryTypeContext to be used.</param>
        /// <param name="isSingle">Whether target is single item.</param>
        /// <param name="odataUri">The odata uri info for current query.</param>
        /// <returns>The generated ODataContextUrlInfo.</returns>
        internal static ODataContextUrlInfo Create(ODataFeedAndEntryTypeContext typeContext, bool isSingle, ODataUri odataUri = null)
        {
            Debug.Assert(typeContext != null, "typeContext != null");

            return(new ODataContextUrlInfo()
            {
                isContained = typeContext.NavigationSourceKind == EdmNavigationSourceKind.ContainedEntitySet,
                navigationSource = typeContext.NavigationSourceName,
                TypeCast = typeContext.NavigationSourceEntityTypeName == typeContext.ExpectedEntityTypeName ? null : typeContext.ExpectedEntityTypeName,
                TypeName = typeContext.NavigationSourceEntityTypeName,
                IncludeFragmentItemSelector = isSingle && typeContext.NavigationSourceKind != EdmNavigationSourceKind.Singleton,
                odataUri = odataUri
            });
        }
 /// <summary>
 /// Creates a new navigation link scope.
 /// </summary>
 /// <param name="writerState">The writer state for the new scope.</param>
 /// <param name="navLink">The navigation link for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 /// <returns>The newly created navigation link scope.</returns>
 protected virtual NavigationLinkScope CreateNavigationLinkScope(WriterState writerState, ODataNavigationLink navLink, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
 {
     return new NavigationLinkScope(writerState, navLink, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
 }
 /// <summary>
 /// Constructor to create a new navigation link scope.
 /// </summary>
 /// <param name="writerState">The writer state for the new scope.</param>
 /// <param name="navLink">The navigation link for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 internal NavigationLinkScope(WriterState writerState, ODataNavigationLink navLink, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
     : base(writerState, navLink, navigationSource, entityType, skipWriting, selectedProperties, odataUri)
 {
 }
Exemple #14
0
        private static void BuildFilterWithBinaryOperator()
        {
            var personTypeRef = new EdmEntityTypeReference(TripPinModel.Person, false);
            var friendsProp = (IEdmNavigationProperty)TripPinModel.Person.FindProperty("Friends");
            var firstNameProp = TripPinModel.Person.FindProperty("FirstName");
            var lastNameProp = TripPinModel.Person.FindProperty("LastName");

            var topIt = new EntityRangeVariable("$it", personTypeRef, TripPinModel.PeopleSet);
            var topItRef = new EntityRangeVariableReferenceNode("$it", topIt);
            var friendsNavNode = new CollectionNavigationNode(friendsProp, topItRef);
            var e0 = new EntityRangeVariable("e0", personTypeRef, friendsNavNode);
            var e0Ref = new EntityRangeVariableReferenceNode("e0", e0);
            var fun1 = new SingleValueFunctionCallNode(
                "startswith",
                new QueryNode[]
                {
                    new SingleValuePropertyAccessNode(e0Ref, firstNameProp),
                    new ConstantNode("var1", "'var1'")
                },
                EdmCoreModel.Instance.GetBoolean(false));

            var friendsNavNode2 = new CollectionNavigationNode(friendsProp, e0Ref);
            var e1 = new EntityRangeVariable("e1", personTypeRef, friendsNavNode2);
            var e1Ref = new EntityRangeVariableReferenceNode("e1", e1);
            var fun2 = new SingleValueFunctionCallNode(
                "contains",
                new QueryNode[]
                {
                    new SingleValuePropertyAccessNode(e1Ref, lastNameProp),
                    new ConstantNode("var2", "'var2'")
                },
                EdmCoreModel.Instance.GetBoolean(false));

            // Actually $it also needed, but would not be used in UriBuilder, so omit it here.
            var any2 = new AnyNode(new Collection<RangeVariable> { e1 }, e1)
            {
                Body = fun2,
                Source = friendsNavNode2
            };

            var any1 = new AnyNode(new Collection<RangeVariable> { e0 }, e0)
            {
                Body = new BinaryOperatorNode(BinaryOperatorKind.And, fun1, any2),
                Source = friendsNavNode
            };

            var odataUri = new ODataUri
            {
                Path = new ODataPath(new EntitySetSegment(TripPinModel.PeopleSet)),
                ServiceRoot = TripPinRoot,
                Filter = new FilterClause(any1, topIt)
            };
            var builder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri);
            Console.WriteLine(builder.BuildUri());

            // http://services.odata.org/V4/TripPinService/People?$filter=Friends%2Fany(
            // e0:startswith(e0%2FFirstName%2C'var1') and e0%2FFriends%2Fany(e1:contains(e1%2FLastName%2C'var2')))
        }
Exemple #15
0
        private static void BuildFilterWithNestedAny()
        {
            var personTypeRef = new EdmEntityTypeReference(TripPinModel.Person, false);
            var tripTypeRef = new EdmEntityTypeReference(TripPinModel.Trip, false);

            var friendsProp = (IEdmNavigationProperty)TripPinModel.Person.FindProperty("Friends");
            var tripsProp = (IEdmNavigationProperty)TripPinModel.Person.FindProperty("Trips");
            var budgetProp = TripPinModel.Trip.FindProperty("Budget");

            var topIt = new EntityRangeVariable("$it", personTypeRef, TripPinModel.PeopleSet);
            var topItRef = new EntityRangeVariableReferenceNode("$it", topIt);

            var friendsNavNode0 = new CollectionNavigationNode(friendsProp, topItRef);
            var e0 = new EntityRangeVariable("e0", personTypeRef, friendsNavNode0);
            var e0Ref = new EntityRangeVariableReferenceNode("e0", e0);

            var friendsNavNode1 = new CollectionNavigationNode(friendsProp, e0Ref);
            var e1 = new EntityRangeVariable("e1", personTypeRef, friendsNavNode1);
            var e1Ref = new EntityRangeVariableReferenceNode("e1", e1);

            var tripNavNode = new CollectionNavigationNode(tripsProp, e1Ref);
            var e2 = new EntityRangeVariable("e2", tripTypeRef, friendsNavNode1);
            var e2Ref = new EntityRangeVariableReferenceNode("e2", e2);

            var bugetNode = new SingleValuePropertyAccessNode(e2Ref, budgetProp);

            var gt = new BinaryOperatorNode(
                BinaryOperatorKind.GreaterThan,
                bugetNode,
                new ConstantNode(1200, "1200"));

            var any2 = new AnyNode(new Collection<RangeVariable> { e2 }, e2) { Body = gt, Source = tripNavNode };
            var any1 = new AnyNode(new Collection<RangeVariable> { e1 }, e1) { Body = any2, Source = friendsNavNode1 };
            var any0 = new AnyNode(new Collection<RangeVariable> { e0 }, e0) { Body = any1, Source = friendsNavNode0 };


            var odataUri = new ODataUri
            {
                Path = new ODataPath(new EntitySetSegment(TripPinModel.PeopleSet)),
                ServiceRoot = TripPinRoot,
                Filter = new FilterClause(any0, topIt)
            };
            var builder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri);
            Console.WriteLine(builder.BuildUri());
            // http://services.odata.org/V4/TripPinService/People?$filter=Friends%2Fany(e0:e0%2FFriends%2Fany(e1:e1%2FTrips%2Fany(e2:e2%2FBudget gt 1200)))
        }
        private static ODataJsonLightOutputContext CreateJsonLightOutputContext(MemoryStream stream, IEdmModel userModel, ODataUri uri = null)
        {
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings { Version = ODataVersion.V4, AutoComputePayloadMetadataInJson = true, ShouldIncludeAnnotation = ODataUtils.CreateAnnotationFilter("*") };
            settings.SetServiceDocumentUri(new Uri("http://host/service"));
            if (uri != null)
            {
                settings.ODataUri = uri;
            }

            ODataMediaType mediaType = new ODataMediaType("application", "json", new List<KeyValuePair<string, string>>());
            //mediaType.Parameters.Add(new KeyValuePair<string, string>("odata.metadata", "full"));
            return new ODataJsonLightOutputContext(
                ODataFormat.Json,
                new NonDisposingStream(stream),
                mediaType,
                Encoding.UTF8,
                settings,
                /*writingResponse*/ true,
                /*synchronous*/ true,
                userModel ?? EdmCoreModel.Instance,
                /*urlResolver*/ null);
        }
        public void WriteEntityInDeltaFeedWithSelectExpand()
        {
            this.TestInit(this.GetModel());

            ODataDeltaFeed feed = new ODataDeltaFeed();

            ODataEntry orderEntry= new ODataEntry()
            {
                Properties = new List<ODataProperty>
                {
                    new ODataProperty
                    {
                        Name = "ShippingAddress",
                        Value = new ODataComplexValue
                        {
                            Properties = new List<ODataProperty>
                            {
                                new ODataProperty { Name = "City", Value = "Shanghai" },
                            }
                        }
                    }
                },
                SerializationInfo = new ODataFeedAndEntrySerializationInfo
                {
                    NavigationSourceEntityTypeName = "Order",
                    NavigationSourceKind = EdmNavigationSourceKind.EntitySet,
                    NavigationSourceName = "Orders"
                },
            };


           var result = new ODataQueryOptionParser(this.GetModel(), this.GetCustomerType(), this.GetCustomers(), new Dictionary<string, string> { { "$expand", "Orders($select=ShippingAddress)" }, { "$select", "ContactName" } }).ParseSelectAndExpand();

            ODataUri odataUri = new ODataUri()
            {
                ServiceRoot = new Uri("http://host/service"),
                SelectAndExpand = result
            };

            var outputContext = CreateJsonLightOutputContext(this.stream, this.GetModel(), odataUri);
            ODataJsonLightDeltaWriter writer = new ODataJsonLightDeltaWriter(outputContext, this.GetProducts(), this.GetProductType());
            writer.WriteStart(feed);
            writer.WriteStart(orderEntry);
            writer.WriteEnd();
            writer.WriteEnd();
            writer.Flush();

            string payload = this.TestFinish();
            payload.Should().Be("{\"@odata.context\":\"http://host/service/$metadata#Products(ContactName,Orders,Orders(ShippingAddress))/$delta\",\"value\":[{\"@odata.context\":\"http://host/service/$metadata#Orders/$entity\",\"ShippingAddress\":{\"City\":\"Shanghai\"}}]}");
        }
 /// <summary>
 /// Create a new entry scope.
 /// </summary>
 /// <param name="entry">The entry for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 /// <returns>The newly create scope.</returns>
 protected abstract EntryScope CreateEntryScope(ODataEntry entry, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri);
 protected override ODataWriterCore.EntryScope CreateEntryScope(ODataEntry entry, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
 {
     throw new NotImplementedException();
 }
        private static string WriteJsonLightEntry(bool isRequest, Uri serviceDocumentUri, bool specifySet,
            ODataEntry odataEntry, IEdmNavigationSource entitySet, IEdmEntityType entityType, ODataUri odataUri)
        {
            var model = new EdmModel();
            model.AddElement(new EdmEntityContainer("Fake", "Container_sub"));
            var stream = new MemoryStream();
            var message = new InMemoryMessage { Stream = stream };

            var settings = new ODataMessageWriterSettings { Version = ODataVersion.V4, AutoComputePayloadMetadataInJson = true };
            settings.ODataUri = odataUri;
            settings.SetServiceDocumentUri(serviceDocumentUri);

            settings.SetContentType(ODataFormat.Json);
            settings.SetContentType("application/json;odata.metadata=full", null);

            ODataMessageWriter messageWriter;
            if (isRequest)
            {
                messageWriter = new ODataMessageWriter((IODataRequestMessage)message, settings, TestUtils.WrapReferencedModelsToMainModel("Fake", "Container", model));
            }
            else
            {
                messageWriter = new ODataMessageWriter((IODataResponseMessage)message, settings, TestUtils.WrapReferencedModelsToMainModel("Fake", "Container", model));
            }

            var entryWriter = messageWriter.CreateODataEntryWriter(specifySet ? entitySet : null, entityType);
            entryWriter.WriteStart(odataEntry);
            entryWriter.WriteEnd();
            entryWriter.Flush();

            var actual = Encoding.UTF8.GetString(stream.ToArray());
            return actual;
        }
        public void ExpandWithNestedQueryOptionsShouldWork()
        {
            var ervFilter = new EntityRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetDogTypeReference(), HardCodedTestModel.GetDogsSet());
            var ervOrderby = new EntityRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetDogTypeReference(), HardCodedTestModel.GetDogsSet());
            var expand =
                new ExpandedNavigationSelectItem(
                    new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null)),
                    HardCodedTestModel.GetPeopleSet(),
                    null,
                    new FilterClause(
                        new BinaryOperatorNode(
                            BinaryOperatorKind.Equal,
                            new SingleValuePropertyAccessNode(new EntityRangeVariableReferenceNode("$it", ervFilter), HardCodedTestModel.GetDogColorProp()),
                            new ConstantNode("Brown", "'Brown'")),
                            ervFilter),
                    new OrderByClause(
                        null,
                        new SingleValuePropertyAccessNode(new EntityRangeVariableReferenceNode("$it", ervOrderby), HardCodedTestModel.GetDogColorProp()),
                        OrderByDirection.Ascending,
                        ervOrderby),
                    1,
                    /* skipOption */ null,
                    true,
                    new SearchClause(new SearchTermNode("termX")),
                    /* levelsOption*/ null);

            ODataUri uri = new ODataUri()
            {
                ServiceRoot = new Uri("http://gobbledygook/"),
                Path = new ODataPath(new EntitySetSegment(HardCodedTestModel.GetPeopleSet())),
                SelectAndExpand = new SelectExpandClause(new[] { expand }, true)
            };

            Uri actualUri = new ODataUriBuilder(ODataUrlConventions.Default, uri).BuildUri();
            Assert.AreEqual("http://gobbledygook/People?$expand=" + Uri.EscapeDataString("MyDog($filter=Color eq 'Brown';$orderby=Color;$top=1;$count=true;$search=termX)"), actualUri.OriginalString);
        }
        /// <summary>
        /// Create ODataContextUrlInfo from basic information
        /// </summary>
        /// <param name="navigationSource">Navigation source for current element.</param>\
        /// <param name="expectedEntityTypeName">The expectedEntity for current element.</param>
        /// <param name="isSingle">Whether target is single item.</param>
        /// <param name="odataUri">The odata uri info for current query.</param>
        /// <returns>The generated ODataContextUrlInfo.</returns>
        internal static ODataContextUrlInfo Create(IEdmNavigationSource navigationSource, string expectedEntityTypeName, bool isSingle, ODataUri odataUri)
        {
            EdmNavigationSourceKind kind      = navigationSource.NavigationSourceKind();
            string navigationSourceEntityType = navigationSource.EntityType().FullName();

            return(new ODataContextUrlInfo()
            {
                isContained = kind == EdmNavigationSourceKind.ContainedEntitySet,
                navigationSource = navigationSource.Name,
                TypeCast = navigationSourceEntityType == expectedEntityTypeName ? null : expectedEntityTypeName,
                TypeName = navigationSourceEntityType,
                IncludeFragmentItemSelector = isSingle && kind != EdmNavigationSourceKind.Singleton,
                odataUri = odataUri
            });
        }
        private string GetWriterOutputForContentTypeAndKnobValue(string contentType, bool autoComputePayloadMetadataInJson, ODataItem[] itemsToWrite, EdmModel edmModel, IEdmEntitySetBase edmEntitySet, EdmEntityType edmEntityType, string selectClause = null, string expandClause = null, string resourcePath = null)
        {
            MemoryStream outputStream = new MemoryStream();
            IODataResponseMessage message = new InMemoryMessage() { Stream = outputStream };
            message.SetHeader("Content-Type", contentType);
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings()
            {
                AutoComputePayloadMetadataInJson = autoComputePayloadMetadataInJson,
            };

            var result = new ODataQueryOptionParser(edmModel, edmEntityType, edmEntitySet, new Dictionary<string, string> { { "$select", selectClause }, { "$expand", expandClause } }).ParseSelectAndExpand();

            ODataUri odataUri = new ODataUri()
            {
                ServiceRoot = new Uri("http://example.com"),
                SelectAndExpand = result
            };

            if (resourcePath != null)
            {
                Uri requestUri = new Uri("http://example.com/" + resourcePath);
                odataUri.RequestUri = requestUri;
                odataUri.Path = new ODataUriParser(edmModel, new Uri("http://example.com"), requestUri).ParsePath();
            }

            settings.ODataUri = odataUri;

            string output;
            using (var messageWriter = new ODataMessageWriter(message, settings, edmModel))
            {
                int currentIdx = 0;

                if (itemsToWrite[currentIdx] is ODataFeed)
                {
                    ODataWriter writer = messageWriter.CreateODataFeedWriter(edmEntitySet, edmEntityType);
                    this.WriteFeed(writer, itemsToWrite, ref currentIdx);
                }
                else if (itemsToWrite[currentIdx] is ODataEntry)
                {
                    ODataWriter writer = messageWriter.CreateODataEntryWriter(edmEntitySet, edmEntityType);
                    this.WriteEntry(writer, itemsToWrite, ref currentIdx);
                }
                else
                {
                    Assert.Fail("Top level item to write must be entry or feed.");
                }

                currentIdx.Should().Be(itemsToWrite.Length, "Invalid list of items to write.");

                outputStream.Seek(0, SeekOrigin.Begin);
                output = new StreamReader(outputStream).ReadToEnd();
            }

            return output;
        }
        /// <summary>
        /// Create contextUrlInfo for delta
        /// </summary>
        /// <param name="typeContext">The ODataFeedAndEntryTypeContext to be used.</param>
        /// <param name="kind">The delta kind.</param>
        /// <param name="odataUri">The odata uri info for current query.</param>
        /// <returns>The generated ODataContextUrlInfo.</returns>
        internal static ODataContextUrlInfo Create(ODataFeedAndEntryTypeContext typeContext, ODataDeltaKind kind, ODataUri odataUri = null)
        {
            Debug.Assert(typeContext != null, "typeContext != null");

            ODataContextUrlInfo contextUriInfo = new ODataContextUrlInfo()
            {
                isContained                 = typeContext.NavigationSourceKind == EdmNavigationSourceKind.ContainedEntitySet,
                navigationSource            = typeContext.NavigationSourceName,
                TypeCast                    = typeContext.NavigationSourceEntityTypeName == typeContext.ExpectedEntityTypeName ? null : typeContext.ExpectedEntityTypeName,
                TypeName                    = typeContext.NavigationSourceEntityTypeName,
                IncludeFragmentItemSelector = kind == ODataDeltaKind.Entry && typeContext.NavigationSourceKind != EdmNavigationSourceKind.Singleton,
                DeltaKind                   = kind,
            };

            // Only use odata uri in with model case.
            if (typeContext is ODataFeedAndEntryTypeContext.ODataFeedAndEntryTypeContextWithModel)
            {
                contextUriInfo.odataUri = odataUri;
            }

            return(contextUriInfo);
        }
        private void PushScope(WriterState state, ODataItem item, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
        {
            Debug.Assert(
                state == WriterState.Error ||
                state == WriterState.Entry && (item == null || item is ODataEntry) ||
                state == WriterState.Feed && item is ODataFeed ||
                state == WriterState.NavigationLink && item is ODataNavigationLink ||
                state == WriterState.NavigationLinkWithContent && item is ODataNavigationLink ||
                state == WriterState.Start && item == null ||
                state == WriterState.Completed && item == null,
                "Writer state and associated item do not match.");

            Scope scope;
            switch (state)
            {
                case WriterState.Entry:
                    scope = this.CreateEntryScope((ODataEntry)item, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
                    break;
                case WriterState.Feed:
                    scope = this.CreateFeedScope((ODataFeed)item, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
                    break;
                case WriterState.NavigationLink:            // fall through
                case WriterState.NavigationLinkWithContent:
                    scope = this.CreateNavigationLinkScope(state, (ODataNavigationLink)item, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
                    break;
                case WriterState.Start:                     // fall through
                case WriterState.Completed:                 // fall through
                case WriterState.Error:
                    scope = new Scope(state, item, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
                    break;
                default:
                    string errorMessage = Strings.General_InternalError(InternalErrorCodes.ODataWriterCore_Scope_Create_UnreachableCodePath);
                    Debug.Assert(false, errorMessage);
                    throw new ODataException(errorMessage);
            }

            this.scopes.Push(scope);
        }
 /// <summary>
 /// Create ODataContextUrlInfo from basic information
 /// </summary>
 /// <param name="navigationSource">Navigation source for current element.</param>\
 /// <param name="expectedEntityTypeName">The expectedEntity for current element.</param>
 /// <param name="isSingle">Whether target is single item.</param>
 /// <param name="odataUri">The odata uri info for current query.</param>
 /// <returns>The generated ODataContextUrlInfo.</returns>
 internal static ODataContextUrlInfo Create(IEdmNavigationSource navigationSource, string expectedEntityTypeName, bool isSingle, ODataUri odataUri)
 {
     EdmNavigationSourceKind kind = navigationSource.NavigationSourceKind();
     string navigationSourceEntityType = navigationSource.EntityType().FullName();
     return new ODataContextUrlInfo()
     {
         isContained = kind == EdmNavigationSourceKind.ContainedEntitySet,
         IsUnknownEntitySet = kind == EdmNavigationSourceKind.UnknownEntitySet,
         navigationSource = navigationSource.Name,
         TypeCast = navigationSourceEntityType == expectedEntityTypeName ? null : expectedEntityTypeName,
         TypeName = navigationSourceEntityType,
         IncludeFragmentItemSelector = isSingle && kind != EdmNavigationSourceKind.Singleton,
         odataUri = odataUri
     };
 }
 /// <summary>
 /// Constructor creating a new writer scope.
 /// </summary>
 /// <param name="state">The writer state of this scope.</param>
 /// <param name="item">The item attached to this scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of this scope should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 internal Scope(WriterState state, ODataItem item, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
 {
     this.state = state;
     this.item = item;
     this.entityType = entityType;
     this.navigationSource = navigationSource;
     this.skipWriting = skipWriting;
     this.selectedProperties = selectedProperties;
     this.odataUri = odataUri;
 }
        /// <summary>
        /// Create contextUrlInfo for delta
        /// </summary>
        /// <param name="typeContext">The ODataFeedAndEntryTypeContext to be used.</param>
        /// <param name="kind">The delta kind.</param>
        /// <param name="odataUri">The odata uri info for current query.</param>
        /// <returns>The generated ODataContextUrlInfo.</returns>
        internal static ODataContextUrlInfo Create(ODataFeedAndEntryTypeContext typeContext, ODataDeltaKind kind, ODataUri odataUri = null)
        {
            Debug.Assert(typeContext != null, "typeContext != null");

            ODataContextUrlInfo contextUriInfo = new ODataContextUrlInfo()
            {
                isContained = typeContext.NavigationSourceKind == EdmNavigationSourceKind.ContainedEntitySet,
                IsUnknownEntitySet = typeContext.NavigationSourceKind == EdmNavigationSourceKind.UnknownEntitySet,
                navigationSource = typeContext.NavigationSourceName,
                TypeCast = typeContext.NavigationSourceEntityTypeName == typeContext.ExpectedEntityTypeName ? null : typeContext.ExpectedEntityTypeName,
                TypeName = typeContext.NavigationSourceEntityTypeName,
                IncludeFragmentItemSelector = kind == ODataDeltaKind.Entry && typeContext.NavigationSourceKind != EdmNavigationSourceKind.Singleton,
                DeltaKind = kind,
            };

            // Only use odata uri in with model case.
            if (typeContext is ODataFeedAndEntryTypeContext.ODataFeedAndEntryTypeContextWithModel)
            {
                contextUriInfo.odataUri = odataUri;
            }

            return contextUriInfo;
        }
 /// <summary>
 /// Constructor of the ODataUriBuilder
 /// </summary>
 /// <param name="urlConventions">ODataUriBuilder constructor</param>
 /// <param name="odataUri">semantic tree of the uri</param>
 public ODataUriBuilder(ODataUrlConventions urlConventions, ODataUri odataUri)
 {
     this.urlConventions = urlConventions;
     this.odataUri = odataUri;
 }