예제 #1
0
        public static ODataSerializerProvider GetMockODataSerializerProvider(ODataSerializer serializer)
        {
            Mock <ODataSerializerProvider> serializerProvider = new Mock <ODataSerializerProvider>();

            serializerProvider.Setup(sp => sp.GetODataPayloadSerializer(It.IsAny <IEdmModel>(), It.IsAny <Type>())).Returns(serializer);
            return(serializerProvider.Object);
        }
        public void GetODataSerializer_ReturnsNull_IfTypeUnknown()
        {
            // Arrange
            HttpRequest request = GetRequest(_edmModel);

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(typeof(UnknownEntityType), request);

            // Assert
            Assert.Null(serializer);
        }
        /// <inheritdoc/>
        public override bool CanWriteType(Type type)
        {
            if (type == null)
            {
                throw Error.ArgumentNull("type");
            }

            ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(type);

            return(serializer != null);
        }
예제 #4
0
        private static ODataPayloadKind?GetClrObjectResponsePayloadKind(Type type, bool isGenericSingleResult, Func <Type, ODataSerializer> getODataPayloadSerializer)
        {
            // SingleResult<T> should be serialized as T.
            if (isGenericSingleResult)
            {
                type = type.GetGenericArguments()[0];
            }

            ODataSerializer serializer = getODataPayloadSerializer(type);

            return(serializer == null ? null : (ODataPayloadKind?)serializer.ODataPayloadKind);
        }
예제 #5
0
        private ODataPayloadKind?GetClrObjectResponsePayloadKind(Type type, IEdmModel model)
        {
            // SingleResult<T> should be serialized as T.
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(SingleResult <>))
            {
                type = type.GetGenericArguments()[0];
            }

            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(model, type, Request);

            return(serializer == null ? null : (ODataPayloadKind?)serializer.ODataPayloadKind);
        }
예제 #6
0
        public void GetODataSerializer_Returns_ExpectedSerializerType(Type payloadType, Type expectedSerializerType)
        {
            // Arrange
            var request = RequestFactory.Create();

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(payloadType, request);

            // Assert
            Assert.NotNull(serializer);
            Assert.IsType(expectedSerializerType, serializer);
        }
예제 #7
0
        public void GetODataSerializer_ReturnsSameSerializer_ForSameType()
        {
            // Arrange
            HttpRequest request = GetRequest(_edmModel);

            // Act
            ODataSerializer firstCallSerializer  = _serializerProvider.GetODataPayloadSerializer(typeof(Product), request);
            ODataSerializer secondCallSerializer = _serializerProvider.GetODataPayloadSerializer(typeof(Product), request);

            // Assert
            Assert.Same(firstCallSerializer, secondCallSerializer);
        }
예제 #8
0
        public void GetEdmTypeSerializer_Caches_CreateEdmTypeSerializerOutput()
        {
            // Arrange
            IEdmTypeReference edmType = new Mock <IEdmTypeReference>().Object;

            // Act
            ODataSerializer serializer1 = _serializerProvider.GetEdmTypeSerializer(edmType);
            ODataSerializer serializer2 = _serializerProvider.GetEdmTypeSerializer(edmType);

            // Assert
            Assert.Same(serializer2, serializer1);
        }
예제 #9
0
        public void GetODataSerializer_Returns_ExpectedSerializerType(Type payloadType, Type expectedSerializerType)
        {
            // Arrange
            HttpRequest request = GetRequest(EdmCoreModel.Instance);

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(payloadType, request);

            // Assert
            Assert.NotNull(serializer);
            Assert.IsType(expectedSerializerType, serializer);
        }
예제 #10
0
        public void GetODataSerializer_ReturnsSameSerializer_ForSameType()
        {
            // Arrange
            var request = RequestFactory.CreateFromModel(_edmModel);

            // Act
            ODataSerializer firstCallSerializer = _serializerProvider.GetODataPayloadSerializer(
                typeof(ODataResourceDeserializerTests.Supplier), request);
            ODataSerializer secondCallSerializer = _serializerProvider.GetODataPayloadSerializer(
                typeof(ODataResourceDeserializerTests.Supplier), request);

            // Assert
            Assert.Same(firstCallSerializer, secondCallSerializer);
        }
예제 #11
0
        public void GetODataSerializer_Enum()
        {
            // Arrange
            HttpRequest request = GetRequest(_edmModel);

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(typeof(TestEnum), request);

            // Assert
            Assert.NotNull(serializer);
            var enumSerializer = Assert.IsType <ODataEnumSerializer>(serializer);

            Assert.Equal(ODataPayloadKind.Property, enumSerializer.ODataPayloadKind);
        }
예제 #12
0
        public void GetODataSerializer_Primitive(Type type, EdmPrimitiveTypeKind edmPrimitiveTypeKind)
        {
            // Arrange
            HttpRequest request = GetRequest(EdmCoreModel.Instance);

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(type, request);

            // Assert
            Assert.NotEqual(EdmPrimitiveTypeKind.None, edmPrimitiveTypeKind);
            Assert.NotNull(serializer);
            ODataPrimitiveSerializer primitiveSerializer = Assert.IsType <ODataPrimitiveSerializer>(serializer);

            Assert.Equal(ODataPayloadKind.Property, primitiveSerializer.ODataPayloadKind);
        }
예제 #13
0
        public void GetODataSerializer_ResourceSet_ForComplexCollection(Type collectionType)
        {
            // Arrange
            HttpRequest request = GetRequest(_edmModel);

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(collectionType, request);

            // Assert
            Assert.NotNull(serializer);
            var resourceSetSerializer = Assert.IsType <ODataResourceSetSerializer>(serializer);

            Assert.Equal(ODataPayloadKind.ResourceSet, resourceSetSerializer.ODataPayloadKind);
            Assert.Same(resourceSetSerializer.SerializerProvider, _serializerProvider);
        }
예제 #14
0
        public void GetODataSerializer_Resource_ForComplex()
        {
            // Arrange
            HttpRequest request = GetRequest(_edmModel);

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(typeof(Address), request);

            // Assert
            Assert.NotNull(serializer);
            var complexSerializer = Assert.IsType <ODataResourceSerializer>(serializer);

            Assert.Equal(complexSerializer.SerializerProvider, _serializerProvider);
            Assert.Equal(ODataPayloadKind.Resource, complexSerializer.ODataPayloadKind);
        }
예제 #15
0
        public void GetODataSerializer_Resource_ForEntity()
        {
            // Arrange
            HttpRequest request = GetRequest(_edmModel);

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(typeof(Product), request);

            // Assert
            Assert.NotNull(serializer);
            var entitySerializer = Assert.IsType <ODataResourceSerializer>(serializer);

            Assert.Equal(entitySerializer.SerializerProvider, _serializerProvider);
            Assert.Equal(ODataPayloadKind.Resource, entitySerializer.ODataPayloadKind);
        }
예제 #16
0
        private ODataPayloadKind?GetClrObjectResponsePayloadKind(Type type, OutputFormatterWriteContext context)
        {
            // SingleResult<T> should be serialized as T.
            //if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(SingleResult<>))
            //{
            //    type = type.GetGenericArguments()[0];
            //}

            IODataSerializerProvider provider =
                context.HttpContext.RequestServices.GetRequiredService <IODataSerializerProvider>();

            ODataSerializer serializer = provider.GetODataPayloadSerializer(context.HttpContext, type);

            return(serializer == null ? null : (ODataPayloadKind?)serializer.ODataPayloadKind);
        }
        /// <inheritdoc/>
        public override bool CanWriteType(Type type)
        {
            if (type == null)
            {
                throw Error.ArgumentNull("type");
            }

            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(type);

            if (serializer == null)
            {
                return(false);
            }

            return(_payloadKinds.Contains(serializer.ODataPayloadKind));
        }
예제 #18
0
        public void GetODataPayloadSerializer_ReturnsRawValueSerializer_ForValueRequests(Type type, EdmPrimitiveTypeKind edmPrimitiveTypeKind)
        {
            // Arrange
            ODataPath   odataPath = new ODataPath(new ValueSegment(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Int32)));
            HttpRequest request   = GetRequest(EdmCoreModel.Instance);

            request.ODataFeature().Path = odataPath;

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(type, request);

            // Assert
            Assert.NotEqual(EdmPrimitiveTypeKind.None, edmPrimitiveTypeKind);
            Assert.NotNull(serializer);
            Assert.Equal(ODataPayloadKind.Value, serializer.ODataPayloadKind);
        }
예제 #19
0
        public void GetODataPayloadSerializer_ReturnsRawValueSerializer_ForEnumValueRequests()
        {
            // Arrange
            ODataPath   odataPath = new ODataPath(new ValueSegment(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Int32)));
            HttpRequest request   = GetRequest(_edmModel);

            request.ODataFeature().Path = odataPath;

            // Act
            ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(typeof(TestEnum), request);

            // Assert
            Assert.NotNull(serializer);
            var rawValueSerializer = Assert.IsType <ODataRawValueSerializer>(serializer);

            Assert.Equal(ODataPayloadKind.Value, rawValueSerializer.ODataPayloadKind);
        }
        /// <summary>
        /// Gets the serializer for the given result type.
        /// </summary>
        /// <param name="type">The type of result to serialize.</param>
        /// <param name="request">The HTTP request.</param>
        /// <returns>The serializer instance.</returns>
        public override ODataSerializer GetODataPayloadSerializer(
            Type type,
            HttpRequestMessage request)
        {
            ODataSerializer serializer = null;

            if (type.Name == "PrimitiveResult")
            {
                serializer = this.primitiveSerializer;
            }
            else
            {
                serializer = base.GetODataPayloadSerializer(type, request);
            }

            return(serializer);
        }
예제 #21
0
        /// <summary>
        /// Gets the serializer for the given result type.
        /// </summary>
        /// <param name="model">The EDM model.</param>
        /// <param name="type">The type of result to serialize.</param>
        /// <param name="request">The HTTP request.</param>
        /// <returns>The serializer instance.</returns>
        public override ODataSerializer GetODataPayloadSerializer(
            IEdmModel model,
            Type type,
            HttpRequestMessage request)
        {
            ODataSerializer serializer = base.GetODataPayloadSerializer(model, type, request);

            if (serializer == null)
            {
                if (type == typeof(EntityCollectionResult))
                {
                    serializer = this.feedSerializer;
                }
                else if (type == typeof(EntityResult))
                {
                    serializer = this.entityTypeSerializer;
                }
                else if (type == typeof(PrimitiveResult))
                {
                    serializer = this.primitiveSerializer;
                }
                else if (type == typeof(RawResult))
                {
                    serializer = this.rawSerializer;
                }
                else if (type == typeof(ComplexResult))
                {
                    serializer = this.complexTypeSerializer;
                }
                else if (type == typeof(NonEntityCollectionResult))
                {
                    serializer = this.collectionSerializer;
                }
                else if (type == typeof(EnumResult))
                {
                    serializer = this.enumSerializer;
                }
            }

            return(serializer);
        }
예제 #22
0
        /// <summary>
        /// Gets the serializer for the given result type.
        /// </summary>
        /// <param name="model">The EDM model.</param>
        /// <param name="type">The type of result to serialize.</param>
        /// <param name="request">The HTTP request.</param>
        /// <returns>The serializer instance.</returns>
        public override ODataSerializer GetODataPayloadSerializer(
            IEdmModel model,
            Type type,
            HttpRequestMessage request)
        {
            ODataSerializer serializer = base.GetODataPayloadSerializer(model, type, request);

            if (serializer == null)
            {
                if (type == typeof(EntityCollectionResult))
                {
                    serializer = this.feedSerializer;
                }
                else if (type == typeof(EntityResult))
                {
                    serializer = this.entityTypeSerializer;
                }
            }

            return(serializer);
        }
        /// <inheritdoc/>
        public override bool CanWriteType(Type type)
        {
            if (type == null)
            {
                throw Error.ArgumentNull("type");
            }

            if (_request != null)
            {
                IEdmModel model = _request.GetEdmModel();
                if (model != null)
                {
                    ODataSerializer serializer = _serializerProvider.GetODataPayloadSerializer(model, type);
                    if (serializer != null)
                    {
                        return(_payloadKinds.Contains(serializer.ODataPayloadKind));
                    }
                }
            }

            return(false);
        }
        private IEnumerable <KeyValuePair <string, string> > GetResponseMessageHeaders(Type graphType, ODataFormat odataFormat, ODataVersion version)
        {
            IODataResponseMessage responseMessage = new ODataMessageWrapper();

            ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings()
            {
                BaseUri = new Uri(ODataFormatterConstants.DefaultNamespace),
                Version = version,
                Indent  = false
            };

            writerSettings.SetContentType(odataFormat);
            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings))
            {
                ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(graphType);

                // get the OData specific headers for the payloadkind
                ODataUtils.SetHeadersForPayload(messageWriter, serializer.ODataPayloadKind);
            }

            return(responseMessage.Headers);
        }
예제 #25
0
        /// <summary>
        /// Gets the serializer for the given result type.
        /// </summary>
        /// <param name="type">The type of result to serialize.</param>
        /// <param name="request">The HTTP request.</param>
        /// <returns>The serializer instance.</returns>
        public override ODataSerializer GetODataPayloadSerializer(
            Type type,
            HttpRequestMessage request)
        {
            ODataSerializer serializer = null;

            if (type == typeof(ResourceSetResult))
            {
                serializer = this.resourceSetSerializer;
            }
            else if (type == typeof(PrimitiveResult))
            {
                serializer = this.primitiveSerializer;
            }
            else if (type == typeof(RawResult))
            {
                serializer = this.rawSerializer;
            }
            else if (type == typeof(ComplexResult))
            {
                serializer = this.resourceSerializer;
            }
            else if (type == typeof(NonResourceCollectionResult))
            {
                serializer = this.collectionSerializer;
            }
            else if (type == typeof(EnumResult))
            {
                serializer = this.enumSerializer;
            }
            else
            {
                serializer = base.GetODataPayloadSerializer(type, request);
            }

            return(serializer);
        }
예제 #26
0
        private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)
        {
            IEdmModel model = Request.ODataProperties().Model;

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

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

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

            ODataPath            path = Request.ODataProperties().Path;
            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;
            }

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

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

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

            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,
            };

            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.Feed,
                    Path               = path,
                    MetadataLevel      = ODataMediaTypes.GetMetadataLevel(contentType),
                    SelectExpandClause = Request.ODataProperties().SelectExpandClause
                };

                serializer.WriteObject(value, type, messageWriter, writeContext);
            }
        }
예제 #27
0
        internal static void WriteToStream(
            Type type,
            object value,
            IEdmModel model,
            ODataVersion version,
            Uri baseAddress,
            MediaTypeHeaderValue contentType,
            IWebApiUrlHelper internaUrlHelper,
            IWebApiRequestMessage internalRequest,
            IWebApiHeaders internalRequestHeaders,
            Func <IServiceProvider, ODataMessageWrapper> getODataMessageWrapper,
            Func <IEdmTypeReference, ODataSerializer> getEdmTypeSerializer,
            Func <Type, ODataSerializer> getODataPayloadSerializer,
            Func <ODataSerializerContext> getODataSerializerContext)
        {
            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

            ODataSerializer serializer = GetSerializer(type, value, internalRequest, getEdmTypeSerializer, getODataPayloadSerializer);

            ODataPath            path = internalRequest.Context.Path;
            IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource;

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

            if (!String.IsNullOrEmpty(preferHeader))
            {
                ODataMessageWrapper messageWrapper = getODataMessageWrapper(null);
                messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
            }

            IODataResponseMessage responseMessage = getODataMessageWrapper(internalRequest.RequestContainer);

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

            ODataMessageWriterSettings writerSettings = internalRequest.WriterSettings;

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

            string metadataLink = internaUrlHelper.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;

            if (internalRequest.Context.QueryOptions != null && internalRequest.Context.QueryOptions.SelectExpand != null)
            {
                if (internalRequest.Context.QueryOptions.SelectExpand.ProcessedSelectExpandClause != internalRequest.Context.ProcessedSelectExpandClause)
                {
                    selectExpandDifferentFromQueryOptions = internalRequest.Context.ProcessedSelectExpandClause;
                }
            }
            else if (internalRequest.Context.ProcessedSelectExpandClause != null)
            {
                selectExpandDifferentFromQueryOptions = internalRequest.Context.ProcessedSelectExpandClause;
            }

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

                SelectAndExpand = internalRequest.Context.ProcessedSelectExpandClause,
                Apply           = internalRequest.Context.ApplyClause,
                Path            = ConvertPath(path),
            };

            ODataMetadataLevel metadataLevel = ODataMetadataLevel.MinimalMetadata;

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

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model))
            {
                ODataSerializerContext writeContext = getODataSerializerContext();
                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  = internalRequest.Context.QueryOptions;

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

                serializer.WriteObject(value, type, messageWriter, writeContext);
            }
        }
예제 #28
0
 public static ODataSerializerProvider GetMockODataSerializerProvider(ODataSerializer serializer)
 {
     Mock<ODataSerializerProvider> serializerProvider = new Mock<ODataSerializerProvider>();
     serializerProvider.Setup(sp => sp.GetODataPayloadSerializer(It.IsAny<IEdmModel>(), It.IsAny<Type>(), It.IsAny<HttpRequestMessage>()))
         .Returns(serializer);
     return serializerProvider.Object;
 }
예제 #29
0
        private void WriteResponseBody(OutputFormatterWriteContext context)
        {
            HttpRequest  request  = context.HttpContext.Request;
            HttpResponse response = context.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.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(new MediaTypeHeaderValue(context.ContentType.Value)),
                    SelectExpandClause = request.ODataProperties().SelectExpandClause
                };

                serializer.WriteObject(value, type, messageWriter, writeContext);
            }
        }
        /// <summary>
        /// Read and serialize outgoing object to HTTP request stream.
        /// </summary>
        internal static void WriteToStream(
            Type type,
            object value,
            IEdmModel model,
            Uri baseAddress,
            MediaTypeHeaderValue contentType,
            IUrlHelper internalUrlHelper,
            HttpRequest internalRequest,
            IHeaderDictionary internalRequestHeaders,
            Func <IServiceProvider, ODataMigrationMessageWrapper> getODataMessageWrapper,
            Func <IEdmTypeReference, ODataSerializer> getEdmTypeSerializer,
            Func <Type, ODataSerializer> getODataPayloadSerializer,
            Func <ODataSerializerContext> getODataSerializerContext)
        {
            if (model == null)
            {
                throw new InvalidOperationException("Request must have model");
            }

            ODataSerializer serializer = GetSerializer(type, value, internalRequest, getEdmTypeSerializer, getODataPayloadSerializer);

            // special case: if the top level serializer is an ODataPrimitiveSerializer then swap it out for an ODataMigrationPrimitiveSerializer
            // This only applies to the top level because inline primitives are translated but top level primitives are not, unless we use a customized serializer.
            if (serializer is ODataPrimitiveSerializer)
            {
                serializer = new ODataMigrationPrimitiveSerializer();
            }

            ODataPath            path = internalRequest.ODataFeature().Path;
            IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource;

            // serialize a response
            string preferHeader     = GetRequestPreferHeader(internalRequestHeaders);
            string annotationFilter = null;

            if (!String.IsNullOrEmpty(preferHeader))
            {
                ODataMigrationMessageWrapper messageWrapper = getODataMessageWrapper(null);
                messageWrapper.SetHeader("Prefer", preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
            }

            ODataMigrationMessageWrapper responseMessageWrapper = getODataMessageWrapper(internalRequest.GetRequestContainer());
            IODataResponseMessage        responseMessage        = responseMessageWrapper;

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

            ODataMessageWriterSettings writerSettings = internalRequest.GetWriterSettings();

            writerSettings.BaseUri     = baseAddress;
            writerSettings.Version     = ODataVersion.V4; // Todo how to specify v3?  Maybe don't because reading as v4
            writerSettings.Validations = writerSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType;

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

            if (metadataLink == null)
            {
                throw new SerializationException("Unable to determine metadata url");
            }

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

                SelectAndExpand = internalRequest.ODataFeature()?.SelectExpandClause,
                Apply           = internalRequest.ODataFeature().ApplyClause,
                Path            = (path == null || IsOperationPath(path)) ? null : path.Path,
            };

            ODataMetadataLevel metadataLevel = ODataMetadataLevel.MinimalMetadata;

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

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

                // Substitute stream to swap @odata.context
                Stream substituteStream = new MemoryStream();
                Stream originalStream   = messageWriter.SubstituteResponseStream(substituteStream);

                serializer.WriteObject(value, type, messageWriter, writeContext);
                StreamReader reader = new StreamReader(substituteStream);
                substituteStream.Seek(0, SeekOrigin.Begin);
                JToken responsePayload = JToken.Parse(reader.ReadToEnd());

                // If odata context is present, replace with odata metadata
                if (responsePayload["@odata.context"] != null)
                {
                    responsePayload["odata.metadata"] = responsePayload["@odata.context"].ToString().Replace("$entity", "@Element");
                    ((JObject)responsePayload).Property("@odata.context").Remove();
                }

                // Write to actual stream
                // We cannot dispose of the stream because this method does not own the stream (subsequent methods will close the streamwriter)
                StreamWriter   streamWriter   = new StreamWriter(originalStream);
                JsonTextWriter writer         = new JsonTextWriter(streamWriter);
                JsonSerializer jsonSerializer = new JsonSerializer();
                jsonSerializer.Serialize(writer, responsePayload);
                writer.Flush();
                messageWriter.SubstituteResponseStream(originalStream);
            }
        }
        public async Task WriteJson(object value, Stream writeStream)
        {
            IEdmModel model = _odataProperties.Model;

            if (model == null)
            {
                throw new Exception("Microsoft.OData.Edm.Error.InvalidOperation(SRResources.RequestMustHaveModel)");
            }
            var type = value.GetType();

            type = _context.ObjectType;
            var pageResult = value as PageResult <object>;

            if (pageResult != null)
            {
                //value = pageResult.Items;
                type = pageResult.Items.GetType();
            }

            var urlHelper = UrlHelper(_context.HttpContext);
            var path      = Request.ODataFeature().Path;
            IEdmNavigationSource targetNavigationSource = path?.NavigationSource;

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

            // TODO: Fix this ffs...

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

            if (ODataCountMediaTypeMapping.IsCountRequest(Request.HttpContext))
            {
                Response.ContentType = "text/plain";
            }

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

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

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

            Uri baseAddress = GetBaseAddress();
            ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings()
            {
                BaseUri = baseAddress,
                Version = _version,
                //MessageWriterSettings
            };

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

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

            MediaTypeHeaderValue contentType = null;

            // TODO: Restore
            //if (contentHeaders != null && contentHeaders.ContentType != null)
            //{
            //	contentType = contentHeaders.ContentType;
            //}

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model))
            {
                ODataSerializer        serializer   = GetSerializer(type, value, model, _context.HttpContext.RequestServices.GetService <IODataSerializerProvider>());
                ODataSerializerContext writeContext = new ODataSerializerContext()
                {
                    Context          = _context.HttpContext,
                    Url              = urlHelper,
                    NavigationSource = targetNavigationSource,
                    Model            = model,
                    RootElementName  = GetRootElementName(path) ?? "root",
                    SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Collection,
                    Path               = path,
                    MetadataLevel      = ODataMediaTypes.GetMetadataLevel(contentType),
                    SelectExpandClause = Request.ODataFeature().SelectExpandClause
                };

                await serializer.WriteObjectAsync(value, type, messageWriter, writeContext);
            }
        }