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