mirror of https://github.com/abpframework/abp.git
23 changed files with 345 additions and 138 deletions
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> |
||||
|
<AssemblyName>Volo.Abp.AspNetCore.Mvc.NewtonsoftJson</AssemblyName> |
||||
|
<PackageId>Volo.Abp.AspNetCore.Mvc.NewtonsoftJson</PackageId> |
||||
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<IsPackable>true</IsPackable> |
||||
|
<OutputType>Library</OutputType> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(MicrosoftAspNetCorePackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,42 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Formatters; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using Microsoft.Extensions.ObjectPool; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Json; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.NewtonsoftJson; |
||||
|
|
||||
|
[DependsOn(typeof(AbpAspNetCoreMvcModule))] |
||||
|
public class AbpAspNetCoreMvcNewtonsoftModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var options = context.Services.ExecutePreConfiguredActions<AbpAspNetCoreMvcNewtonsoftOptions>(); |
||||
|
|
||||
|
if (options.UseHybridSerializer) |
||||
|
{ |
||||
|
context.Services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>(); |
||||
|
|
||||
|
Configure<MvcOptions>(mvcOptions => |
||||
|
{ |
||||
|
mvcOptions.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>(); |
||||
|
mvcOptions.OutputFormatters.RemoveType<NewtonsoftJsonOutputFormatter>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpHybridJsonFormatterOptions>(formatterOptions => |
||||
|
{ |
||||
|
formatterOptions.TextInputFormatters.Add<AbpNewtonsoftJsonFormatter>(); |
||||
|
formatterOptions.TextOutputFormatters.Add<AbpNewtonsoftJsonFormatter>(); |
||||
|
}); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
context.Services.AddMvcCore().AddNewtonsoftJson(); |
||||
|
} |
||||
|
|
||||
|
context.Services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<MvcNewtonsoftJsonOptions>, AbpMvcNewtonsoftJsonOptionsSetup>()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace Volo.Abp.AspNetCore.Mvc.NewtonsoftJson; |
||||
|
|
||||
|
public class AbpAspNetCoreMvcNewtonsoftOptions |
||||
|
{ |
||||
|
public bool UseHybridSerializer { get; set; } |
||||
|
|
||||
|
public AbpAspNetCoreMvcNewtonsoftOptions() |
||||
|
{ |
||||
|
UseHybridSerializer = true; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
using System; |
||||
|
using System.Buffers; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Formatters; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.ObjectPool; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Json; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.NewtonsoftJson; |
||||
|
|
||||
|
public class AbpNewtonsoftJsonFormatter : IAbpHybridJsonInputFormatter, IAbpHybridJsonOutputFormatter, ITransientDependency |
||||
|
{ |
||||
|
private readonly ILoggerFactory _loggerFactory; |
||||
|
private readonly ArrayPool<char> _charPool; |
||||
|
private readonly ObjectPoolProvider _objectPoolProvider; |
||||
|
private readonly IOptions<MvcOptions> _mvcOptions; |
||||
|
private readonly IOptions<MvcNewtonsoftJsonOptions> _mvcNewtonsoftJsonOptions; |
||||
|
|
||||
|
public AbpNewtonsoftJsonFormatter( |
||||
|
ILoggerFactory loggerFactory, |
||||
|
ArrayPool<char> charPool, |
||||
|
ObjectPoolProvider objectPoolProvider, |
||||
|
IOptions<MvcOptions> mvcOptions, |
||||
|
IOptions<MvcNewtonsoftJsonOptions> mvcNewtonsoftJsonOptions) |
||||
|
{ |
||||
|
_loggerFactory = loggerFactory; |
||||
|
_charPool = charPool; |
||||
|
_objectPoolProvider = objectPoolProvider; |
||||
|
_mvcOptions = mvcOptions; |
||||
|
_mvcNewtonsoftJsonOptions = mvcNewtonsoftJsonOptions; |
||||
|
} |
||||
|
|
||||
|
Task<bool> IAbpHybridJsonInputFormatter.CanHandleAsync(Type type) |
||||
|
{ |
||||
|
return Task.FromResult(true); |
||||
|
} |
||||
|
|
||||
|
public Task<TextInputFormatter> GetTextInputFormatterAsync() |
||||
|
{ |
||||
|
return Task.FromResult<TextInputFormatter>(new NewtonsoftJsonInputFormatter( |
||||
|
_loggerFactory.CreateLogger<NewtonsoftJsonInputFormatter>(), |
||||
|
_mvcNewtonsoftJsonOptions.Value.SerializerSettings, |
||||
|
_charPool, |
||||
|
_objectPoolProvider, |
||||
|
_mvcOptions.Value, |
||||
|
_mvcNewtonsoftJsonOptions.Value)); |
||||
|
} |
||||
|
|
||||
|
Task<bool> IAbpHybridJsonOutputFormatter.CanHandleAsync(Type type) |
||||
|
{ |
||||
|
return Task.FromResult(true); |
||||
|
} |
||||
|
|
||||
|
public Task<TextOutputFormatter> GetTextOutputFormatterAsync() |
||||
|
{ |
||||
|
return Task.FromResult<TextOutputFormatter>(new NewtonsoftJsonOutputFormatter( |
||||
|
_mvcNewtonsoftJsonOptions.Value.SerializerSettings, |
||||
|
_charPool, |
||||
|
_mvcOptions.Value, |
||||
|
_mvcNewtonsoftJsonOptions.Value)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc.Formatters; |
||||
|
using Volo.Abp.Collections; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.Json; |
||||
|
|
||||
|
public class AbpHybridJsonFormatterOptions |
||||
|
{ |
||||
|
public ITypeList<IAbpHybridJsonInputFormatter> TextInputFormatters { get; } |
||||
|
|
||||
|
public ITypeList<IAbpHybridJsonInputFormatter> TextOutputFormatters { get; } |
||||
|
|
||||
|
public AbpHybridJsonFormatterOptions() |
||||
|
{ |
||||
|
TextInputFormatters = new TypeList<IAbpHybridJsonInputFormatter>(); |
||||
|
TextOutputFormatters = new TypeList<IAbpHybridJsonInputFormatter>(); |
||||
|
} |
||||
|
} |
||||
@ -1,72 +0,0 @@ |
|||||
using System.Buffers; |
|
||||
using System.Text.Encodings.Web; |
|
||||
using System.Text.Json; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Microsoft.AspNetCore.Mvc.Formatters; |
|
||||
using Microsoft.Extensions.Logging; |
|
||||
using Microsoft.Extensions.ObjectPool; |
|
||||
using Microsoft.Extensions.Options; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.Json; |
|
||||
|
|
||||
public class AbpHybridJsonOptionsSetup : IConfigureOptions<MvcOptions> |
|
||||
{ |
|
||||
private readonly IOptions<JsonOptions> _jsonOptions; |
|
||||
private readonly IOptions<MvcNewtonsoftJsonOptions> _mvcNewtonsoftJsonOptions; |
|
||||
private readonly ILoggerFactory _loggerFactory; |
|
||||
private readonly ArrayPool<char> _charPool; |
|
||||
private readonly ObjectPoolProvider _objectPoolProvider; |
|
||||
|
|
||||
public AbpHybridJsonOptionsSetup( |
|
||||
IOptions<JsonOptions> jsonOptions, |
|
||||
IOptions<MvcNewtonsoftJsonOptions> mvcNewtonsoftJsonOptions, |
|
||||
ILoggerFactory loggerFactory, |
|
||||
ArrayPool<char> charPool, |
|
||||
ObjectPoolProvider objectPoolProvider) |
|
||||
{ |
|
||||
_jsonOptions = jsonOptions; |
|
||||
_mvcNewtonsoftJsonOptions = mvcNewtonsoftJsonOptions; |
|
||||
_loggerFactory = loggerFactory; |
|
||||
_charPool = charPool; |
|
||||
_objectPoolProvider = objectPoolProvider; |
|
||||
} |
|
||||
|
|
||||
public void Configure(MvcOptions options) |
|
||||
{ |
|
||||
var systemTextJsonInputFormatter = new SystemTextJsonInputFormatter( |
|
||||
_jsonOptions.Value, |
|
||||
_loggerFactory.CreateLogger<SystemTextJsonInputFormatter>()); |
|
||||
|
|
||||
var newtonsoftJsonInputFormatter = new NewtonsoftJsonInputFormatter( |
|
||||
_loggerFactory.CreateLogger<NewtonsoftJsonInputFormatter>(), |
|
||||
_mvcNewtonsoftJsonOptions.Value.SerializerSettings, |
|
||||
_charPool, |
|
||||
_objectPoolProvider, |
|
||||
options, |
|
||||
_mvcNewtonsoftJsonOptions.Value); |
|
||||
|
|
||||
options.InputFormatters.RemoveType<SystemTextJsonInputFormatter>(); |
|
||||
options.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>(); |
|
||||
options.InputFormatters.Add(new AbpHybridJsonInputFormatter(systemTextJsonInputFormatter, newtonsoftJsonInputFormatter)); |
|
||||
|
|
||||
var jsonSerializerOptions = _jsonOptions.Value.JsonSerializerOptions; |
|
||||
if (jsonSerializerOptions.Encoder is null) |
|
||||
{ |
|
||||
// If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters.
|
|
||||
jsonSerializerOptions = new JsonSerializerOptions(jsonSerializerOptions) |
|
||||
{ |
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
var systemTextJsonOutputFormatter = new SystemTextJsonOutputFormatter(jsonSerializerOptions); |
|
||||
var newtonsoftJsonOutputFormatter = new NewtonsoftJsonOutputFormatter( |
|
||||
_mvcNewtonsoftJsonOptions.Value.SerializerSettings, |
|
||||
_charPool, |
|
||||
options); |
|
||||
|
|
||||
options.OutputFormatters.RemoveType<SystemTextJsonOutputFormatter>(); |
|
||||
options.OutputFormatters.RemoveType<NewtonsoftJsonOutputFormatter>(); |
|
||||
options.OutputFormatters.Add(new AbpHybridJsonOutputFormatter(systemTextJsonOutputFormatter, newtonsoftJsonOutputFormatter)); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,60 @@ |
|||||
|
using System; |
||||
|
using System.Text.Encodings.Web; |
||||
|
using System.Text.Json; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Formatters; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Json.SystemTextJson; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.Json; |
||||
|
|
||||
|
public class AbpSystemTextJsonFormatter : IAbpHybridJsonInputFormatter, IAbpHybridJsonOutputFormatter, ITransientDependency |
||||
|
{ |
||||
|
private readonly AbpSystemTextJsonUnsupportedTypeMatcher _unsupportedTypeMatcher; |
||||
|
private readonly IOptions<JsonOptions> _jsonOptions; |
||||
|
private readonly ILoggerFactory _loggerFactory; |
||||
|
|
||||
|
public AbpSystemTextJsonFormatter(AbpSystemTextJsonUnsupportedTypeMatcher unsupportedTypeMatcher, |
||||
|
IOptions<JsonOptions> jsonOptions, |
||||
|
ILoggerFactory loggerFactory) |
||||
|
{ |
||||
|
_unsupportedTypeMatcher = unsupportedTypeMatcher; |
||||
|
_jsonOptions = jsonOptions; |
||||
|
_loggerFactory = loggerFactory; |
||||
|
} |
||||
|
|
||||
|
Task<bool> IAbpHybridJsonInputFormatter.CanHandleAsync(Type type) |
||||
|
{ |
||||
|
return Task.FromResult(!_unsupportedTypeMatcher.Match(type)); |
||||
|
} |
||||
|
|
||||
|
public virtual Task<TextInputFormatter> GetTextInputFormatterAsync() |
||||
|
{ |
||||
|
return Task.FromResult<TextInputFormatter>(new SystemTextJsonInputFormatter( |
||||
|
_jsonOptions.Value, |
||||
|
_loggerFactory.CreateLogger<SystemTextJsonInputFormatter>())); |
||||
|
} |
||||
|
|
||||
|
Task<bool> IAbpHybridJsonOutputFormatter.CanHandleAsync(Type type) |
||||
|
{ |
||||
|
return Task.FromResult(!_unsupportedTypeMatcher.Match(type)); |
||||
|
} |
||||
|
|
||||
|
public Task<TextOutputFormatter> GetTextOutputFormatterAsync() |
||||
|
{ |
||||
|
var jsonSerializerOptions = _jsonOptions.Value.JsonSerializerOptions; |
||||
|
if (jsonSerializerOptions.Encoder is null) |
||||
|
{ |
||||
|
// If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters.
|
||||
|
jsonSerializerOptions = new JsonSerializerOptions(jsonSerializerOptions) |
||||
|
{ |
||||
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
return Task.FromResult<TextOutputFormatter>(new SystemTextJsonOutputFormatter(jsonSerializerOptions)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc.Formatters; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.Json; |
||||
|
|
||||
|
public interface IAbpHybridJsonInputFormatter |
||||
|
{ |
||||
|
Task<bool> CanHandleAsync(Type type); |
||||
|
|
||||
|
Task<TextInputFormatter> GetTextInputFormatterAsync(); |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc.Formatters; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.Json; |
||||
|
|
||||
|
public interface IAbpHybridJsonOutputFormatter |
||||
|
{ |
||||
|
Task<bool> CanHandleAsync(Type type); |
||||
|
|
||||
|
Task<TextOutputFormatter> GetTextOutputFormatterAsync(); |
||||
|
} |
||||
Loading…
Reference in new issue