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