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);
                    }
                }
            }));
        }
Exemple #2
0
        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");
            }

            if (Request == null)
            {
                throw Error.NotSupported(SRResources.WriteToStreamAsyncMustHaveRequest);
            }

            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;
                if (contentHeaders == null)
                {
                    version = _defaultODataVersion;
                }
                else
                {
                    version = GetODataVersion(contentHeaders, ODataFormatterConstants.ODataServiceVersion) ?? _defaultODataVersion;
                }

                // get the most appropriate serializer given that we support inheritance.
                type = value == null ? type : value.GetType();
                ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(type);
                if (serializer == null)
                {
                    throw Error.InvalidOperation(SRResources.TypeCannotBeSerialized, type.Name, typeof(ODataMediaTypeFormatter).Name);
                }

                UrlHelper urlHelper = Request.GetUrlHelper();

                IEdmEntitySet targetEntitySet = null;
                ODataUriHelpers.TryGetEntitySetAndEntityType(Request.RequestUri, Model, out 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);

                // TODO: Issue 483: http://aspnetwebstack.codeplex.com/workitem/483
                // We need to set the MetadataDocumentUri when this property is added to ODataMessageWriterSettings as
                // part of the JSON Light work.
                // This is required so ODataLib can coerce AbsoluteUri's into RelativeUri's when appropriate in JSON Light.
                ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings()
                {
                    BaseUri = baseAddress,
                    Version = version,
                    Indent = true,
                    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))
                {
                    ODataSerializerContext writeContext = new ODataSerializerContext()
                    {
                        EntitySet = targetEntitySet,
                        UrlHelper = urlHelper,
                        ServiceOperationName = operationName,
                        SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed,
                        Request = Request
                    };

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