/// <summary> /// Gets the type to which the XML will be deserialized. /// </summary> /// <param name="declaredType">The declared type.</param> /// <returns>The type to which the XML will be deserialized.</returns> protected virtual Type GetSerializableType([NotNull] Type declaredType) { var wrapperProvider = WrapperProviderFactories.GetWrapperProvider( new WrapperProviderContext(declaredType, isSerialization: false)); return(wrapperProvider?.WrappingType ?? declaredType); }
/// <inheritdoc /> public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context) { var tempWriterSettings = WriterSettings.Clone(); tempWriterSettings.Encoding = context.SelectedEncoding; using (var xmlWriter = CreateXmlWriter(context.HttpContext.Response.Body, tempWriterSettings)) { var obj = context.Object; var runtimeType = obj?.GetType(); var resolvedType = ResolveType(context.DeclaredType, runtimeType); var wrappingType = GetSerializableType(resolvedType); // Wrap the object only if there is a wrapping type. if (wrappingType != null && wrappingType != resolvedType) { var wrapperProvider = WrapperProviderFactories.GetWrapperProvider( new WrapperProviderContext( declaredType: resolvedType, isSerialization: true)); obj = wrapperProvider.Wrap(obj); } var dataContractSerializer = GetCachedSerializer(wrappingType); dataContractSerializer.WriteObject(xmlWriter, obj); } return(Task.FromResult(true)); }
/// <summary> /// Gets the type to be serialized. /// </summary> /// <param name="type">The original type to be serialized</param> /// <returns>The original or wrapped type provided by any <see cref="IWrapperProvider"/>s.</returns> protected virtual Type GetSerializableType(Type type) { var wrapperProvider = WrapperProviderFactories.GetWrapperProvider( new WrapperProviderContext(type, isSerialization: true)); return(wrapperProvider?.WrappingType ?? type); }
/// <summary> /// Gets the type to which the XML will be deserialized. /// </summary> /// <param name="declaredType">The declared type.</param> /// <returns>The type to which the XML will be deserialized.</returns> protected virtual Type GetSerializableType(Type declaredType) { if (declaredType == null) { throw new ArgumentNullException(nameof(declaredType)); } var wrapperProvider = WrapperProviderFactories.GetWrapperProvider( new WrapperProviderContext(declaredType, isSerialization: false)); return(wrapperProvider?.WrappingType ?? declaredType); }
/// <inheritdoc /> public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (selectedEncoding == null) { throw new ArgumentNullException(nameof(selectedEncoding)); } var writerSettings = WriterSettings.Clone(); writerSettings.Encoding = selectedEncoding; // Wrap the object only if there is a wrapping type. var value = context.Object; var wrappingType = GetSerializableType(context.ObjectType); if (wrappingType != null && wrappingType != context.ObjectType) { var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext( declaredType: context.ObjectType, isSerialization: true)); value = wrapperProvider.Wrap(value); } var xmlSerializer = GetCachedSerializer(wrappingType); // Opt into sync IO support until we can work out an alternative https://github.com/aspnet/AspNetCore/issues/6397 var syncIOFeature = context.HttpContext.Features.Get <Http.Features.IHttpBodyControlFeature>(); if (syncIOFeature != null) { syncIOFeature.AllowSynchronousIO = true; } using (var textWriter = context.WriterFactory(context.HttpContext.Response.Body, writerSettings.Encoding)) { using (var xmlWriter = CreateXmlWriter(context, textWriter, writerSettings)) { Serialize(xmlSerializer, xmlWriter, value); } // Perf: call FlushAsync to call WriteAsync on the stream with any content left in the TextWriter's // buffers. This is better than just letting dispose handle it (which would result in a synchronous // write). await textWriter.FlushAsync(); } }
/// <inheritdoc /> public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (selectedEncoding == null) { throw new ArgumentNullException(nameof(selectedEncoding)); } var response = context.HttpContext.Response; var writerSettings = WriterSettings.Clone(); writerSettings.Encoding = selectedEncoding; // Wrap the object only if there is a wrapping type. var value = context.Object; var wrappingType = GetSerializableType(context.ObjectType); if (wrappingType != null && wrappingType != context.ObjectType) { var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext( declaredType: context.ObjectType, isSerialization: true)); value = wrapperProvider.Wrap(value); } var xmlSerializer = GetCachedSerializer(wrappingType); using (var textWriter = context.WriterFactory(context.HttpContext.Response.Body, writerSettings.Encoding)) { using (var xmlWriter = CreateXmlWriter(textWriter, writerSettings)) { xmlSerializer.Serialize(xmlWriter, value); } // Perf: call FlushAsync to call WriteAsync on the stream with any content left in the TextWriter's // buffers. This is better than just letting dispose handle it (which would result in a synchronous // write). await textWriter.FlushAsync(); } }
/// <summary> /// Initializes a new instance of <see cref="XmlSerializerOutputFormatter"/> /// </summary> /// <param name="writerSettings">The settings to be used by the <see cref="XmlSerializer"/>.</param> /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param> public XmlSerializerOutputFormatter(XmlWriterSettings writerSettings, ILoggerFactory loggerFactory) { if (writerSettings == null) { throw new ArgumentNullException(nameof(writerSettings)); } SupportedEncodings.Add(Encoding.UTF8); SupportedEncodings.Add(Encoding.Unicode); SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationXml); SupportedMediaTypes.Add(MediaTypeHeaderValues.TextXml); SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationAnyXmlSyntax); WriterSettings = writerSettings; WrapperProviderFactories = WrapperProviderFactoriesExtensions.GetDefaultProviderFactories(); WrapperProviderFactories.Add(new EnumerableWrapperProviderFactory(WrapperProviderFactories)); _logger = loggerFactory?.CreateLogger(GetType()); }
/// <inheritdoc /> public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var response = context.HttpContext.Response; var writerSettings = WriterSettings.Clone(); writerSettings.Encoding = context.ContentType.Encoding ?? Encoding.UTF8; // Wrap the object only if there is a wrapping type. var value = context.Object; var wrappingType = GetSerializableType(context.ObjectType); if (wrappingType != null && wrappingType != context.ObjectType) { var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext( declaredType: context.ObjectType, isSerialization: true)); value = wrapperProvider.Wrap(value); } var xmlSerializer = GetCachedSerializer(wrappingType); using (var textWriter = context.WriterFactory(context.HttpContext.Response.Body, writerSettings.Encoding)) { using (var xmlWriter = CreateXmlWriter(textWriter, writerSettings)) { xmlSerializer.Serialize(xmlWriter, value); } } return(TaskCache.CompletedTask); }
/// <inheritdoc /> public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (selectedEncoding == null) { throw new ArgumentNullException(nameof(selectedEncoding)); } var writerSettings = WriterSettings.Clone(); writerSettings.Encoding = selectedEncoding; var httpContext = context.HttpContext; var response = httpContext.Response; _mvcOptions ??= httpContext.RequestServices.GetRequiredService <IOptions <MvcOptions> >().Value; _asyncEnumerableReaderFactory ??= new AsyncEnumerableReader(_mvcOptions); var value = context.Object; var valueType = context.ObjectType !; if (value is not null && _asyncEnumerableReaderFactory.TryGetReader(value.GetType(), out var reader)) { Log.BufferingAsyncEnumerable(_logger, value); value = await reader(value); valueType = value.GetType(); } // Wrap the object only if there is a wrapping type. var wrappingType = GetSerializableType(valueType); if (wrappingType != null && wrappingType != valueType) { var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext( declaredType: valueType, isSerialization: true)); Debug.Assert(wrapperProvider is not null); value = wrapperProvider.Wrap(value); } var xmlSerializer = GetCachedSerializer(wrappingType !); var responseStream = response.Body; FileBufferingWriteStream?fileBufferingWriteStream = null; if (!_mvcOptions.SuppressOutputFormatterBuffering) { fileBufferingWriteStream = new FileBufferingWriteStream(); responseStream = fileBufferingWriteStream; } try { await using (var textWriter = context.WriterFactory(responseStream, selectedEncoding)) { using var xmlWriter = CreateXmlWriter(context, textWriter, writerSettings); Serialize(xmlSerializer, xmlWriter, value); } if (fileBufferingWriteStream != null) { response.ContentLength = fileBufferingWriteStream.Length; await fileBufferingWriteStream.DrainBufferAsync(response.BodyWriter); } } finally { if (fileBufferingWriteStream != null) { await fileBufferingWriteStream.DisposeAsync(); } } }