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.Equal("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 EntryMetadataUrlRoundTrip()
        {
            var stream = new MemoryStream();
            var writerRequestMemoryMessage = new InMemoryMessage();
            writerRequestMemoryMessage.Stream = stream;
            writerRequestMemoryMessage.SetHeader("Content-Type", "application/json");

            var writerSettings = new ODataMessageWriterSettings() {Version = ODataVersion.V4, DisableMessageStreamDisposal = true};
            writerSettings.ODataUri = new ODataUri() {ServiceRoot = new Uri("http://christro.svc/")};

            var messageWriter = new ODataMessageWriter((IODataResponseMessage)writerRequestMemoryMessage, writerSettings, this.model);
            var organizationSetWriter = messageWriter.CreateODataEntryWriter(this.organizationsSet);
            var odataEntry = new ODataEntry(){ TypeName = ModelNamespace + ".Corporation" };
            odataEntry.Property("Id", 1);
            odataEntry.Property("Name", "");
            odataEntry.Property("TickerSymbol", "MSFT");

            organizationSetWriter.WriteStart(odataEntry);
            organizationSetWriter.WriteEnd();

            var readerPayloadInput = Encoding.UTF8.GetString(stream.GetBuffer());
            Console.WriteLine(readerPayloadInput);

            var readerResponseMemoryMessage = new InMemoryMessage();
            readerResponseMemoryMessage.Stream = new MemoryStream(stream.GetBuffer());
            readerResponseMemoryMessage.SetHeader("Content-Type", "application/json");

            var messageReader = new ODataMessageReader((IODataResponseMessage)readerResponseMemoryMessage, new ODataMessageReaderSettings() {MaxProtocolVersion = ODataVersion.V4, DisableMessageStreamDisposal = true}, this.model);
            var organizationReader = messageReader.CreateODataEntryReader(this.organizationsSet, this.organizationsSet.EntityType());
            organizationReader.Read().Should().Be(true);
            organizationReader.Item.As<ODataEntry>();
        }
 public ODataJsonLightValueSerializerTests()
 {
     model = new EdmModel();
     stream = new MemoryStream();
     settings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true, Version = ODataVersion.V4 };
     settings.SetServiceDocumentUri(new Uri("http://example.com"));
 }
        public WriterTypeNameEndToEndTests()
        {
            var model = new EdmModel();
            var type = new EdmEntityType("TestModel", "TestEntity", /* baseType */ null, /* isAbstract */ false, /* isOpen */ true);
            var keyProperty = type.AddStructuralProperty("DeclaredInt16", EdmPrimitiveTypeKind.Int16);
            type.AddKeys(new[] { keyProperty });

            // Note: DerivedPrimitive is declared as a Geography, but its value below will be set to GeographyPoint, which is derived from Geography.
            type.AddStructuralProperty("DerivedPrimitive", EdmPrimitiveTypeKind.Geography);
            var container = new EdmEntityContainer("TestModel", "Container");
            var set = container.AddEntitySet("Set", type);
            model.AddElement(type);
            model.AddElement(container);

            var writerStream = new MemoryStream();
            this.settings = new ODataMessageWriterSettings();
            this.settings.SetServiceDocumentUri(ServiceDocumentUri);

            // Make the message writer and entry writer lazy so that individual tests can tweak the settings before the message writer is created.
            this.messageWriter = new Lazy<ODataMessageWriter>(() =>
                new ODataMessageWriter(
                    (IODataResponseMessage)new InMemoryMessage { Stream = writerStream },
                    this.settings,
                    model));

            var entryWriter = new Lazy<ODataWriter>(() => this.messageWriter.Value.CreateODataEntryWriter(set, type));

            var valueWithAnnotation = new ODataPrimitiveValue(45);
            valueWithAnnotation.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "TypeNameFromSTNA" });

            var propertiesToWrite = new List<ODataProperty>
            {
                new ODataProperty
                {
                    Name = "DeclaredInt16", Value = (Int16)42
                }, 
                new ODataProperty
                {
                    Name = "UndeclaredDecimal", Value = (Decimal)4.5
                }, 
                new ODataProperty
                {
                    // Note: value is more derived than the declared type.
                    Name = "DerivedPrimitive", Value = Microsoft.Spatial.GeographyPoint.Create(42, 45)
                },
                new ODataProperty()
                {
                    Name = "PropertyWithSTNA", Value = valueWithAnnotation
                }
            };

            this.writerOutput = new Lazy<string>(() =>
            {
                entryWriter.Value.WriteStart(new ODataEntry { Properties = propertiesToWrite });
                entryWriter.Value.WriteEnd();
                entryWriter.Value.Flush();
                writerStream.Seek(0, SeekOrigin.Begin);
                return new StreamReader(writerStream).ReadToEnd();
            });
        }
        public ODataAtomPropertyAndValueSerializerTests()
        {
            EdmModel model = new EdmModel();

            EdmComplexType complex1 = new EdmComplexType("ns", "complex1");
            complex1.AddProperty(new EdmStructuralProperty(complex1, "p1", EdmCoreModel.Instance.GetInt32(isNullable: false)));
            model.AddElement(complex1);            
            
            EdmComplexType complex2 = new EdmComplexType("ns", "complex2");
            complex2.AddProperty(new EdmStructuralProperty(complex2, "p1", EdmCoreModel.Instance.GetInt32(isNullable: false)));
            model.AddElement(complex2);

            EdmComplexTypeReference complex2Reference = new EdmComplexTypeReference(complex2, isNullable: false);
            EdmCollectionType primitiveCollectionType = new EdmCollectionType(EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int32, isNullable: false));
            EdmCollectionType complexCollectionType = new EdmCollectionType(complex2Reference);
            EdmCollectionTypeReference primitiveCollectionTypeReference = new EdmCollectionTypeReference(primitiveCollectionType);
            EdmCollectionTypeReference complexCollectionTypeReference = new EdmCollectionTypeReference(complexCollectionType);

            model.AddElement(new EdmTerm("custom", "int", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int32, isNullable: false)));
            model.AddElement(new EdmTerm("custom", "string", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.String, isNullable: false)));
            model.AddElement(new EdmTerm("custom", "double", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Double, isNullable: false)));
            model.AddElement(new EdmTerm("custom", "bool", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Boolean, isNullable: true)));
            model.AddElement(new EdmTerm("custom", "decimal", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Decimal, isNullable: false)));
            model.AddElement(new EdmTerm("custom", "timespan", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Duration, isNullable: false)));
            model.AddElement(new EdmTerm("custom", "guid", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Guid, isNullable: false)));
            model.AddElement(new EdmTerm("custom", "complex", complex2Reference));
            model.AddElement(new EdmTerm("custom", "primitiveCollection", primitiveCollectionTypeReference));
            model.AddElement(new EdmTerm("custom", "complexCollection", complexCollectionTypeReference));

            this.stream = new MemoryStream();
            this.settings = new ODataMessageWriterSettings { Version = ODataVersion.V4, ShouldIncludeAnnotation = ODataUtils.CreateAnnotationFilter("*") };
            this.settings.SetServiceDocumentUri(ServiceDocumentUri);
            this.serializer = new ODataAtomPropertyAndValueSerializer(this.CreateAtomOutputContext(model, this.stream));
        }
 public void CreateCollectionWriterWithoutTypeShouldPassForJsonLight()
 {
     var settings = new ODataMessageWriterSettings();
     settings.SetContentType(ODataFormat.Json);
     var writer = new ODataMessageWriter(new DummyRequestMessage(), settings, new EdmModel());
     writer.CreateODataCollectionWriter(null).Should().BeOfType<ODataJsonLightCollectionWriter>();
 }
        /// <summary>
        /// If we are writing a response and the given Json Padding function name is not null or empty 
        /// this function will close the JSONP scope.
        /// </summary>
        /// <param name="jsonWriter">JsonWriter to write to.</param>
        /// <param name="settings">Writer settings.</param>
        internal static void EndJsonPaddingIfRequired(IJsonWriter jsonWriter, ODataMessageWriterSettings settings)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter should not be null");

            if (settings.HasJsonPaddingFunction())
            {
                jsonWriter.EndPaddingFunctionScope();
            }
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="format">The format for this output context.</param>
 /// <param name="messageStream">The message stream to write the payload to.</param>
 /// <param name="mediaType">The specific media type being written.</param>
 /// <param name="encoding">The encoding to use for the payload.</param>
 /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param>
 /// <param name="writingResponse">true if writing a response message; otherwise false.</param>
 /// <param name="synchronous">true if the output should be written synchronously; false if it should be written asynchronously.</param>
 /// <param name="model">The model to use.</param>
 /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param>
 internal ODataJsonLightOutputContext(ODataFormat format, Stream messageStream, ODataMediaType mediaType, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver)
     : base(format, messageStream, encoding, messageWriterSettings, writingResponse, synchronous, mediaType.HasIeee754CompatibleSetToTrue(), model, urlResolver)
 {
     Debug.Assert(messageStream != null, "messageStream != null");
     Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null");
     Debug.Assert(mediaType != null, "mediaType != null");
     Uri metadataDocumentUri = messageWriterSettings.MetadataDocumentUri;
     this.metadataLevel = JsonLightMetadataLevel.Create(mediaType, metadataDocumentUri, model, writingResponse);
 }
        public void WriteInstanceAnnotationShouldSkipAnnotationBaseOnAnnotationFilter()
        {
            this.settings = new ODataMessageWriterSettings {Version = ODataVersion.V4, ShouldIncludeAnnotation = name => false};
            this.serializer = new ODataAtomPropertyAndValueSerializer(this.CreateAtomOutputContext(EdmCoreModel.Instance, this.stream));

            var annotation = AtomInstanceAnnotation.CreateFrom(new ODataInstanceAnnotation("Namespace.TermName", new ODataPrimitiveValue("string value")), /*target*/ null);
            this.serializer.WriteInstanceAnnotation(annotation);
            this.ValidatePayload("");
        }
        public void WriterSettingsIntegrationTest()
        {
            var settings = new ODataMessageWriterSettings();
            settings.SetServiceDocumentUri(ServiceDocumentUri);
            settings.MetadataDocumentUri.Should().Equals(ServiceDocumentUri + "/$metadata");

            settings.SetServiceDocumentUri(null);
            settings.MetadataDocumentUri.Should().BeNull();
        }
        /// <summary>
        /// Will write the function's name and start the JSONP scope if we are writing a response and the 
        /// JSONP function name is not null or empty.
        /// </summary>
        /// <param name="jsonWriter">JsonWriter to write to.</param>
        /// <param name="settings">Writer settings.</param>
        internal static void StartJsonPaddingIfRequired(IJsonWriter jsonWriter, ODataMessageWriterSettings settings)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter should not be null");

            if (settings.HasJsonPaddingFunction())
            {
                jsonWriter.WritePaddingFunctionName(settings.JsonPCallback);
                jsonWriter.StartPaddingFunctionScope();
            }
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="format">The format for this output context.</param>
 /// <param name="jsonWriter">The JSON writer to write to.</param>
 /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param>
 /// <param name="writingResponse">true if writing a response message; otherwise false.</param>
 /// <param name="synchronous">true if the output should be written synchronously; false if it should be written asynchronously.</param>
 /// <param name="model">The model to use.</param>
 /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param>
 private ODataJsonOutputContext(
     ODataFormat format,
     JsonWriter jsonWriter,
     ODataMessageWriterSettings messageWriterSettings,
     bool writingResponse,
     bool synchronous,
     IEdmModel model,
     IODataUrlResolver urlResolver)
     : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver)
 {
     this.jsonWriter = jsonWriter;
 }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="format">The format for this output context.</param>
        /// <param name="textWriter">The text writer to write to.</param>
        /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param>
        /// <param name="model">The model to use.</param>
        protected internal ODataJsonOutputContextBase(
            ODataFormat format,
            TextWriter textWriter,
            ODataMessageWriterSettings messageWriterSettings,
            IEdmModel model)
            : base(format, messageWriterSettings, false /*writingResponse*/, true /*synchronous*/, model, null /*urlResolver*/)
        {
            Debug.Assert(textWriter != null, "textWriter != null");

            this.textWriter = textWriter;
            this.jsonWriter = new JsonWriter(this.textWriter, messageWriterSettings.Indent, format, true /*isIeee754Compatible*/);
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="format">The format for this output context.</param>
        /// <param name="textWriter">The text writer to write to.</param>
        /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param>
        /// <param name="model">The model to use.</param>
        internal ODataJsonLightOutputContext(
            ODataFormat format,
            TextWriter textWriter,
            ODataMessageWriterSettings messageWriterSettings,
            IEdmModel model)
            : base(format, textWriter, messageWriterSettings, model)
        {
            Debug.Assert(!this.WritingResponse, "Expecting WritingResponse to always be false for this constructor, so no need to validate the MetadataDocumentUri on the writer settings.");
            Debug.Assert(textWriter != null, "textWriter != null");
            Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null");

            this.metadataLevel = new JsonMinimalMetadataLevel();
        }
        public ODataAtomPropertyTypeSerializerTests()
        {
            model = new EdmModel();
            EdmComplexType complexType = new EdmComplexType("ns", "complex");
            complexType.AddProperty(new EdmStructuralProperty(complexType, "StringProperty", EdmCoreModel.Instance.GetString(isNullable: false)));
            model.AddElement(complexType);

            this.stream = new MemoryStream();
            this.settings = new ODataMessageWriterSettings { Version = ODataVersion.V4, ShouldIncludeAnnotation = ODataUtils.CreateAnnotationFilter("*") };
            this.settings.SetServiceDocumentUri(ServiceDocumentUri);
            this.serializer = new ODataAtomPropertyAndValueSerializer(this.CreateAtomOutputContext(model, this.stream));
            this.instanceAnnotationWriteTracker = new InstanceAnnotationWriteTracker();
        }
        /// <summary>
        /// Creates an Xml writer over the specified stream, with the provided settings and encoding.
        /// </summary>
        /// <param name="stream">The stream to create the XmlWriter over.</param>
        /// <param name="messageWriterSettings">The OData message writer settings used to control the settings of the Xml writer.</param>
        /// <param name="encoding">The encoding used for writing.</param>
        /// <returns>An <see cref="XmlWriter"/> instance configured with the provided settings and encoding.</returns>
        internal static XmlWriter CreateXmlWriter(Stream stream, ODataMessageWriterSettings messageWriterSettings, Encoding encoding)
        {
            Debug.Assert(stream != null, "stream != null");
            Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null");

            XmlWriterSettings xmlWriterSettings = CreateXmlWriterSettings(messageWriterSettings, encoding);

            XmlWriter writer = XmlWriter.Create(stream, xmlWriterSettings);
            if (messageWriterSettings.AlwaysUseDefaultXmlNamespaceForRootElement)
            {
                writer = new DefaultNamespaceCompensatingXmlWriter(writer);
            }

            return writer;
        }
Beispiel #17
0
        public void JsonPaddingEnabledWithRawValueSpecified()
        {
            var settings = new ODataMessageWriterSettings {JsonPCallback = "functionName", DisableMessageStreamDisposal = true};
            settings.SetContentType(ODataFormat.RawValue);
            IODataResponseMessage message = new InMemoryMessage {StatusCode = 200, Stream = new MemoryStream()};

            using (var writer = new ODataMessageWriter(message, settings))
            {
                writer.WriteValue(123);
            }

            var responseStream = message.GetStream();
            responseStream.Position = 0;
            var responseString = new StreamReader(responseStream).ReadToEnd();
            responseString.Should().Be("functionName(123)");
            message.GetHeader("Content-Type").Should().StartWith("text/javascript");
        }
        protected internal ODataJsonOutputContextBase(
            ODataFormat format,
            Stream messageStream,
            Encoding encoding,
            ODataMessageWriterSettings messageWriterSettings,
            bool writingResponse,
            bool synchronous,
            bool isIeee754Compatible,
            IEdmModel model,
            IODataUrlResolver urlResolver)
            : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver)
        {
            Debug.Assert(messageStream != null, "messageStream != null");

            try
            {
                this.messageOutputStream = messageStream;

                Stream outputStream;
                if (synchronous)
                {
                    outputStream = messageStream;
                }
                else
                {
                    this.asynchronousOutputStream = new AsyncBufferedStream(messageStream);
                    outputStream = this.asynchronousOutputStream;
                }

                this.textWriter = new StreamWriter(outputStream, encoding);
                
                // COMPAT 2: JSON indentation - WCFDS indents only partially, it inserts newlines but doesn't actually insert spaces for indentation
                // in here we allow the user to specify if true indentation should be used or if the limited functionality is enough.
                this.jsonWriter = new JsonWriter(this.textWriter, messageWriterSettings.Indent, format, isIeee754Compatible);
            }
            catch (Exception e)
            {
                // Dispose the message stream if we failed to create the input context.
                if (ExceptionUtils.IsCatchableExceptionType(e) && messageStream != null)
                {
                    messageStream.Dispose();
                }

                throw;
            }
        }
Beispiel #19
0
        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");
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="format">The format for this output context.</param>
        /// <param name="messageStream">The message stream to write the payload to.</param>
        /// <param name="encoding">The encoding to use for the payload.</param>
        /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param>
        /// <param name="writingResponse">true if writing a response message; otherwise false.</param>
        /// <param name="synchronous">true if the output should be written synchronously; false if it should be written asynchronously.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param>
        private ODataAtomOutputContext(
            ODataFormat format,
            Stream messageStream,
            Encoding encoding,
            ODataMessageWriterSettings messageWriterSettings,
            bool writingResponse,
            bool synchronous,
            IEdmModel model,
            IODataUrlResolver urlResolver)
            : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver)
        {
            Debug.Assert(messageStream != null, "stream != null");

            try
            {
                this.messageOutputStream = messageStream;

                Stream outputStream;
                if (synchronous)
                {
                    outputStream = messageStream;
                }
                else
                {
                    this.asynchronousOutputStream = new AsyncBufferedStream(messageStream);
                    outputStream = this.asynchronousOutputStream;
                }

                this.xmlRootWriter = ODataAtomWriterUtils.CreateXmlWriter(outputStream, messageWriterSettings, encoding);
                this.xmlWriter = this.xmlRootWriter;
            }
            catch (Exception e)
            {
                // Dispose the message stream if we failed to create the input context.
                if (ExceptionUtils.IsCatchableExceptionType(e) && messageStream != null)
                {
                    messageStream.Dispose();
                }

                throw;
            }
        }
 public void WriteTopLevelUIntPropertyShouldWork()
 {
     var settings = new ODataMessageWriterSettings();
     settings.ODataUri.ServiceRoot = new Uri("http://host/service");
     settings.SetContentType(ODataFormat.Json);
     var model = new EdmModel();
     model.GetUInt32("MyNS", false);
     IODataRequestMessage request = new InMemoryMessage() { Stream = new MemoryStream() };
     var writer = new ODataMessageWriter(request, settings, model);
     Action write = () => writer.WriteProperty(new ODataProperty()
     {
         Name = "Id",
         Value = (UInt32)123
     });
     write.ShouldNotThrow();
     request.GetStream().Position = 0;
     var reader = new StreamReader(request.GetStream());
     string output = reader.ReadToEnd();
     output.Should().Be("{\"@odata.context\":\"http://host/service/$metadata#MyNS.UInt32\",\"value\":123}");
 }
        private void WriteEntry()
        {
            var asyncWriter = this.CreateAsyncWriter();

            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, userModel))
            {
                var entryWriter = innerMessageWriter.CreateODataEntryWriter(singleton, testType);
                entryWriter.WriteStart(entry);
                entryWriter.WriteEnd();
            }

            asyncWriter.Flush();
        }
        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("*");
        }
        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.Equal(expectedPayload, payload);
        }
        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;
        }
Beispiel #26
0
        public WriterTypeNameEndToEndTests()
        {
            var model       = new EdmModel();
            var type        = new EdmEntityType("TestModel", "TestEntity", /* baseType */ null, /* isAbstract */ false, /* isOpen */ true);
            var keyProperty = type.AddStructuralProperty("DeclaredInt16", EdmPrimitiveTypeKind.Int16);

            type.AddKeys(new[] { keyProperty });

            // Note: DerivedPrimitive is declared as a Geography, but its value below will be set to GeographyPoint, which is derived from Geography.
            type.AddStructuralProperty("DerivedPrimitive", EdmPrimitiveTypeKind.Geography);
            var container = new EdmEntityContainer("TestModel", "Container");
            var set       = container.AddEntitySet("Set", type);

            model.AddElement(type);
            model.AddElement(container);

            var writerStream = new MemoryStream();

            this.settings = new ODataMessageWriterSettings();
            this.settings.SetServiceDocumentUri(ServiceDocumentUri);

            // Make the message writer and entry writer lazy so that individual tests can tweak the settings before the message writer is created.
            this.messageWriter = new Lazy <ODataMessageWriter>(() =>
                                                               new ODataMessageWriter(
                                                                   (IODataResponseMessage) new InMemoryMessage {
                Stream = writerStream
            },
                                                                   this.settings,
                                                                   model));

            var entryWriter = new Lazy <ODataWriter>(() => this.messageWriter.Value.CreateODataResourceWriter(set, type));

            var valueWithAnnotation = new ODataPrimitiveValue(45);

            valueWithAnnotation.TypeAnnotation = new ODataTypeAnnotation("TypeNameFromSTNA");

            var propertiesToWrite = new List <ODataProperty>
            {
                new ODataProperty
                {
                    Name = "DeclaredInt16", Value = (Int16)42
                },
                new ODataProperty
                {
                    Name = "UndeclaredDecimal", Value = (Decimal)4.5
                },
                new ODataProperty
                {
                    // Note: value is more derived than the declared type.
                    Name = "DerivedPrimitive", Value = Microsoft.Spatial.GeographyPoint.Create(42, 45)
                },
                new ODataProperty()
                {
                    Name = "PropertyWithSTNA", Value = valueWithAnnotation
                }
            };

            this.writerOutput = new Lazy <string>(() =>
            {
                entryWriter.Value.WriteStart(new ODataResource {
                    Properties = propertiesToWrite
                });
                entryWriter.Value.WriteEnd();
                entryWriter.Value.Flush();
                writerStream.Seek(0, SeekOrigin.Begin);
                return(new StreamReader(writerStream).ReadToEnd());
            });
        }
Beispiel #27
0
 public static Func <ODataResource, XmlWriter, XmlWriter> GetAtomStartResourceXmlCustomizationCallback(this ODataMessageWriterSettings settings)
 {
     return((Func <ODataResource, XmlWriter, XmlWriter>)ReflectionUtils.GetProperty(settings, "AtomStartResourceXmlCustomizationCallback"));
 }
Beispiel #28
0
        public void OpenEntityType()
        {
            //UpdateOpenTypeSingleton
            var entry = new ODataEntry()
            {
                TypeName = ServerSideNameSpacePrefix + "PublicCompany"
            };

            entry.Properties = new[]
            {
                new ODataProperty
                {
                    Name  = "FullName",
                    Value = "MS Ltd."
                },
                new ODataProperty
                {
                    Name  = "PhoneNumber",
                    Value = "123-45678"
                },

                new ODataProperty
                {
                    Name  = "TotalAssets",
                    Value = 500000L,
                }
            };
            var settings = new ODataMessageWriterSettings();

            settings.PayloadBaseUri = ServiceBaseUri;
            settings.AutoComputePayloadMetadataInJson = true;

            var companyType      = Model.FindDeclaredType(ServerSideNameSpacePrefix + "PublicCompany") as IEdmEntityType;
            var companySingleton = Model.EntityContainer.FindSingleton("PublicCompany");

            var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri + "PublicCompany"));

            requestMessage.SetHeader("Content-Type", MimeTypes.ApplicationJson);
            requestMessage.SetHeader("Accept", MimeTypes.ApplicationJson);
            requestMessage.Method = "PATCH";
            using (var messageWriter = new ODataMessageWriter(requestMessage, settings))
            {
                var odataWriter = messageWriter.CreateODataEntryWriter(companySingleton, companyType);
                odataWriter.WriteStart(entry);
                odataWriter.WriteEnd();
            }

            var responseMessage = requestMessage.GetResponse();

            Assert.AreEqual(204, responseMessage.StatusCode);

            //Check account can be correctly desirialized.
            var company = TestClientContext.PublicCompanyPlus.GetValue();

            Assert.IsNotNull(company);
            Assert.AreEqual("MS Ltd.", company.FullNamePlus);
            Assert.AreEqual(500000, company.TotalAssetsPlus);

            TestClientContext.MergeOption = Microsoft.OData.Client.MergeOption.OverwriteChanges;
            company.FullNamePlus          = "MS2 Ltd.";
            company.TotalAssetsPlus       = 1000000;
            TestClientContext.UpdateObject(company);
            TestClientContext.SaveChanges();

            company.FullNamePlus    = null;
            company.TotalAssetsPlus = 0;
            company = TestClientContext.PublicCompanyPlus.GetValue();
            Assert.IsNotNull(company);
            Assert.AreEqual("MS2 Ltd.", company.FullNamePlus);
            Assert.AreEqual(1000000, company.TotalAssetsPlus);
        }
Beispiel #29
0
        private void WriteResponseBody(OutputFormatterContext context)
        {
            HttpRequest  request  = context.ActionContext.HttpContext.Request;
            HttpResponse response = context.ActionContext.HttpContext.Response;

            IEdmModel model = request.ODataProperties().Model;

            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

            object          value      = context.Object;
            Type            type       = value.GetType();
            ODataSerializer serializer = GetSerializer(type, value, model, new DefaultODataSerializerProvider(), request);

            IUrlHelper urlHelper = context.ActionContext.HttpContext.UrlHelper();

            ODataPath            path = request.ODataProperties().Path;
            IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource;

            string preferHeader     = RequestPreferenceHelpers.GetRequestPreferHeader(request);
            string annotationFilter = null;

            if (!String.IsNullOrEmpty(preferHeader))
            {
                ODataMessageWrapper messageWrapper = new ODataMessageWrapper(response.Body, response.Headers);
                messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
            }

            IODataResponseMessage responseMessage = new ODataMessageWrapper(response.Body, response.Headers);

            if (annotationFilter != null)
            {
                responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter;
            }

            Uri baseAddress = GetBaseAddress(request);
            ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings(_messageWriterSettings)
            {
                PayloadBaseUri = baseAddress,
                Version        = ODataProperties.DefaultODataVersion,
            };

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

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

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

                // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath.
                SelectAndExpand = request.ODataProperties().SelectExpandClause,
                Path            = (path == null || IsOperationPath(path)) ? null : path.ODLPath,
            };

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model))
            {
                ODataSerializerContext writeContext = new ODataSerializerContext()
                {
                    Request          = request,
                    RequestContext   = request.HttpContext,
                    Url              = urlHelper,
                    NavigationSource = targetNavigationSource,
                    Model            = model,
                    RootElementName  = GetRootElementName(path) ?? "root",
                    SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed,
                    Path               = path,
                    MetadataLevel      = ODataMediaTypes.GetMetadataLevel(context.SelectedContentType),
                    SelectExpandClause = request.ODataProperties().SelectExpandClause
                };

                serializer.WriteObject(value, type, messageWriter, writeContext);
            }
        }
 public TestODataOutputContext(ODataFormat format, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver)
     :base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver)
 {
 }
Beispiel #31
0
 public static Action <ODataEntry, XmlWriter, XmlWriter> GetAtomEndEntryXmlCustomizationCallback(this ODataMessageWriterSettings settings)
 {
     return((Action <ODataEntry, XmlWriter, XmlWriter>)ReflectionUtils.GetProperty(settings, "AtomEndEntryXmlCustomizationCallback"));
 }
        private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)
        {
            IEdmModel model = Request.GetEdmModel();

            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

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

            UrlHelper urlHelper = Request.GetUrlHelper();

            Contract.Assert(urlHelper != null);

            ODataPath     path            = Request.GetODataPath();
            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)
            {
                BaseUri = GetBaseAddress(Request),
                Version = _version,
            };

            // The MetadataDocumentUri is never required for errors. Additionally, it sometimes won't be available
            // for errors, such as when routing itself fails. In that case, the route data property is not
            // available on the request, and due to a bug with HttpRoute.GetVirtualPath (bug #669) we won't be able
            // to generate a metadata link.
            if (serializer.ODataPayloadKind != ODataPayloadKind.Error)
            {
                string metadataLink = urlHelper.ODataLink(new MetadataPathSegment());

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

                string selectClause = GetSelectClause(Request);
                writerSettings.SetMetadataDocumentUri(new Uri(metadataLink), selectClause);
            }

            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.GetSelectExpandClause()
                };

                serializer.WriteObject(value, type, messageWriter, writeContext);
            }
        }
        public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
        {
            if (type == null)
            {
                throw Error.ArgumentNull("type");
            }

            if (writeStream == null)
            {
                throw Error.ArgumentNull("writeStream");
            }

            HttpContentHeaders contentHeaders = content == null ? null : content.Headers;

            return(TaskHelpers.RunSynchronously(() =>
            {
                // Get the format and version to use from the ODataServiceVersion content header or if not available use the
                // values configured for the specialized formatter instance.
                ODataVersion version;
                ODataFormat odataFormat;
                if (contentHeaders == null)
                {
                    version = _defaultODataVersion;
                    odataFormat = ODataFormatterConstants.DefaultODataFormat;
                }
                else
                {
                    version = GetODataVersion(contentHeaders, ODataFormatterConstants.ODataServiceVersion) ?? _defaultODataVersion;
                    odataFormat = GetODataFormat(contentHeaders);
                }

                ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(type);
                if (serializer == null)
                {
                    throw Error.InvalidOperation(SRResources.TypeCannotBeSerialized, type.Name, typeof(ODataMediaTypeFormatter).Name);
                }

                if (IsClient)
                {
                    // TODO: Bug 467617: figure out the story for the operation name on the client side and server side.
                    string operationName = (value != null ? value.GetType() : type).Name;

                    // serialize a request
                    IODataRequestMessage requestMessage = new ODataMessageWrapper(writeStream);
                    ODataResponseContext responseContext = new ODataResponseContext(requestMessage, odataFormat, version, new Uri(ODataFormatterConstants.DefaultNamespace), operationName);

                    ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings()
                    {
                        BaseUri = responseContext.BaseAddress,
                        Version = responseContext.ODataVersion,
                        Indent = responseContext.IsIndented,
                        DisableMessageStreamDisposal = true,
                    };

                    writerSettings.SetContentType(responseContext.ODataFormat);
                    using (ODataMessageWriter messageWriter = new ODataMessageWriter(requestMessage, writerSettings, Model))
                    {
                        ODataSerializerWriteContext writeContext = new ODataSerializerWriteContext(responseContext);
                        serializer.WriteObject(value, messageWriter, writeContext);
                    }
                }
                else
                {
                    UrlHelper urlHelper = Request.GetUrlHelper();
                    NameValueCollection queryStringValues = Request.RequestUri.ParseQueryString();

                    IEdmEntitySet targetEntitySet = null;
                    ODataUriHelpers.TryGetEntitySetAndEntityType(Request.RequestUri, Model, out targetEntitySet);

                    ODataQueryProjectionNode rootProjectionNode = null;
                    if (targetEntitySet != null)
                    {
                        // TODO: Bug 467621: Move to ODataUriParser once it is done.
                        rootProjectionNode = ODataUriHelpers.GetODataQueryProjectionNode(queryStringValues["$select"], queryStringValues["$expand"], targetEntitySet);
                    }

                    // serialize a response
                    Uri baseAddress = new Uri(Request.RequestUri, Request.GetConfiguration().VirtualPathRoot);

                    // TODO: Bug 467617: figure out the story for the operation name on the client side and server side.
                    // This is clearly a workaround. We are assuming that the operation name is the last segment in the request uri
                    // which works for most cases and fall back to the type name of the object being written.
                    // We should rather use uri parser semantic tree to figure out the operation name from the request url.
                    string operationName = ODataUriHelpers.GetOperationName(Request.RequestUri, baseAddress);
                    operationName = operationName ?? type.Name;

                    IODataResponseMessage responseMessage = new ODataMessageWrapper(writeStream);
                    ODataResponseContext responseContext = new ODataResponseContext(responseMessage, odataFormat, version, baseAddress, operationName);

                    ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings()
                    {
                        BaseUri = responseContext.BaseAddress,
                        Version = responseContext.ODataVersion,
                        Indent = responseContext.IsIndented,
                        DisableMessageStreamDisposal = true,
                    };
                    if (contentHeaders != null && contentHeaders.ContentType != null)
                    {
                        writerSettings.SetContentType(contentHeaders.ContentType.ToString(), Encoding.UTF8.WebName);
                    }

                    using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, ODataDeserializerProvider.EdmModel))
                    {
                        ODataSerializerWriteContext writeContext = new ODataSerializerWriteContext(responseContext)
                        {
                            EntitySet = targetEntitySet,
                            UrlHelper = urlHelper,
                            RootProjectionNode = rootProjectionNode,
                            CurrentProjectionNode = rootProjectionNode
                        };

                        serializer.WriteObject(value, messageWriter, writeContext);
                    }
                }
            }));
        }
Beispiel #34
0
        public void ProcessRequest(HttpContext context, Uri serviceBaseUri)
        {
            var sparqlGenerator = new SparqlGenerator(_config.Map, _config.DefaultLanguageCode, _config.MaxPageSize);

            var messageWriterSettings = new ODataMessageWriterSettings(_config.BaseODataWriterSettings)
            {
                BaseUri = serviceBaseUri
            };

            if (context.Request.AcceptTypes != null)
            {
                messageWriterSettings.SetContentType(String.Join(",", context.Request.AcceptTypes),
                                                     context.Request.Headers["Accept-Charset"]);
            }

            var          requestMessage   = new HttpDataRequestMessage(context.Request);
            ODataVersion effectiveVersion = GetEffectiveODataVersion(requestMessage);

            messageWriterSettings.Version = effectiveVersion;

            var metadataUri = new Uri(serviceBaseUri, "./$metadata");

            if (serviceBaseUri.Equals(context.Request.Url))
            {
                // We need to respond with the service document
                var responseMessage = new HttpDataResponseMessage(context.Response);
                context.Response.ContentType     = "application/xml";
                context.Response.ContentEncoding = System.Text.Encoding.UTF8;
                var feedGenerator = new ODataFeedGenerator(requestMessage, responseMessage,
                                                           _config.Map, serviceBaseUri.ToString(),
                                                           messageWriterSettings);
                feedGenerator.WriteServiceDocument();
            }
            else if (serviceBaseUri.ToString().TrimEnd('/').Equals(context.Request.Url.ToString().TrimEnd('/')))
            {
                // Trimming of trailing slash to normalize - the serviceBaseUri should always have a trailing slash,
                // but we will redirect requests that do not to the proper service document url
                context.Response.RedirectPermanent(serviceBaseUri.ToString(), true);
            }
            else if (metadataUri.Equals(context.Request.Url))
            {
                context.Response.ContentType = "application/xml";
                context.Response.WriteFile(_config.MetadataPath);
            }
            else
            {
                var parsedQuery = QueryDescriptorQueryNode.ParseUri(
                    context.Request.Url,
                    serviceBaseUri,
                    _config.Model);
                sparqlGenerator.ProcessQuery(parsedQuery);
                var responseMessage = new HttpDataResponseMessage(context.Response);
                var feedGenerator   = new ODataFeedGenerator(
                    requestMessage,
                    responseMessage,
                    _config.Map,
                    serviceBaseUri.ToString(),
                    messageWriterSettings);
                sparqlGenerator.SparqlQueryModel.Execute(_config.SparqlEndpoint, feedGenerator);
                context.Response.ContentType = "application/atom+xml";
            }
        }
Beispiel #35
0
        private static void CsvWriterDemo()
        {
            EdmEntityType customer = new EdmEntityType("ns", "customer");
            var           key      = customer.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32);

            customer.AddKeys(key);
            customer.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);

            ODataEntry entry1 = new ODataEntry()
            {
                Properties = new[]
                {
                    new ODataProperty()
                    {
                        Name = "Id", Value = 51
                    },
                    new ODataProperty()
                    {
                        Name = "Name", Value = "Name_A"
                    },
                }
            };

            ODataEntry entry2 = new ODataEntry()
            {
                Properties = new[]
                {
                    new ODataProperty()
                    {
                        Name = "Id", Value = 52
                    },
                    new ODataProperty()
                    {
                        Name = "Name", Value = "Name_B"
                    },
                }
            };

            var stream  = new MemoryStream();
            var message = new Message {
                Stream = stream
            };

            // Set Content-Type header value
            message.SetHeader("Content-Type", "text/csv");
            var settings = new ODataMessageWriterSettings
            {
                // Set our resolver here.
                MediaTypeResolver            = CsvMediaTypeResolver.Instance,
                DisableMessageStreamDisposal = true,
            };

            using (var messageWriter = new ODataMessageWriter(message, settings))
            {
                var writer = messageWriter.CreateODataFeedWriter(null, customer);
                writer.WriteStart(new ODataFeed());
                writer.WriteStart(entry1);
                writer.WriteEnd();
                writer.WriteStart(entry2);
                writer.WriteEnd();
                writer.WriteEnd();
                writer.Flush();
            }

            stream.Seek(0, SeekOrigin.Begin);
            string msg;

            using (var sr = new StreamReader(stream)) { msg = sr.ReadToEnd(); }
            Console.WriteLine(msg);
        }
Beispiel #36
0
        public void UpdateUsingAtomShouldBeFailed()
        {
            var entryWrapper = new ODataResourceWrapper()
            {
                Resource = new ODataResource()
                {
                    TypeName = NameSpacePrefix + "Person"
                },
                NestedResourceInfoWrappers = new List <ODataNestedResourceInfoWrapper>()
                {
                    new ODataNestedResourceInfoWrapper()
                    {
                        NestedResourceInfo = new ODataNestedResourceInfo()
                        {
                            Name         = "HomeAddress",
                            IsCollection = false
                        },
                        NestedResourceOrResourceSet = new ODataResourceWrapper()
                        {
                            Resource = new ODataResource()
                            {
                                TypeName   = NameSpacePrefix + "HomeAddress",
                                Properties = new[]
                                {
                                    new ODataProperty
                                    {
                                        Name  = "City",
                                        Value = "Chengdu"
                                    },
                                    new ODataProperty
                                    {
                                        Name  = "FamilyName",
                                        Value = "Tigers"
                                    }
                                }
                            }
                        }
                    }
                }
            };

            var settings = new ODataMessageWriterSettings();

            settings.BaseUri = ServiceBaseUri;
            var personType = Model.FindDeclaredType(NameSpacePrefix + "Person") as IEdmEntityType;
            var personSet  = Model.EntityContainer.FindEntitySet("People");

            var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri + "People(1)"));

            requestMessage.SetHeader("Content-Type", MimeTypes.ApplicationAtomXml);
            requestMessage.SetHeader("Accept", MimeTypes.ApplicationAtomXml);
            requestMessage.Method = "PATCH";

            using (var messageWriter = new ODataMessageWriter(requestMessage, settings, Model))
            {
                try
                {
                    var odataWriter = messageWriter.CreateODataResourceWriter(personSet, personType);
                    ODataWriterHelper.WriteResource(odataWriter, entryWrapper);
                }
                catch (Microsoft.OData.ODataContentTypeException)
                {
                    return;
                }
                Assert.IsTrue(false);
            }
        }
Beispiel #37
0
        public void PostUsingAtomShouldBeFailed()
        {
            var entryWrapper = new ODataResourceWrapper()
            {
                Resource = new ODataResource()
                {
                    TypeName   = NameSpacePrefix + "Person",
                    Properties = new[]
                    {
                        new ODataProperty {
                            Name = "PersonID", Value = 101
                        },
                        new ODataProperty {
                            Name = "FirstName", Value = "Peter"
                        },
                        new ODataProperty {
                            Name = "LastName", Value = "Zhang"
                        },
                        new ODataProperty
                        {
                            Name  = "Home",
                            Value = GeographyPoint.Create(32.1, 23.1)
                        },
                        new ODataProperty
                        {
                            Name  = "Numbers",
                            Value = new ODataCollectionValue
                            {
                                TypeName = "Collection(Edm.String)",
                                Items    = new string[] { "12345" }
                            }
                        },
                        new ODataProperty
                        {
                            Name  = "Emails",
                            Value = new ODataCollectionValue
                            {
                                TypeName = "Collection(Edm.String)",
                                Items    = new string[] { "*****@*****.**" }
                            }
                        }
                    }
                },
                NestedResourceInfoWrappers = new List <ODataNestedResourceInfoWrapper>()
                {
                    new ODataNestedResourceInfoWrapper()
                    {
                        NestedResourceInfo = new ODataNestedResourceInfo()
                        {
                            Name         = "HomeAddress",
                            IsCollection = false
                        },
                        NestedResourceOrResourceSet = new ODataResourceWrapper()
                        {
                            Resource = new ODataResource()
                            {
                                TypeName   = NameSpacePrefix + "HomeAddress",
                                Properties = new[]
                                {
                                    new ODataProperty
                                    {
                                        Name  = "Street",
                                        Value = "ZiXing Road"
                                    },
                                    new ODataProperty
                                    {
                                        Name  = "City",
                                        Value = "Chengdu"
                                    },
                                    new ODataProperty
                                    {
                                        Name  = "PostalCode",
                                        Value = "200241"
                                    },
                                    new ODataProperty
                                    {
                                        Name  = "FamilyName",
                                        Value = "Tigers"
                                    }
                                }
                            }
                        }
                    }
                }
            };

            var settings = new ODataMessageWriterSettings();

            settings.BaseUri = ServiceBaseUri;

            var personType = Model.FindDeclaredType(NameSpacePrefix + "Person") as IEdmEntityType;
            var peopleSet  = Model.EntityContainer.FindEntitySet("People");

            var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri + "People"));

            requestMessage.SetHeader("Content-Type", MimeTypes.ApplicationAtomXml);
            requestMessage.SetHeader("Accept", MimeTypes.ApplicationAtomXml);
            requestMessage.Method = "POST";
            using (var messageWriter = new ODataMessageWriter(requestMessage, settings, Model))
            {
                try
                {
                    var odataWriter = messageWriter.CreateODataResourceWriter(peopleSet, personType);
                    ODataWriterHelper.WriteResource(odataWriter, entryWrapper);
                }
                catch (Microsoft.OData.ODataContentTypeException)
                {
                    return;
                }
                Assert.IsTrue(false);
            }
        }
Beispiel #38
0
 public static ODataFormat GetFormat(this ODataMessageWriterSettings settings)
 {
     return((ODataFormat)ReflectionUtils.GetProperty(settings, "Format"));
 }
Beispiel #39
0
        public void OpenComplexType()
        {
            //Update entity with open complex type
            AccountPlus account = new AccountPlus()
            {
                AccountIDPlus     = 1000000,
                CountryRegionPlus = "CN",
                AccountInfoPlus   = new AccountInfoPlus()
                {
                    FirstNamePlus  = "Peter",
                    MiddleNamePlus = "White",
                    LastNamePlus   = "Andy",
                    IsActivePlus   = true
                }
            };

            TestClientContext.AddToAccountsPlus(account);
            TestClientContext.SaveChanges();

            //Check account can be correctly desirialized.
            account = TestClientContext.AccountsPlus.Where(a => a.AccountIDPlus == 1000000).Single();
            Assert.IsNotNull(account);
            Assert.AreEqual(account.AccountInfoPlus.MiddleNamePlus, "White");
            Assert.IsTrue(account.AccountInfoPlus.IsActivePlus);

            //Update entity with open complex type
            var entry = new ODataEntry()
            {
                TypeName = ServerSideNameSpacePrefix + "Account"
            };

            entry.Properties = new[]
            {
                new ODataProperty {
                    Name = "AccountID", Value = 1000000
                },
                new ODataProperty
                {
                    Name  = "AccountInfo",
                    Value = new ODataComplexValue
                    {
                        TypeName   = ServerSideNameSpacePrefix + "AccountInfo",
                        Properties = new[]
                        {
                            new ODataProperty
                            {
                                Name  = "FirstName",
                                Value = "Peter"
                            },
                            new ODataProperty
                            {
                                Name  = "LastName",
                                Value = "Andy"
                            },
                            //Property that exists in Customer-Defined client code.
                            new ODataProperty
                            {
                                Name  = "MiddleName",
                                Value = "White2"
                            },
                            new ODataProperty
                            {
                                Name  = "IsActive",
                                Value = false,
                            },
                            //Property that doesn't exist in Customer-Defined client code.
                            new ODataProperty
                            {
                                Name  = "ShippingAddress",
                                Value = "#999, ZiXing Road"
                            }
                        }
                    }
                }
            };

            var settings = new ODataMessageWriterSettings();

            settings.PayloadBaseUri = ServiceBaseUri;

            var accountType = Model.FindDeclaredType(ServerSideNameSpacePrefix + "Account") as IEdmEntityType;
            var accountSet  = Model.EntityContainer.FindEntitySet("Accounts");

            var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri + "Accounts(1000000)"));

            requestMessage.SetHeader("Content-Type", MimeTypes.ApplicationJson);
            requestMessage.SetHeader("Accept", MimeTypes.ApplicationJson);
            requestMessage.Method = "PATCH";
            using (var messageWriter = new ODataMessageWriter(requestMessage, settings))
            {
                var odataWriter = messageWriter.CreateODataEntryWriter(accountSet, accountType);
                odataWriter.WriteStart(entry);
                odataWriter.WriteEnd();
            }

            var responseMessage = requestMessage.GetResponse();

            TestClientContext.MergeOption = Microsoft.OData.Client.MergeOption.OverwriteChanges;
            //Check account can be correctly desirialized.
            account = TestClientContext.AccountsPlus.Where(a => a.AccountIDPlus == 1000000).Single();
            Assert.IsNotNull(account);
            Assert.AreEqual(account.AccountInfoPlus.MiddleNamePlus, "White2");
            Assert.IsTrue(!account.AccountInfoPlus.IsActivePlus);
        }
Beispiel #40
0
 public static string GetAcceptableCharsets(this ODataMessageWriterSettings settings)
 {
     return((string)ReflectionUtils.GetProperty(settings, "AcceptableCharsets"));
 }
        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.CreateODataResourceWriter(peopleSet);

            var entry = new ODataResource
            {
                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();

            Assert.Equal(payload, "{\"@odata.context\":\"http://host/service/$metadata#People/$entity\",\"ID\":\"18446744073709551615\",\"Name\":\"Foo\",\"FavoriteNumber\":250.0,\"Age\":123,\"Guid\":-9223372036854775808,\"Weight\":123.45,\"Money\":79228162514264337593543950335}");

#if NETCOREAPP1_0
            stream = new MemoryStream(Encoding.GetEncoding(0).GetBytes(payload));
#else
            stream = new MemoryStream(Encoding.Default.GetBytes(payload));
#endif
            message = new InMemoryMessage {
                Stream = stream
            };
            message.StatusCode = 200;

            var readerSettings = new ODataMessageReaderSettings();

            var messageReader = new ODataMessageReader(message, readerSettings, model);
            var entryReader   = messageReader.CreateODataResourceReader(peopleSet, personType);
            Assert.True(entryReader.Read());
            var entryReaded = entryReader.Item as ODataResource;

            var propertiesReaded = entryReaded.Properties.ToList();
            var propertiesGiven  = entry.Properties.ToList();
            Assert.Equal(propertiesReaded.Count, propertiesGiven.Count);
            for (int i = 0; i < propertiesReaded.Count; ++i)
            {
                Assert.Equal(propertiesReaded[i].Name, propertiesGiven[i].Name);
                Assert.Equal(propertiesReaded[i].Value.GetType(), propertiesGiven[i].Value.GetType());
                Assert.Equal(propertiesReaded[i].Value, propertiesGiven[i].Value);
            }
        }
        private byte[] CreateBatchRequest(string batchContentType, int unitRepeatCount)
        {
            Debug.Assert(!string.IsNullOrEmpty(batchContentType), "!string.IsNullOrEmpty(batchContentType)");

            MemoryStream stream = new MemoryStream();

            IODataRequestMessage requestMessage = new InMemoryMessage {
                Stream = stream
            };

            requestMessage.SetHeader("Content-Type", batchContentType);
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings();

            settings.BaseUri = new Uri(serviceDocumentUri);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(requestMessage, settings))
            {
                ODataBatchWriter batchWriter = messageWriter.CreateODataBatchWriter();
                batchWriter.WriteStartBatch();

                // Each iteration generates a change set with two operations, followed by one top level operation.
                // Operations count in each iteration is three.
                // Use API available in OData 7.2
                for (int idx = 0; idx < unitRepeatCount * NumOfRequestPerUnit; idx += NumOfRequestPerUnit)
                {
                    batchWriter.WriteStartChangeset();

                    ODataBatchOperationRequestMessage createOperationMessage = batchWriter.CreateOperationRequestMessage(
                        "PUT",
                        new Uri(string.Format(CultureInfo.InvariantCulture, "{0}/{1}", serviceDocumentUri, "MySingleton")),
                        idx.ToString());

                    using (ODataMessageWriter operationMessageWriter = new ODataMessageWriter(createOperationMessage))
                    {
                        ODataWriter   entryWriter = operationMessageWriter.CreateODataResourceWriter();
                        ODataResource entry       = new ODataResource()
                        {
                            TypeName   = "NS.Web",
                            Properties = new[]
                            {
                                new ODataProperty()
                                {
                                    Name = "WebId", Value = "webid_" + idx
                                },
                                new ODataProperty()
                                {
                                    Name = "Name", Value = this.aLongString
                                }
                            }
                        };
                        entryWriter.WriteStart(entry);
                        entryWriter.WriteEnd();
                    }

                    // A PATCH operation.
                    ODataBatchOperationRequestMessage updateOperationMessage = batchWriter.CreateOperationRequestMessage(
                        "PATCH",
                        new Uri(string.Format(CultureInfo.InvariantCulture, "{0}/{1}", serviceDocumentUri, "MySingleton")),
                        (idx + 1).ToString(),
                        BatchPayloadUriOption.AbsoluteUri);

                    using (ODataMessageWriter operationMessageWriter = new ODataMessageWriter(updateOperationMessage))
                    {
                        var entryWriter = operationMessageWriter.CreateODataResourceWriter();
                        var entry       = new ODataResource()
                        {
                            TypeName   = "NS.Web",
                            Properties = new[] { new ODataProperty()
                                                 {
                                                     Name = "WebId", Value = "webid_" + (idx + 1)
                                                 } }
                        };
                        entryWriter.WriteStart(entry);
                        entryWriter.WriteEnd();
                    }

                    batchWriter.WriteEndChangeset();

                    ODataBatchOperationRequestMessage queryOperationMessage = batchWriter.CreateOperationRequestMessage(
                        "GET",
                        new Uri(string.Format(CultureInfo.InvariantCulture, "{0}/{1}", serviceDocumentUri, "MySingleton")),
                        (idx + 2).ToString());
                    queryOperationMessage.SetHeader("Accept", "application/json;odata.metadata=full");
                }

                batchWriter.WriteEndBatch();

                stream.Position = 0;
                return(stream.ToArray());
            }
        }
        private byte[] ServiceReadSingletonBatchRequestAndWriterBatchResponse(ODataJsonBatchPayloadTestCase testCase, ODataVersion version)
        {
            string requestPayload = testCase.RequestPayload;
            Action <ODataBatchOperationRequestMessage, IList <string> > requestOpMessageVerifier = testCase.RequestMessageDependsOnIdVerifier;

            IODataRequestMessage requestMessage = new InMemoryMessage()
            {
                Stream = new MemoryStream(Encoding.ASCII.GetBytes(requestPayload))
            };

            requestMessage.SetHeader("Content-Type", batchContentTypeApplicationJson);

            MemoryStream responseStream = new MemoryStream();

            using (ODataMessageReader messageReader =
                       new ODataMessageReader(requestMessage, new ODataMessageReaderSettings()
            {
                Version = version
            }, this.edmModel))
            {
                IODataResponseMessage responseMessage = new InMemoryMessage {
                    Stream = responseStream
                };

                // Client is expected to receive the response message in the same format as that is used in the request sent.
                responseMessage.SetHeader("Content-Type", batchContentTypeApplicationJson);

                ODataMessageWriterSettings settings = new ODataMessageWriterSettings()
                {
                    Version = version
                };
                settings.SetServiceDocumentUri(new Uri(serviceDocumentUri));

                ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, null);
                int operationIdx = 0;

                ODataBatchWriter batchWriter = messageWriter.CreateODataBatchWriter();
                batchWriter.WriteStartBatch();

                ODataBatchReader batchReader = messageReader.CreateODataBatchReader();
                while (batchReader.Read())
                {
                    switch (batchReader.State)
                    {
                    case ODataBatchReaderState.Operation:
                        // Encountered an operation (either top-level or in a change set)
                        ODataBatchOperationRequestMessage operationMessage = batchReader.CreateOperationRequestMessage();

                        // Verify operation message if applicable.
                        requestOpMessageVerifier?.Invoke(operationMessage, testCase.ListOfDependsOnIds.ElementAt(operationIdx));

                        if (operationMessage.Method == "POST")
                        {
                            ODataBatchOperationResponseMessage response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId);
                            response.StatusCode = 201;
                            response.SetHeader("Content-Type", batchContentTypeApplicationJson);
                        }
                        else if (operationMessage.Method == "GET")
                        {
                            ODataBatchOperationResponseMessage response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId);
                            response.StatusCode = 200;
                            response.SetHeader("Content-Type", batchContentTypeApplicationJson);

                            using (ODataMessageWriter operationMessageWriter = new ODataMessageWriter(response, settings, this.edmModel))
                            {
                                ODataWriter entryWriter = operationMessageWriter.CreateODataResourceWriter(this.singleton,
                                                                                                           this.userType);
                                ODataResource entry = new ODataResource()
                                {
                                    TypeName   = "NS.User",
                                    Properties =
                                        new[]
                                    {
                                        new ODataProperty()
                                        {
                                            Name = "UserPrincipalName", Value = "*****@*****.**"
                                        },
                                        new ODataProperty()
                                        {
                                            Name = "GivenName", Value = "Jon"
                                        }
                                    }
                                };
                                entryWriter.WriteStart(entry);
                                entryWriter.WriteEnd();
                            }
                        }

                        operationIdx++;
                        break;

                    case ODataBatchReaderState.ChangesetStart:
                        batchWriter.WriteStartChangeset();
                        break;

                    case ODataBatchReaderState.ChangesetEnd:
                        batchWriter.WriteEndChangeset();
                        break;
                    }
                }

                batchWriter.WriteEndBatch();
            }

            responseStream.Position = 0;
            return(responseStream.ToArray());
        }
        private byte[] ServiceReadReferenceUriBatchRequestAndWriteResponse(string batchContentType, byte[] requestPayload)
        {
            Debug.Assert(!string.IsNullOrEmpty(batchContentType), "!string.IsNullOrEmpty(batchContentType)");

            IODataRequestMessage requestMessage = new InMemoryMessage()
            {
                Stream = new MemoryStream(requestPayload)
            };

            requestMessage.SetHeader("Content-Type", batchContentType);
            ODataMessageReaderSettings settings = new ODataMessageReaderSettings();

            settings.BaseUri = new Uri(serviceDocumentUri);

            byte[] responseBytes = null;

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

                IODataResponseMessage responseMessage = new InMemoryMessage {
                    Stream = responseStream
                };

                // Client is expected to receive the response message in the same format as that is used in the request sent.
                responseMessage.SetHeader("Content-Type", batchContentType);

                using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage))
                {
                    ODataBatchWriter batchWriter = messageWriter.CreateODataBatchWriter();
                    batchWriter.WriteStartBatch();

                    ODataBatchReader batchReader = messageReader.CreateODataBatchReader();
                    while (batchReader.Read())
                    {
                        switch (batchReader.State)
                        {
                        case ODataBatchReaderState.Operation:
                            // Encountered an operation (either top-level or in a change set)
                            ODataBatchOperationRequestMessage operationMessage =
                                batchReader.CreateOperationRequestMessage();

                            ODataBatchOperationResponseMessage response =
                                batchWriter.CreateOperationResponseMessage(operationMessage.ContentId);

                            if (operationMessage.Method == "PUT")
                            {
                                using (ODataMessageReader operationMessageReader = new ODataMessageReader(
                                           operationMessage, new ODataMessageReaderSettings(), this.userModel))
                                {
                                    ODataReader reader = operationMessageReader.CreateODataResourceReader();
                                }

                                response.StatusCode = 201;
                                response.SetHeader("Content-Type", "application/json;odata.metadata=none");
                            }
                            else if (operationMessage.Method == "PATCH")
                            {
                                using (ODataMessageReader operationMessageReader = new ODataMessageReader(
                                           operationMessage, new ODataMessageReaderSettings(), this.userModel))
                                {
                                    ODataReader reader = operationMessageReader.CreateODataResourceReader();
                                }

                                response.StatusCode = 204;
                            }
                            else if (operationMessage.Method == "GET")
                            {
                                response.StatusCode = 200;
                                response.SetHeader("Content-Type", "application/json;");
                                ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings();
                                writerSettings.ODataUri.ServiceRoot = new Uri(serviceDocumentUri);

                                using (
                                    ODataMessageWriter operationMessageWriter = new ODataMessageWriter(response,
                                                                                                       writerSettings, this.userModel))
                                {
                                    ODataWriter entryWriter =
                                        operationMessageWriter.CreateODataResourceWriter(this.singleton,
                                                                                         this.webType);
                                    ODataResource entry = new ODataResource()
                                    {
                                        TypeName   = "NS.Web",
                                        Properties = new[]
                                        {
                                            new ODataProperty()
                                            {
                                                Name = "WebId", Value = -1
                                            },
                                            new ODataProperty()
                                            {
                                                Name = "Name", Value = aLongString
                                            }
                                        }
                                    };
                                    entryWriter.WriteStart(entry);
                                    entryWriter.WriteEnd();
                                }
                            }

                            break;

                        case ODataBatchReaderState.ChangesetStart:
                            // Set the group Id on the writer side to correlate with request.
                            // Use API available in OData 7.2. Don't need to have same group Id for this test.
                            batchWriter.WriteStartChangeset();
                            break;

                        case ODataBatchReaderState.ChangesetEnd:
                            batchWriter.WriteEndChangeset();
                            break;
                        }
                    }

                    batchWriter.WriteEndBatch();

                    responseStream.Position = 0;
                    responseBytes           = responseStream.ToArray();
                }

                return(responseBytes);
            }
        }
Beispiel #45
0
        private static IJsonWriter CreateJsonWriter(IServiceProvider container, TextWriter textWriter, bool isIeee754Compatible, ODataMessageWriterSettings writerSettings)
        {
            IJsonWriter jsonWriter;

            if (container == null)
            {
                jsonWriter = new JsonWriter(textWriter, isIeee754Compatible);
            }
            else
            {
                IJsonWriterFactory jsonWriterFactory = container.GetRequiredService <IJsonWriterFactory>();
                jsonWriter = jsonWriterFactory.CreateJsonWriter(textWriter, isIeee754Compatible);
                Debug.Assert(jsonWriter != null, "jsonWriter != null");
            }

            JsonWriter writer = jsonWriter as JsonWriter;

            if (writer != null && writerSettings.ArrayPool != null)
            {
                writer.ArrayPool = writerSettings.ArrayPool;
            }

            return(jsonWriter);
        }
Beispiel #46
0
 public static object GetWriterBehavior(this ODataMessageWriterSettings settings)
 {
     return(ReflectionUtils.GetProperty(settings, "WriterBehavior"));
 }
Beispiel #47
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MessageWriterSettingsArgs"/> class.
        /// </summary>
        /// <param name="settings">The settings.</param>
        public MessageWriterSettingsArgs(ODataMessageWriterSettings settings)
        {
            WebUtil.CheckArgumentNull(settings, "settings");

            this.Settings = settings;
        }
Beispiel #48
0
        /// <summary>
        /// Creates a writer for the given request message and settings.
        /// </summary>
        /// <param name="requestMessage">The request message.</param>
        /// <param name="writerSettings">The writer settings.</param>
        /// <param name="isParameterPayload">true if the writer is intended to for a parameter payload, false otherwise.</param>
        /// <returns>Newly created writer.</returns>
        internal ODataMessageWriter CreateWriter(IODataRequestMessage requestMessage, ODataMessageWriterSettings writerSettings, bool isParameterPayload)
        {
            Debug.Assert(requestMessage != null, "requestMessage != null");
            Debug.Assert(writerSettings != null, "writerSettings != null");

            this.requestInfo.Context.Format.ValidateCanWriteRequestFormat(requestMessage, isParameterPayload);

            // When calling Execute() to invoke an Action, the client doesn't support parsing the target url
            // to determine which IEdmOperationImport to pass to the ODL writer. So the ODL writer is
            // serializing the parameter payload without metadata. Setting the model to null so ODL doesn't
            // do unecessary validations when writing without metadata.
            var model = isParameterPayload ? null : this.requestInfo.Model;

            return(new ODataMessageWriter(requestMessage, writerSettings, model));
        }
 public override System.Threading.Tasks.Task <ODataOutputContext> CreateOutputContextAsync(ODataMessageInfo messageInfo, ODataMessageWriterSettings messageWriterSettings)
 {
     throw new NotImplementedException();
 }
        private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)
        {
            IEdmModel model = Request.GetModel();

            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

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

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

            ODataPath            path = Request.ODataProperties().Path;
            IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource;

            // serialize a response
            HttpConfiguration configuration = Request.GetConfiguration();

            if (configuration == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustContainConfiguration);
            }

            string preferHeader     = RequestPreferenceHelpers.GetRequestPreferHeader(Request);
            string annotationFilter = null;

            if (!String.IsNullOrEmpty(preferHeader))
            {
                ODataMessageWrapper messageWrapper = new ODataMessageWrapper(writeStream, content.Headers);
                messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
            }

            ODataMessageWrapper responseMessageWrapper = new ODataMessageWrapper(writeStream, content.Headers)
            {
                Container = Request.GetRequestContainer()
            };
            IODataResponseMessage responseMessage = responseMessageWrapper;

            if (annotationFilter != null)
            {
                responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter;
            }

            Uri baseAddress = GetBaseAddressInternal(Request);
            ODataMessageWriterSettings writerSettings = Request.GetWriterSettings();

            writerSettings.BaseUri     = baseAddress;
            writerSettings.Version     = _version;
            writerSettings.Validations = writerSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType;

            string metadataLink = urlHelper.CreateODataLink(MetadataSegment.Instance);

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

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

                // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath.
                SelectAndExpand = Request.ODataProperties().SelectExpandClause,
                Apply           = Request.ODataProperties().ApplyClause,
                Path            = (path == null || IsOperationPath(path)) ? null : path.ODLPath,
            };

            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,
                    NavigationSource = targetNavigationSource,
                    Model            = model,
                    RootElementName  = GetRootElementName(path) ?? "root",
                    SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.ResourceSet,
                    Path               = path,
                    MetadataLevel      = ODataMediaTypes.GetMetadataLevel(contentType),
                    SelectExpandClause = Request.ODataProperties().SelectExpandClause
                };

                serializer.WriteObject(value, type, messageWriter, writeContext);
            }
        }
        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.True(entryReader.Read());
            var entryReaded = entryReader.Item as ODataEntry;

            var propertiesReaded = entryReaded.Properties.ToList();
            var propertiesGiven = entry.Properties.ToList();
            Assert.Equal(propertiesReaded.Count, propertiesGiven.Count);
            for (int i = 0; i < propertiesReaded.Count; ++i)
            {
                Assert.Equal(propertiesReaded[i].Name, propertiesGiven[i].Name);
                Assert.Equal(propertiesReaded[i].Value.GetType(), propertiesGiven[i].Value.GetType());
                Assert.Equal(propertiesReaded[i].Value, propertiesGiven[i].Value);
            }
        }
 public TestODataOutputContext(ODataFormat format, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver)
     : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver)
 {
 }
        private string GetWriterOutputForContentTypeAndKnobValue(
            string contentType,
            bool autoComputePayloadMetadataInJson,
            ODataItem[] itemsToWrite,
            EdmModel edmModel,
            IEdmEntitySetBase edmEntitySet,
            EdmEntityType edmEntityType,
            string selectClause = null,
            string expandClause = null,
            string resourcePath = null,
            bool enableFullValidation = true)
        {
            MemoryStream outputStream = new MemoryStream();
            IODataResponseMessage message = new InMemoryMessage() { Stream = outputStream };
            message.SetHeader("Content-Type", contentType);
            ODataMessageWriterSettings settings = new ODataMessageWriterSettings()
            {
                AutoComputePayloadMetadataInJson = autoComputePayloadMetadataInJson,
                EnableFullValidation = enableFullValidation
            };

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

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

            if (resourcePath != null)
            {
                Uri requestUri = new Uri("http://example.org/odata.svc/" + resourcePath);
                odataUri.RequestUri = requestUri;
                odataUri.Path = new ODataUriParser(edmModel, new Uri("http://example.org/odata.svc/"), 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.True(false, "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 ODataMessageWriter given the writer settings.
 /// </summary>
 /// <param name="writerSettings">Writer settings.</param>
 /// <param name="isParameterPayload">true if the writer is intended to for a parameter payload, false otherwise.</param>
 /// <returns>An instance of ODataMessageWriter.</returns>
 internal abstract ODataMessageWriter CreateWriter(ODataMessageWriterSettings writerSettings, bool isParameterPayload);
        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);
        }
Beispiel #56
0
        internal static async Task WriteToStreamAsync(
            Type type,
            object value,
            IEdmModel model,
            ODataVersion version,
            Uri baseAddress,
            MediaTypeHeaderValue contentType,
            HttpRequest request,
            IHeaderDictionary requestHeaders,
            ODataSerializerProvider serializerProvider)
        {
            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

            ODataSerializer serializer = GetSerializer(type, value, request, serializerProvider);

            ODataPath            path = request.ODataFeature().Path;
            IEdmNavigationSource targetNavigationSource = path == null ? null : path.GetNavigationSource();
            HttpResponse         response = request.HttpContext.Response;

            // serialize a response
            string preferHeader     = RequestPreferenceHelpers.GetRequestPreferHeader(requestHeaders);
            string annotationFilter = null;

            if (!string.IsNullOrEmpty(preferHeader))
            {
                ODataMessageWrapper messageWrapper = ODataMessageWrapperHelper.Create(response.Body, response.Headers);
                messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
            }

            IODataResponseMessageAsync responseMessage = ODataMessageWrapperHelper.Create(new StreamWrapper(response.Body), response.Headers, request.GetSubServiceProvider());

            if (annotationFilter != null)
            {
                responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter;
            }

            ODataMessageWriterSettings writerSettings = request.GetWriterSettings();

            writerSettings.BaseUri     = baseAddress;
            writerSettings.Version     = version;
            writerSettings.Validations = writerSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType;

            string metadataLink = request.CreateODataLink(MetadataSegment.Instance);

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

            // Set this variable if the SelectExpandClause is different from the processed clause on the Query options
            SelectExpandClause selectExpandDifferentFromQueryOptions = null;
            ODataQueryOptions  queryOptions = request.GetQueryOptions();
            SelectExpandClause processedSelectExpandClause = request.ODataFeature().SelectExpandClause;

            if (queryOptions != null && queryOptions.SelectExpand != null)
            {
                if (queryOptions.SelectExpand.ProcessedSelectExpandClause != processedSelectExpandClause)
                {
                    selectExpandDifferentFromQueryOptions = processedSelectExpandClause;
                }
            }
            else if (processedSelectExpandClause != null)
            {
                selectExpandDifferentFromQueryOptions = processedSelectExpandClause;
            }

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

                // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath.
                SelectAndExpand = processedSelectExpandClause,
                Apply           = request.ODataFeature().ApplyClause,
                //Path = (path == null || IsOperationPath(path)) ? null : path.Path,
                Path = path
            };

            ODataMetadataLevel metadataLevel = ODataMetadataLevel.Minimal;

            if (contentType != null)
            {
                IEnumerable <KeyValuePair <string, string> > parameters =
                    contentType.Parameters.Select(val => new KeyValuePair <string, string>(val.Name.ToString(),
                                                                                           val.Value.ToString()));
                metadataLevel = ODataMediaTypes.GetMetadataLevel(contentType.MediaType.ToString(), parameters);
            }

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model))
            {
                ODataSerializerContext writeContext = BuildSerializerContext(request);
                writeContext.NavigationSource = targetNavigationSource;
                writeContext.Model            = model;
                writeContext.RootElementName  = GetRootElementName(path) ?? "root";
                writeContext.SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.ResourceSet;
                writeContext.Path          = path;
                writeContext.MetadataLevel = metadataLevel;
                writeContext.QueryOptions  = queryOptions;

                //Set the SelectExpandClause on the context if it was explicitly specified.
                if (selectExpandDifferentFromQueryOptions != null)
                {
                    writeContext.SelectExpandClause = selectExpandDifferentFromQueryOptions;
                }

                await serializer.WriteObjectAsync(value, type, messageWriter, writeContext).ConfigureAwait(false);
            }
        }
Beispiel #57
0
 public ODataJsonWriterUtilsTests()
 {
     this.stringWriter = new StringWriter();
     this.jsonWriter   = new JsonWriter(this.stringWriter, isIeee754Compatible: true);
     this.settings     = new ODataMessageWriterSettings();
 }
Beispiel #58
0
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
#endif
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseSession();

#if NETCORE30 || NET50
            app.UseRouting();
#endif

            // do not change the name of defaultCulture
            var defaultCulture = "en-US";
            IList <CultureInfo> supportedCultures = new List <CultureInfo>
            {
                new CultureInfo(defaultCulture)
            };
            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture(defaultCulture),
                SupportedCultures     = supportedCultures,
                SupportedUICultures   = supportedCultures
            });

#if ODATA_SERVER
#if NETCORE10
            // BUGS
            // Below fixes to make OData work properly.
            // None of that should be needed once Microsoft.AspNetCore.OData released.
            app.Use((context, func) =>
            {
                System.Diagnostics.Debug.WriteLine(context.Request.Path);

                if (context.Request.Path.StartsWithSegments(new PathString("/MyNorthWind"), StringComparison.OrdinalIgnoreCase))
                {
                    System.Diagnostics.Debug.WriteLine("Headers for {0} ({1}):", context.Request.Path, context.Request.Headers);

                    foreach (string key in context.Request.Headers.Keys)
                    {
                        System.Diagnostics.Debug.WriteLine(key + "=" + context.Request.Headers[key]);
                    }

                    // Case where only text/ plain and / or odata.metadata = minimal found in Accept header causing System.InvalidOperationException: No media types found in 'Microsoft.AspNetCore.OData.Formatter.ODataOutputFormatter.SupportedMediaTypes'.Add at least one media type to the list of supported media types.
                    // Solution is to enforce simple application/json content type
                    if (context.Request.Headers.ContainsKey("Accept"))
                    {
                        context.Request.Headers["Accept"] = "application/json";
                    }
                }

                // Fix to generate and return metadata
                // http://stackoverflow.com/questions/42193231/odata-v4-on-net-core-1-1-missing-metadata/43330412#43330412
                if (context.Request.Path.StartsWithSegments(new PathString("/MyNorthWind/$metadata"), StringComparison.OrdinalIgnoreCase))
                {
                    var edmModel = app.ApplicationServices.GetService <Microsoft.OData.Edm.IEdmModel>();

                    var stream  = new MemoryStream();
                    var message = new InMemoryMessage()
                    {
                        Stream = stream
                    };
                    var settings = new ODataMessageWriterSettings();

                    var writer = new ODataMessageWriter((IODataResponseMessage)message, settings, edmModel);
                    writer.WriteMetadataDocument();

                    string output = Encoding.UTF8.GetString(stream.ToArray());

                    return(context.Response.WriteAsync(output));
                }

                return(func());
            });

            // Configuring OData
            app.UseOData("MyNorthWind");
#elif NETCORE20
            // Configurate OData source.
            // http://odata.github.io/WebApi/#14-01-netcore-beta1
            var builder = new ODataConventionModelBuilder(app.ApplicationServices);
            builder.EntitySet <Category>("Categories");
            builder.EntitySet <Order>("Orders");
#endif
#endif

#if NETCORE30 || NET50
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");

                endpoints.MapControllerRoute(
                    name: "Validation",
                    pattern: "{control}/UnobtrusiveValidation",
                    defaults: new { controller = "Validation", action = "Register" },
                    constraints: new { control = "(AutoComplete)|(ComboBox)|(MultiSelect)|(^Input.*)|(MultiAutoComplete)" }
                    );
            });
#else
            app.UseMvc(r => {
#if ODATA_SERVER && !NETCORE10
                // Enable filter, order and count in OData
                r.Select().Expand().Filter().MaxTop(100).OrderBy().Count();
                r.MapODataServiceRoute(
                    routeName: "ODataRoute",
                    routePrefix: "MyNorthWind",
                    model: builder.GetEdmModel()
                    );
                r.EnableDependencyInjection();
#endif
                r.MapRoute(
                    name: "Validation",
                    template: "{control}/UnobtrusiveValidation",
                    defaults: new { controller = "Validation", action = "Register" },
                    constraints: new { control = "(AutoComplete)|(ComboBox)|(MultiSelect)|(^Input.*)|(MultiAutoComplete)" }
                    );

                r.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
#endif
        }
        private static TestODataWriterCore CreateODataWriterCore(ODataFormat format, bool writingResponse, IEdmModel model, IEdmEntitySet writerSet, IEdmEntityType writerEntityType, bool writeFeed)
        {
            var resolver = new TestUrlResolver();
            var settings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true, Version = ODataVersion.V4 };
            settings.SetServiceDocumentUri(new Uri("http://example.com"));

            var outputContext = new TestODataOutputContext(format, settings, writingResponse, false, model, resolver);
            return new TestODataWriterCore(outputContext, writerSet, writerEntityType, writeFeed);
        }
        public void QueryDelta()
        {
            Uri deltaLink = null;

            #region Request DeltaLink
            ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings()
            {
                BaseUri = ServiceBaseUri
            };

            var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + "Orders?$expand=OrderDetails", UriKind.Absolute));
            requestMessage.SetHeader("Accept", MimeTypes.ApplicationJson + MimeTypes.ODataParameterMinimalMetadata);
            requestMessage.SetHeader("Prefer", "odata.track-changes");
            var responseMessage = requestMessage.GetResponse();
            Assert.AreEqual(200, responseMessage.StatusCode);

            using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, Model))
            {
                var reader = messageReader.CreateODataFeedReader();

                while (reader.Read())
                {
                    if (reader.State == ODataReaderState.EntryEnd)
                    {
                        ODataEntry entry = reader.Item as ODataEntry;
                        Assert.IsNotNull(entry.Properties.Single(p => p.Name == "OrderID").Value);
                    }
                    else if (reader.State == ODataReaderState.FeedEnd)
                    {
                        var feed = reader.Item as ODataFeed;
                        Assert.IsNotNull(feed);
                        deltaLink = feed.DeltaLink;
                    }
                }
                Assert.AreEqual(ODataReaderState.Completed, reader.State);
            }
            #endregion

            #region Add a new Order
            // create entry and insert
            var orderEntry = new ODataEntry()
            {
                TypeName = NameSpacePrefix + "Order"
            };
            var orderP1 = new ODataProperty {
                Name = "OrderID", Value = 101
            };
            var orderp2 = new ODataProperty {
                Name = "OrderDate", Value = new DateTimeOffset(new DateTime(2013, 8, 29, 14, 11, 57))
            };
            var orderp3 = new ODataProperty
            {
                Name  = "OrderShelfLifes",
                Value = new ODataCollectionValue()
                {
                    TypeName = "Collection(Edm.Duration)", Items = new Collection <TimeSpan> {
                        new TimeSpan(1)
                    }
                }
            };
            orderEntry.Properties = new[] { orderP1, orderp2, orderp3 };

            var settings = new ODataMessageWriterSettings();
            settings.PayloadBaseUri = ServiceBaseUri;

            var orderType = Model.FindDeclaredType(NameSpacePrefix + "Order") as IEdmEntityType;
            var orderSet  = Model.EntityContainer.FindEntitySet("Orders");

            requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri + "Orders"));
            requestMessage.SetHeader("Content-Type", MimeTypes.ApplicationJson + MimeTypes.ODataParameterMinimalMetadata);
            requestMessage.SetHeader("Accept", MimeTypes.ApplicationJson + MimeTypes.ODataParameterMinimalMetadata);
            requestMessage.Method = "POST";
            using (var messageWriter = new ODataMessageWriter(requestMessage, settings))
            {
                var odataWriter = messageWriter.CreateODataEntryWriter(orderSet, orderType);
                odataWriter.WriteStart(orderEntry);
                odataWriter.WriteEnd();
            }
            requestMessage.GetResponse();
            #endregion

            #region Delete a Order
            requestMessage        = new HttpWebRequestMessage(new Uri(ServiceBaseUri + "Orders(8)"));
            requestMessage.Method = "DELETE";
            requestMessage.GetResponse();
            #endregion

            #region Delete a Order Detail link
            requestMessage        = new HttpWebRequestMessage(new Uri(ServiceBaseUri + "OrderDetails(OrderID=7,ProductID=6)"));
            requestMessage.Method = "DELETE";
            requestMessage.GetResponse();
            #endregion

            #region Add a Order Detail entry and link
            #endregion

            #region Using DeltaLink
            requestMessage = new HttpWebRequestMessage(deltaLink);
            requestMessage.SetHeader("Accept", MimeTypes.ApplicationJson + MimeTypes.ODataParameterMinimalMetadata);
            requestMessage.SetHeader("Prefer", "odata.track-changes");
            responseMessage = requestMessage.GetResponse();
            Assert.AreEqual(200, responseMessage.StatusCode);
            #endregion
        }