public void WriterSettingsIntegrationTest()
        {
            var settings = new ODataMessageWriterSettings();
            settings.SetServiceDocumentUri(ServiceDocumentUri);
            settings.MetadataDocumentUri.Should().Equals(ServiceDocumentUri + "/$metadata");

            settings.SetServiceDocumentUri(null);
            settings.MetadataDocumentUri.Should().BeNull();
        }
        public void WriteObject_Calls_CreateODataComplexValue()
        {
            // Arrange
            MemoryStream stream = new MemoryStream();
            IODataResponseMessage message = new ODataMessageWrapper(stream);
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings();
            settings.SetServiceDocumentUri(new Uri("http://any/"));
            settings.SetContentType(ODataFormat.Atom);
            ODataMessageWriter messageWriter = new ODataMessageWriter(message, settings);
            Mock<ODataComplexTypeSerializer> serializer = new Mock<ODataComplexTypeSerializer>(new DefaultODataSerializerProvider());
            ODataSerializerContext writeContext = new ODataSerializerContext { RootElementName = "ComplexPropertyName", Model = _model };
            object graph = new object();
            ODataComplexValue complexValue = new ODataComplexValue
            {
                TypeName = "NS.Name",
                Properties = new[] { new ODataProperty { Name = "Property1", Value = 42 } }
            };

            serializer.CallBase = true;
            serializer.Setup(s => s.CreateODataComplexValue(graph, It.Is<IEdmComplexTypeReference>(e => e.Definition == _addressType), writeContext))
                .Returns(complexValue).Verifiable();

            // Act
            serializer.Object.WriteObject(graph, typeof(Address), messageWriter, writeContext);

            // Assert
            serializer.Verify();
            stream.Seek(0, SeekOrigin.Begin);
            XElement element = XElement.Load(stream);
            Assert.Equal("value", element.Name.LocalName);
            Assert.Equal("#NS.Name", element.Attributes().Single(a => a.Name.LocalName == "type").Value);
            Assert.Equal(1, element.Descendants().Count());
            Assert.Equal("42", element.Descendants().Single().Value);
            Assert.Equal("Property1", element.Descendants().Single().Name.LocalName);
        }
 public void Init()
 {
     model = new EdmModel();
     stream = new MemoryStream();
     settings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true, Version = ODataVersion.V4 };
     settings.SetServiceDocumentUri(new Uri("http://example.com"));
 }
        public void WriteObject_WritesValueReturnedFrom_CreateODataCollectionValue()
        {
            // Arrange
            MemoryStream stream = new MemoryStream();
            IODataResponseMessage message = new ODataMessageWrapper(stream);
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings();
            settings.SetServiceDocumentUri(new Uri("http://any/"));
            settings.SetContentType(ODataFormat.Atom);
            ODataMessageWriter messageWriter = new ODataMessageWriter(message, settings);
            Mock<ODataCollectionSerializer> serializer = new Mock<ODataCollectionSerializer>(new DefaultODataSerializerProvider());
            ODataSerializerContext writeContext = new ODataSerializerContext { RootElementName = "CollectionName", Model = _model };
            IEnumerable enumerable = new object[0];
            ODataCollectionValue collectionValue = new ODataCollectionValue { TypeName = "NS.Name", Items = new[] { 0, 1, 2 } };

            serializer.CallBase = true;
            serializer
                .Setup(s => s.CreateODataCollectionValue(enumerable, It.Is<IEdmTypeReference>(e => e.Definition == _edmIntType.Definition), writeContext))
                .Returns(collectionValue).Verifiable();

            // Act
            serializer.Object.WriteObject(enumerable, typeof(int[]), messageWriter, writeContext);

            // Assert
            serializer.Verify();
            stream.Seek(0, SeekOrigin.Begin);
            XElement element = XElement.Load(stream);
            Assert.Equal("value", element.Name.LocalName);
            Assert.Equal(3, element.Descendants().Count());
            Assert.Equal(new[] { "0", "1", "2" }, element.Descendants().Select(e => e.Value));
        }
        public void WriteCompletedAsyncResponse()
        {
            var asyncWriter = this.TestInit();

            var innerMessage = asyncWriter.CreateResponseMessage();
            innerMessage.StatusCode = 200;
            innerMessage.SetHeader("Content-Type", "application/json");

            var settings = new ODataMessageWriterSettings();
            settings.SetServiceDocumentUri(new Uri(ServiceDocumentUri));
            settings.DisableMessageStreamDisposal = true;

            using (var innerMessageWriter = new ODataMessageWriter(innerMessage, settings, this.userModel))
            {
                var entryWriter = innerMessageWriter.CreateODataEntryWriter(singleton, testType);
                var entry = new ODataEntry() {TypeName = "NS.Test", Properties = new[] {new ODataProperty() {Name = "Id", Value = 1}}};
                entryWriter.WriteStart(entry);
                entryWriter.WriteEnd();
            }

            asyncWriter.Flush();

            var payload = this.TestFinish();
            Assert.AreEqual("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nOData-Version: 4.0\r\n\r\n{\"@odata.context\":\"http://host/service/$metadata#MySingleton\",\"Id\":1}", payload);
        }
        public void ODataWorkspaceSerializer_Works()
        {
            // Arrange
            ODataServiceDocumentSerializer serializer = new ODataServiceDocumentSerializer();
            MemoryStream stream = new MemoryStream();
            IODataResponseMessage message = new ODataMessageWrapper(stream);
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings();
            settings.SetServiceDocumentUri(new Uri("http://any/"));
            settings.SetContentType(ODataFormat.Atom);
            ODataMessageWriter writer = new ODataMessageWriter(message, settings);

            // Act
            serializer.WriteObject(new ODataServiceDocument(), _workspaceType, writer, new ODataSerializerContext());

            // Assert
            stream.Seek(0, SeekOrigin.Begin);
            XElement element = XElement.Load(stream);
            Assert.Equal("service", element.Name.LocalName);
        }
        public void JsonPaddingEnabledWithUserSpecifiedContentType()
        {
            var settings = new ODataMessageWriterSettings {JsonPCallback = "functionName", DisableMessageStreamDisposal = true};
            settings.SetServiceDocumentUri(new Uri("http://stuff"));
            IODataResponseMessage message = new InMemoryMessage {StatusCode = 200, Stream = new MemoryStream()};
            message.SetHeader("Content-Type", "application/json");
            var property = new ODataProperty {Name = "PropertyName", Value = "value"};
            
            using (var writer = new ODataMessageWriter(message, settings))
            {
                writer.WriteProperty(property);
            }

            var responseStream = message.GetStream();
            responseStream.Position = 0;
            var responseString = new StreamReader(responseStream).ReadToEnd();
            responseString.Should().Be("functionName({\"@odata.context\":\"http://stuff/$metadata#Edm.String\",\"value\":\"value\"})");
            message.GetHeader("Content-Type").Should().StartWith("text/javascript");
        }
        protected void WriteAnnotationsAndValidatePayload(Action<ODataWriter> action, ODataFormat format, string expectedPayload, bool request, bool createFeedWriter)
        {
            var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true, EnableAtom = true };
            writerSettings.SetContentType(format);
            writerSettings.SetServiceDocumentUri(new Uri("http://www.example.com/"));

            MemoryStream stream = new MemoryStream();
            if (request)
            {
                IODataRequestMessage requestMessageToWrite = new InMemoryMessage { Method = "GET", Stream = stream };
                using (var messageWriter = new ODataMessageWriter(requestMessageToWrite, writerSettings, Model))
                {
                    ODataWriter odataWriter = createFeedWriter ? messageWriter.CreateODataFeedWriter(EntitySet, EntityType) : messageWriter.CreateODataEntryWriter(EntitySet, EntityType);
                    action(odataWriter);
                }
            }
            else
            {
                IODataResponseMessage responseMessageToWrite = new InMemoryMessage { StatusCode = 200, Stream = stream };
                using (var messageWriter = new ODataMessageWriter(responseMessageToWrite, writerSettings, Model))
                {
                    ODataWriter odataWriter = createFeedWriter ? messageWriter.CreateODataFeedWriter(EntitySet, EntityType) : messageWriter.CreateODataEntryWriter(EntitySet, EntityType);
                    action(odataWriter);
                }
            }

            stream.Position = 0;
            string payload = (new StreamReader(stream)).ReadToEnd();
            if (format == ODataFormat.Atom)
            {
                // The <updated> element is computed dynamically, so we remove it from the both the baseline and the actual payload.
                payload = Regex.Replace(payload, "<updated>[^<]*</updated>", "");
                expectedPayload = Regex.Replace(expectedPayload, "<updated>[^<]*</updated>", "");
            }

            Assert.AreEqual(expectedPayload, payload);
        }
        public void Read_RoundTrips()
        {
            // Arrange
            var deserializer = new ODataEntityReferenceLinkDeserializer();
            MockODataRequestMessage requestMessage = new MockODataRequestMessage();
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings();
            settings.SetServiceDocumentUri(new Uri("http://any/"));
            settings.SetContentType(ODataFormat.Atom);
            ODataMessageWriter messageWriter = new ODataMessageWriter(requestMessage, settings);
            messageWriter.WriteEntityReferenceLink(new ODataEntityReferenceLink { Url = new Uri("http://localhost/samplelink") });
            ODataMessageReader messageReader = new ODataMessageReader(new MockODataRequestMessage(requestMessage));
            ODataDeserializerContext context = new ODataDeserializerContext
            {
                Request = new HttpRequestMessage(),
                Path = new ODataPath(new NavigationPathSegment(GetNavigationProperty(CreateModel())))
            };

            // Act
            Uri uri = deserializer.Read(messageReader, typeof(Uri), context) as Uri;

            // Assert
            Assert.NotNull(uri);
            Assert.Equal("http://localhost/samplelink", uri.AbsoluteUri);
        }
        private string WriterEntry(IEdmModel userModel, ODataEntry entry, EdmEntitySet entitySet, IEdmEntityType entityType, bool fullMetadata = false)
        {
            var message = new InMemoryMessage() { Stream = new MemoryStream() };

            var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true, AutoComputePayloadMetadataInJson = true };
            writerSettings.SetContentType(ODataFormat.Json);
            writerSettings.SetServiceDocumentUri(new Uri("http://www.example.com"));
            writerSettings.SetContentType(fullMetadata ?
                "application/json;odata.metadata=full;odata.streaming=false" :
                "application/json;odata.metadata=minimal;odata.streaming=false", "utf-8");

            using (var msgReader = new ODataMessageWriter((IODataResponseMessage)message, writerSettings, userModel))
            {
                var writer = msgReader.CreateODataEntryWriter(entitySet, entityType);
                writer.WriteStart(entry);
                writer.WriteEnd();
            }

            message.Stream.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(message.Stream))
            {
                return reader.ReadToEnd();
            }
        }
        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;
        }
 private string WriteODataEntry(ODataEntry entryToWrite)
 {
     var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true };
     writerSettings.SetContentType(ODataFormat.Json);
     writerSettings.SetServiceDocumentUri(new Uri("http://www.example.com/"));
     MemoryStream stream = new MemoryStream();
     IODataRequestMessage requestMessageToWrite = new InMemoryMessage { Method = "GET", Stream = stream };
     using (var messageWriter = new ODataMessageWriter(requestMessageToWrite, writerSettings, this.model))
     {
         ODataWriter odataWriter = messageWriter.CreateODataEntryWriter(this.entitySet, this.entityType);
         odataWriter.WriteStart(entryToWrite);
         odataWriter.WriteEnd();
     }
     stream.Position = 0;
     string payload = (new StreamReader(stream)).ReadToEnd();
     return payload;
 }
        private ODataJsonLightOutputContext CreateJsonLightOutputContext(MemoryStream stream)
        {
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings { Version = ODataVersion.V4 };
            settings.SetServiceDocumentUri(new Uri("http://example.com/"));

            return new ODataJsonLightOutputContext(
                ODataFormat.Json,
                new NonDisposingStream(stream),
                new ODataMediaType("application", "json"),
                Encoding.UTF8,
                settings,
                /*writingResponse*/ true,
                /*synchronous*/ true,
                this.model,
                /*urlResolver*/ null);
        }
        private void WriteAndValidateContextUri(ODataFormat odataFormat, EdmModel edmModel, Action<ODataMessageWriter> test, string expectedUri, out string payload, out string contentType)
        {
            var message = new InMemoryMessage() { Stream = new MemoryStream() };

            var writerSettings = new ODataMessageWriterSettings
            {
                DisableMessageStreamDisposal = true,
                PayloadBaseUri = new Uri(TestBaseUri),
                AutoComputePayloadMetadataInJson = true,
                EnableAtom = true
            };
            writerSettings.SetServiceDocumentUri(new Uri(TestBaseUri));
            writerSettings.SetContentType(odataFormat);

            using (var msgWriter = new ODataMessageWriter((IODataResponseMessage)message, writerSettings, edmModel))
            {
                test(msgWriter);
            }

            message.Stream.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(message.Stream))
            {
                contentType = message.GetHeader("Content-Type");
                payload = reader.ReadToEnd();
                payload.Should().Contain(expectedUri);
            }
        }
        private string WriteAtomEntry(ODataEntry entry)
        {
            MemoryStream stream = new MemoryStream();
            InMemoryMessage message = new InMemoryMessage { Stream = stream };

            var settings = new ODataMessageWriterSettings { Version = ODataVersion.V4, AutoComputePayloadMetadataInJson = true, EnableAtom = true};
            settings.SetServiceDocumentUri(new Uri("http://temp.org/"));

            settings.SetContentType(ODataFormat.Atom);
            

            ODataMessageWriter messageWriter = new ODataMessageWriter((IODataResponseMessage)message, settings, Model);

            var entryWriter = messageWriter.CreateODataEntryWriter(EntitySet, EntityType);

            entryWriter.WriteStart(entry);
            entryWriter.WriteEnd();
            entryWriter.Flush();

            var actual = Encoding.UTF8.GetString(stream.ToArray());
            return actual;
        }
        public void SetContentTypeInMessageHeaderTest()
        {
            IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            var testDescriptors = writerActionsForPayloadKinds.SelectMany(
                writerAction => CreateContentTypeHeaderTestCases(writerAction.PayloadKind).Select(
                    testCase =>
                        new
                        {
                            WriterInvocation = writerAction,
                            TestCase = testCase
                        }));
            // ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.Where(td => td.TestCase.ExpectedFormat == ODataFormat.Atom),
                this.WriterTestConfigurationProvider.AllFormatsConfigurations.Where(tc => tc.Format == ODataFormat.Atom),
                (testDescriptor, testConfiguration) =>
                {
                    ODataPayloadKind payloadKind = testDescriptor.WriterInvocation.PayloadKind;
                    if (!payloadKind.IsSupported(testConfiguration))
                    {
                        return;
                    }

                    // Clone the test configuration and make sure no content type is set on the message writer settings
                    ODataMessageWriterSettings settings = testConfiguration.MessageWriterSettings;
                    ODataMessageWriterSettings clonedSettings = new ODataMessageWriterSettings()
                    {
                        // NOTE intentionally not copying acceptable media types, acceptable char sets, format and useFormat
                        PayloadBaseUri = settings.PayloadBaseUri,
                        CheckCharacters = settings.CheckCharacters,
                        DisableMessageStreamDisposal = settings.DisableMessageStreamDisposal,
                        Indent = settings.Indent,
                        MessageQuotas = new ODataMessageQuotas(settings.MessageQuotas),
                        Version = settings.Version,
                        EnableAtom = true
                    };
                    clonedSettings.SetServiceDocumentUri(ServiceDocumentUri);
                    WriterTestConfiguration clonedTestConfiguration = new WriterTestConfiguration(
                        testConfiguration.Format, 
                        clonedSettings, 
                        testConfiguration.IsRequest, 
                        testConfiguration.Synchronous);

                    using (var memoryStream = new TestStream())
                    {
                        TestMessage testMessage;
                        using (ODataMessageWriterTestWrapper messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, clonedTestConfiguration, this.Assert, out testMessage, null, model))
                        {
                            // Set the content type header in the test message
                            testMessage.SetHeader(ODataConstants.ContentTypeHeader, testDescriptor.TestCase.ContentTypeHeaderValue);

                            Func<WriterTestConfiguration, ExpectedException> expectedExceptionFunc = testDescriptor.TestCase.ExpectedException;
                            ExpectedException expectedException = expectedExceptionFunc == null ? null : expectedExceptionFunc(testConfiguration);

                            TestExceptionUtils.ExpectedException(
                                this.Assert,
                                () => testDescriptor.WriterInvocation.WriterAction(messageWriter),
                                expectedException,
                                this.ExceptionVerifier);

                            if (expectedException != null)
                            {
                                // nothing more to do if we expected an exception
                                return;
                            }

                            // Check that the format and encoding was properly set
                            ODataFormat actualFormat = messageWriter.PrivateFormat;
                            Encoding actualEncoding = messageWriter.PrivateEncoding;

                            string actualEncodingName = actualEncoding != null ? actualEncoding.WebName : null;
                            string expectedEncodingName = testDescriptor.TestCase.ExpectedEncoding != null ? testDescriptor.TestCase.ExpectedEncoding.WebName : null;

                            this.Assert.AreEqual(expectedEncodingName, actualEncodingName, "Encodings do not match!");
                            this.Assert.AreEqual(testDescriptor.TestCase.ExpectedFormat, actualFormat, "Formats do not match!");

                            // For batch payloads we need to validate the boundary string as well.
                            if (payloadKind == ODataPayloadKind.Batch)
                            {
                                string batchBoundary = messageWriter.PrivateBatchBoundary;
                                this.Assert.IsNotNull(batchBoundary, "Boundary string must not be null.");
                                this.Assert.IsTrue(testDescriptor.TestCase.ContentTypeHeaderValue.Contains("boundary=" + batchBoundary), "Boundary strings don't match.");
                            }
                        }
                    }
                });
        }
        private static ODataJsonLightOutputContext CreateJsonLightOutputContext(MemoryStream stream, bool writingResponse = true, IEdmModel userModel = null, Uri serviceDocumentUri = null)
        {
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings { Version = ODataVersion.V4, AutoComputePayloadMetadataInJson = true, ShouldIncludeAnnotation = ODataUtils.CreateAnnotationFilter("*") };
            if (serviceDocumentUri != null)
            {
                settings.SetServiceDocumentUri(serviceDocumentUri);
            }

            ODataMediaType mediaType = new ODataMediaType("application", "json", new KeyValuePair<string, string>("odata.metadata", "full"));
            return new ODataJsonLightOutputContext(
                ODataFormat.Json,
                new NonDisposingStream(stream),
                mediaType,
                Encoding.UTF8,
                settings,
                writingResponse,
                /*synchronous*/ true,
                userModel ?? EdmCoreModel.Instance,
                /*urlResolver*/ null);
        }
        /// <summary>
        /// Writes an ODataError with the given custom instance annotation to the test stream.
        /// </summary>
        private void WriteError(params KeyValuePair<string, ODataValue>[] annotations)
        {
            var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true };
            writerSettings.SetContentType(ODataFormat.Json);
            writerSettings.SetServiceDocumentUri(new Uri("http://example.com/"));

            IODataResponseMessage messageToWrite = new InMemoryMessage { StatusCode = 400, Stream = this.stream };

            var error = new ODataError();
            var instanceAnnotations = new Collection<ODataInstanceAnnotation>();
            error.SetInstanceAnnotations(instanceAnnotations);

            foreach (var pair in annotations)
            {
                ODataInstanceAnnotation annotation = new ODataInstanceAnnotation(pair.Key, pair.Value);
                instanceAnnotations.Add(annotation);
            }

            using (var writer = new ODataMessageWriter(messageToWrite, writerSettings, this.model))
            {
                writer.WriteError(error, false);
            }
        }
        private string WriterEntry(EdmModel userModel, ODataEntry entry, IEdmEntityType entityType)
        {
            var message = new InMemoryMessage() { Stream = new MemoryStream() };
            message.SetHeader("Content-Type", "application/atom+xml;type=entry");
            var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true, EnableAtom = true };
            writerSettings.SetServiceDocumentUri(ServiceDocumentUri);
            using (var msgReader = new ODataMessageWriter((IODataResponseMessage)message, writerSettings, userModel))
            {
                var writer = msgReader.CreateODataEntryWriter();
                writer.WriteStart(entry);
                writer.WriteEnd();
            }

            message.Stream.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(message.Stream))
            {
                return reader.ReadToEnd();
            }
        }
        private static ODataJsonLightOutputContext CreateJsonLightOutputContext(MemoryStream stream, bool writingResponse = true, bool synchronous = true)
        {
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings { Version = ODataVersion.V4 };
            settings.SetServiceDocumentUri(new Uri("http://odata.org/test/"));

            return new ODataJsonLightOutputContext(
                ODataFormat.Json,
                new NonDisposingStream(stream),
                new ODataMediaType("application", "json"),
                Encoding.UTF8,
                settings,
                writingResponse,
                synchronous,
                EdmCoreModel.Instance,
                /*urlResolver*/ null);
        }
        private object WriteThenReadValue(object clrValue, IEdmTypeReference typeReference, ODataVersion version, bool isIeee754Compatible)
        {
            MemoryStream stream = new MemoryStream();

            ODataMessageWriterSettings settings = new ODataMessageWriterSettings { Version = version };
            settings.SetServiceDocumentUri(new Uri("http://odata.org/test/"));

            ODataMediaType mediaType = isIeee754Compatible
                ? new ODataMediaType("application", "json", new KeyValuePair<string, string>("IEEE754Compatible", "true"))
                : new ODataMediaType("application", "json");

            using (ODataJsonLightOutputContext outputContext = new ODataJsonLightOutputContext(
                ODataFormat.Json,
                new NonDisposingStream(stream),
                mediaType,
                Encoding.UTF8,
                settings,
                /*writingResponse*/ true,
                /*synchronous*/ true,
                this.model,
                /*urlResolver*/ null))
            {
                ODataJsonLightValueSerializer serializer = new ODataJsonLightValueSerializer(outputContext);
                serializer.WritePrimitiveValue(clrValue, typeReference);
            }

            stream.Position = 0;

            object actualValue;
            using (ODataJsonLightInputContext inputContext = new ODataJsonLightInputContext(
                ODataFormat.Json,
                stream,
                mediaType,
                Encoding.UTF8,
                new ODataMessageReaderSettings(),
                /*readingResponse*/ true,
                /*synchronous*/ true,
                this.model,
                /*urlResolver*/ null))
            {
                ODataJsonLightPropertyAndValueDeserializer deserializer = new ODataJsonLightPropertyAndValueDeserializer(inputContext);
                deserializer.JsonReader.Read();
                actualValue = deserializer.ReadNonEntityValue(
                    /*payloadTypeName*/ null,
                    typeReference,
                    /*duplicatePropertyNamesChecker*/ null,
                    /*collectionValidator*/ null,
                    /*validateNullValue*/ true,
                    /*isTopLevel*/ true,
                    /*insideComplexValue*/ false,
                    /*propertyName*/ null);

            }

            return actualValue;
        }
        public void UnsignedIntAndTypeDefinitionRoundtripJsonLightIntegrationTest()
        {
            var model = new EdmModel();

            var uint16 = new EdmTypeDefinition("MyNS", "UInt16", EdmPrimitiveTypeKind.Double);
            var uint16Ref = new EdmTypeDefinitionReference(uint16, false);
            model.AddElement(uint16);
            model.SetPrimitiveValueConverter(uint16Ref, UInt16ValueConverter.Instance);

            var uint64 = new EdmTypeDefinition("MyNS", "UInt64", EdmPrimitiveTypeKind.String);
            var uint64Ref = new EdmTypeDefinitionReference(uint64, false);
            model.AddElement(uint64);
            model.SetPrimitiveValueConverter(uint64Ref, UInt64ValueConverter.Instance);

            var guidType = new EdmTypeDefinition("MyNS", "Guid", EdmPrimitiveTypeKind.Int64);
            var guidRef = new EdmTypeDefinitionReference(guidType, true);
            model.AddElement(guidType);

            var personType = new EdmEntityType("MyNS", "Person");
            personType.AddKeys(personType.AddStructuralProperty("ID", uint64Ref));
            personType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
            personType.AddStructuralProperty("FavoriteNumber", uint16Ref);
            personType.AddStructuralProperty("Age", model.GetUInt32("MyNS", true));
            personType.AddStructuralProperty("Guid", guidRef);
            personType.AddStructuralProperty("Weight", EdmPrimitiveTypeKind.Double);
            personType.AddStructuralProperty("Money", EdmPrimitiveTypeKind.Decimal);
            model.AddElement(personType);

            var container = new EdmEntityContainer("MyNS", "Container");
            var peopleSet = container.AddEntitySet("People", personType);
            model.AddElement(container);

            var stream = new MemoryStream();
            IODataResponseMessage message = new InMemoryMessage { Stream = stream };
            message.StatusCode = 200;

            var writerSettings = new ODataMessageWriterSettings();
            writerSettings.SetServiceDocumentUri(new Uri("http://host/service"));

            var messageWriter = new ODataMessageWriter(message, writerSettings, model);
            var entryWriter = messageWriter.CreateODataEntryWriter(peopleSet);

            var entry = new ODataEntry
            {
                TypeName = "MyNS.Person",
                Properties = new[]
                {
                    new ODataProperty
                    {
                        Name = "ID",
                        Value = UInt64.MaxValue
                    },
                    new ODataProperty
                    {
                        Name = "Name",
                        Value = "Foo"
                    },
                    new ODataProperty
                    {
                        Name = "FavoriteNumber",
                        Value = (UInt16)250
                    },
                    new ODataProperty
                    {
                        Name = "Age",
                        Value = (UInt32)123
                    },
                    new ODataProperty
                    {
                        Name = "Guid",
                        Value = Int64.MinValue
                    },
                    new ODataProperty
                    {
                        Name = "Weight",
                        Value = 123.45
                    },
                    new ODataProperty
                    {
                        Name = "Money",
                        Value = Decimal.MaxValue
                    }
                }
            };

            entryWriter.WriteStart(entry);
            entryWriter.WriteEnd();
            entryWriter.Flush();

            stream.Position = 0;

            StreamReader reader = new StreamReader(stream);
            string payload = reader.ReadToEnd();
            payload.Should().Be("{\"@odata.context\":\"http://host/service/$metadata#People/$entity\",\"ID\":\"18446744073709551615\",\"Name\":\"Foo\",\"FavoriteNumber\":250.0,\"Age\":123,\"Guid\":-9223372036854775808,\"Weight\":123.45,\"Money\":79228162514264337593543950335}");

            stream = new MemoryStream(Encoding.Default.GetBytes(payload));
            message = new InMemoryMessage { Stream = stream };
            message.StatusCode = 200;

            var readerSettings = new ODataMessageReaderSettings();

            var messageReader = new ODataMessageReader(message, readerSettings, model);
            var entryReader = messageReader.CreateODataEntryReader(peopleSet, personType);
            Assert.IsTrue(entryReader.Read());
            var entryReaded = entryReader.Item as ODataEntry;

            var propertiesReaded = entryReaded.Properties.ToList();
            var propertiesGiven = entry.Properties.ToList();
            Assert.AreEqual(propertiesReaded.Count, propertiesGiven.Count);
            for (int i = 0; i < propertiesReaded.Count; ++i)
            {
                Assert.AreEqual(propertiesReaded[i].Name, propertiesGiven[i].Name);
                Assert.AreEqual(propertiesReaded[i].Value.GetType(), propertiesGiven[i].Value.GetType());
                Assert.AreEqual(propertiesReaded[i].Value, propertiesGiven[i].Value);
            }
        }
        private byte[] ServiceReadAsyncBatchRequestAndWriteAsyncResponse(byte[] requestPayload)
        {
            IODataRequestMessage requestMessage = new InMemoryMessage() { Stream = new MemoryStream(requestPayload) };
            requestMessage.SetHeader("Content-Type", batchContentType);

            using (var messageReader = new ODataMessageReader(requestMessage, new ODataMessageReaderSettings(), this.userModel))
            {
                var responseStream = new MemoryStream();

                IODataResponseMessage responseMessage = new InMemoryMessage { Stream = responseStream };
                responseMessage.SetHeader("Content-Type", batchContentType);
                var messageWriter = new ODataMessageWriter(responseMessage);
                var batchWriter = messageWriter.CreateODataBatchWriter();
                batchWriter.WriteStartBatch();

                var batchReader = messageReader.CreateODataBatchReader();
                while (batchReader.Read())
                {
                    switch (batchReader.State)
                    {
                        case ODataBatchReaderState.Operation:
                            // Encountered an operation (either top-level or in a changeset)
                            var operationMessage = batchReader.CreateOperationRequestMessage();
                            if (operationMessage.Method == "GET" && operationMessage.Url.AbsolutePath.Contains("ALFKI"))
                            {
                                var response = batchWriter.CreateOperationResponseMessage(null);
                                response.StatusCode = 200;
                                response.SetHeader("Content-Type", "application/json;");
                                var settings = new ODataMessageWriterSettings();
                                settings.SetServiceDocumentUri(new Uri(serviceDocumentUri));
                                using (var operationMessageWriter = new ODataMessageWriter(response, settings, this.userModel))
                                {
                                    var entryWriter = operationMessageWriter.CreateODataEntryWriter(this.customers, this.customerType);
                                    var entry = new ODataEntry() { TypeName = "MyNS.Customer", Properties = new[] { new ODataProperty() { Name = "Id", Value = "ALFKI" }, new ODataProperty() { Name = "Name", Value = "John" } } };
                                    entryWriter.WriteStart(entry);
                                    entryWriter.WriteEnd();
                                }
                            }
                            break;
                    }
                }

                var asyncResponse = batchWriter.CreateOperationResponseMessage(null);
                asyncResponse.StatusCode = 202;
                asyncResponse.SetHeader("Location", "http://service/async-monitor");
                asyncResponse.SetHeader("Retry-After", "10");

                batchWriter.WriteEndBatch();

                responseStream.Position = 0;
                return responseStream.ToArray();
            }
        }
 /// <summary>
 /// Creates the default settings for a given <see cref="ODataFormat"/>.
 /// </summary>
 /// <param name="format">The format for the message writer settings to create.</param>
 /// <param name="version">Version of the OData protocol.</param>
 /// <param name="baseUri">Base uri for all relative Uris.</param>
 /// <param name="disableMessageStreamDisposal">When set to true, the writer will not dispose the message stream. When set to false, the message stream will be disposed.</param>
 /// <returns>The default message writer settings for the specified <paramref name="format"/>.</returns>
 private static ODataMessageWriterSettings GetDefaultMessageWriterSettings(
     ODataFormat format,
     Uri baseUri,
     bool disableMessageStreamDisposal,
     ODataVersion version = ODataVersion.V4)
 {
     var settings = new ODataMessageWriterSettings()
     {
         Version = version,
         PayloadBaseUri = baseUri,
         DisableMessageStreamDisposal = disableMessageStreamDisposal,
         EnableAtom = true
     };
     settings.SetServiceDocumentUri(new Uri("http://odata.org/test"));
     settings.SetContentType(format);
     return settings;
 }
 private static ODataAtomOutputContext CreateAtomOutputContext(MemoryStream stream, ODataMediaType mediaType, bool writingResponse = true, IEdmModel userModel = null)
 {
     ODataMessageWriterSettings settings = new ODataMessageWriterSettings { Version = ODataVersion.V4, AutoComputePayloadMetadataInJson = true };
     settings.SetServiceDocumentUri(ServiceDocumentUri);
     return new ODataAtomOutputContext(
         ODataFormat.Atom,
         new NonDisposingStream(stream),
         Encoding.UTF8,
         settings,
         writingResponse,
         /*synchronous*/ true,
         userModel ?? EdmCoreModel.Instance,
         /*urlResolver*/ null);
 }
        private void WriteDeltaFeedAnnotationsAndValidatePayload(Action<ODataDeltaWriter> action, IEdmEntitySet entitySet, string expectedPayload)
        {
            var writerSettings = new ODataMessageWriterSettings {DisableMessageStreamDisposal = true};
            writerSettings.SetServiceDocumentUri(new Uri("http://www.example.com/"));

            MemoryStream stream = new MemoryStream();

            IODataResponseMessage responseMessageToWrite = new InMemoryMessage {StatusCode = 200, Stream = stream};
            responseMessageToWrite.PreferenceAppliedHeader().AnnotationFilter = "*";
            using (var messageWriter = new ODataMessageWriter(responseMessageToWrite, writerSettings, Model))
            {
                ODataDeltaWriter odataDeltaWriter = messageWriter.CreateODataDeltaWriter(entitySet, EntityType);
                action(odataDeltaWriter);
            }

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

            Assert.AreEqual(expectedPayload, payload);
        }
        // TODO: ATOM top level individual property testings
        // FlagsEnumAsComplexPropertyAsTopLevelValue_StrAsValue_StrAsTypeName
        // FlagsEnumAsCollectionItemAsTopLevelValue_StrAsValue_StrAsTypeName

        #endregion

        #region private methods
        public void WriteToMessageWriterAndVerifyPayload(string contentType, Action<ODataMessageWriter> writerAction, string expectedPayload)
        {
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings() { Version = ODataVersion.V4, AutoComputePayloadMetadataInJson = true, DisableMessageStreamDisposal = true, EnableAtom = true};
            settings.SetContentType(contentType, "utf-8");
            settings.SetServiceDocumentUri(ServiceDocumentUri);
            // with model
            {
                MemoryStream stream = new MemoryStream();
                IODataResponseMessage message = new InMemoryMessage() { Stream = stream };
                using (ODataMessageWriter writer = new ODataMessageWriter(message, settings, this.userModel))
                {
                    writerAction(writer);
                }

                stream.Seek(0, SeekOrigin.Begin);
                string payload = (new StreamReader(stream)).ReadToEnd();
                payload.Should().Be(expectedPayload);
            }

            // without model
            {
                MemoryStream stream = new MemoryStream();
                IODataResponseMessage message = new InMemoryMessage() { Stream = stream };
                using (ODataMessageWriter writer = new ODataMessageWriter(message, settings))
                {
                    writerAction(writer);
                }

                stream.Seek(0, SeekOrigin.Begin);
                string payload = (new StreamReader(stream)).ReadToEnd();
                payload.Should().Be(expectedPayload);
            }
        }
        public void WriteTopLevelEntityReferenceLinks()
        {
            ODataEntityReferenceLink link1 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(1)")
            };
            link1.InstanceAnnotations.Add(new ODataInstanceAnnotation("Is.New", new ODataPrimitiveValue(true)));
            ODataEntityReferenceLink link2 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(2)")
            };
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.unknown", new ODataPrimitiveValue(123)));
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.annotation", new ODataPrimitiveValue(456)));

            ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
            {
                Links = new[] { link1, link2 }
            };

            var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true };
            writerSettings.SetContentType(ODataFormat.Json);
            writerSettings.SetServiceDocumentUri(new Uri("http://odata.org/test"));
            MemoryStream stream = new MemoryStream();
            IODataResponseMessage requestMessageToWrite = new InMemoryMessage { StatusCode = 200, Stream = stream };
            requestMessageToWrite.PreferenceAppliedHeader().AnnotationFilter = "*";

            using (var messageWriter = new ODataMessageWriter(requestMessageToWrite, writerSettings, EdmModel))
            {
                messageWriter.WriteEntityReferenceLinks(referencelinks);
            }
            stream.Position = 0;
            string payload = (new StreamReader(stream)).ReadToEnd();

            string expectedPayload = "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection($ref)\",\"value\":[{\"@odata.id\":\"http://host/Customers(1)\",\"@Is.New\":true},{\"@odata.id\":\"http://host/Customers(2)\",\"@TestNamespace.unknown\":123,\"@custom.annotation\":456}]}";

            Assert.AreEqual(expectedPayload, payload);
        }
        public void WriterSettingsIntegrationTestWithSelect()
        {
            var setting = new ODataMessageWriterSettings();
            var edmModel = new EdmModel();
            var defaultContainer = new EdmEntityContainer("TestModel", "DefaultContainer");
            edmModel.AddElement(defaultContainer);
            var cityType = new EdmEntityType("TestModel", "City");
            var cityIdProperty = cityType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(/*isNullable*/false));
            cityType.AddKeys(cityIdProperty);
            cityType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(/*isNullable*/false));
            cityType.AddStructuralProperty("Size", EdmCoreModel.Instance.GetInt32(/*isNullable*/false));
            edmModel.AddElement(cityType);
            var citySet = defaultContainer.AddEntitySet("Cities", cityType);

            var result = new ODataQueryOptionParser(edmModel, cityType, citySet, new Dictionary<string, string> { { "$expand", "" }, { "$select", "Id,*" } }).ParseSelectAndExpand();

            setting.SetServiceDocumentUri(ServiceDocumentUri);
            setting.ODataUri = new ODataUri() { SelectAndExpand = result };
            setting.MetadataDocumentUri.Should().Equals(ServiceDocumentUri + "/$metadata");
            string select, expand;
            setting.SelectExpandClause.GetSelectExpandPaths(out select, out expand);
            select.Should().Be("*");
        }
        private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)
        {
            IEdmModel model = Request.ODataProperties().Model;
            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

            ODataSerializer serializer = GetSerializer(type, value, model, _serializerProvider);

            UrlHelper urlHelper = Request.GetUrlHelper() ?? new UrlHelper(Request);

            ODataPath path = Request.ODataProperties().Path;
            IEdmEntitySet targetEntitySet = path == null ? null : path.EntitySet;

            // serialize a response
            HttpConfiguration configuration = Request.GetConfiguration();
            if (configuration == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustContainConfiguration);
            }

            IODataResponseMessage responseMessage = new ODataMessageWrapper(writeStream, content.Headers);

            ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings(MessageWriterSettings)
            {
                PayloadBaseUri = GetBaseAddress(Request),
                Version = _version,
            };

            string metadataLink = urlHelper.CreateODataLink(new MetadataPathSegment());

            if (metadataLink == null)
            {
                throw new SerializationException(SRResources.UnableToDetermineMetadataUrl);
            }

            string resourcePath = path != null ? path.ToString() : String.Empty;
            Uri baseAddress = GetBaseAddress(Request);
            writerSettings.SetServiceDocumentUri(
                baseAddress,
                Request.ODataProperties().SelectExpandClause,
                resourcePath,
                isIndividualProperty: false);

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,
                 
                // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath.
            };

            MediaTypeHeaderValue contentType = null;
            if (contentHeaders != null && contentHeaders.ContentType != null)
            {
                contentType = contentHeaders.ContentType;
            }

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model))
            {
                ODataSerializerContext writeContext = new ODataSerializerContext()
                {
                    Request = Request,
                    RequestContext = Request.GetRequestContext(),
                    Url = urlHelper,
                    EntitySet = targetEntitySet,
                    Model = model,
                    RootElementName = GetRootElementName(path) ?? "root",
                    SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed,
                    Path = path,
                    MetadataLevel = ODataMediaTypes.GetMetadataLevel(contentType),
                    SelectExpandClause = Request.ODataProperties().SelectExpandClause
                };

                serializer.WriteObject(value, type, messageWriter, writeContext);
            }
        }