diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index 82f67fe15c..b646c5f9e6 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -415,6 +415,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.SystemTextJso
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.Core", "src\Volo.Abp.Json.Core\Volo.Abp.Json.Core.csproj", "{08531C5D-0436-4721-986D-96446CF54316}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.NewtonsoftJson", "src\Volo.Abp.AspNetCore.Mvc.NewtonsoftJson\Volo.Abp.AspNetCore.Mvc.NewtonsoftJson.csproj", "{0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1237,6 +1239,10 @@ Global
{08531C5D-0436-4721-986D-96446CF54316}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08531C5D-0436-4721-986D-96446CF54316}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08531C5D-0436-4721-986D-96446CF54316}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1446,6 +1452,7 @@ Global
{9DD41C8F-0886-483C-B98B-C55EAA7F226D} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{0AD06E14-CBFE-4551-8D18-9E921D8F2A87} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{08531C5D-0436-4721-986D-96446CF54316} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xml b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xml
new file mode 100644
index 0000000000..bc5a74a236
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xsd b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xsd
new file mode 100644
index 0000000000..3f3946e282
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson.csproj
new file mode 100644
index 0000000000..9e8b8951e3
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson.csproj
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+ net6.0
+ true
+ Volo.Abp.AspNetCore.Mvc.NewtonsoftJson
+ Volo.Abp.AspNetCore.Mvc.NewtonsoftJson
+ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ false
+ false
+ false
+ true
+ Library
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs
new file mode 100644
index 0000000000..ccf25979db
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs
@@ -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();
+
+ if (options.UseHybridSerializer)
+ {
+ context.Services.TryAddSingleton();
+
+ Configure(mvcOptions =>
+ {
+ mvcOptions.InputFormatters.RemoveType();
+ mvcOptions.OutputFormatters.RemoveType();
+ });
+
+ Configure(formatterOptions =>
+ {
+ formatterOptions.TextInputFormatters.Add();
+ formatterOptions.TextOutputFormatters.Add();
+ });
+ }
+ else
+ {
+ context.Services.AddMvcCore().AddNewtonsoftJson();
+ }
+
+ context.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpMvcNewtonsoftJsonOptionsSetup>());
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftOptions.cs
new file mode 100644
index 0000000000..63d11b00b7
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftOptions.cs
@@ -0,0 +1,11 @@
+namespace Volo.Abp.AspNetCore.Mvc.NewtonsoftJson;
+
+public class AbpAspNetCoreMvcNewtonsoftOptions
+{
+ public bool UseHybridSerializer { get; set; }
+
+ public AbpAspNetCoreMvcNewtonsoftOptions()
+ {
+ UseHybridSerializer = true;
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpMvcNewtonsoftJsonOptionsSetup.cs
similarity index 83%
rename from framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs
rename to framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpMvcNewtonsoftJsonOptionsSetup.cs
index c68b912372..1d1dc6a373 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpMvcNewtonsoftJsonOptionsSetup.cs
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
-namespace Volo.Abp.AspNetCore.Mvc.Json;
+namespace Volo.Abp.AspNetCore.Mvc.NewtonsoftJson;
public class AbpMvcNewtonsoftJsonOptionsSetup : IConfigureOptions
{
@@ -16,6 +16,6 @@ public class AbpMvcNewtonsoftJsonOptionsSetup : IConfigureOptions();
+ options.SerializerSettings.ContractResolver = ServiceProvider.GetRequiredService();
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpNewtonsoftJsonContractResolver.cs
similarity index 85%
rename from framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs
rename to framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpNewtonsoftJsonContractResolver.cs
index a6f242d59c..f33c9abbd4 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpNewtonsoftJsonContractResolver.cs
@@ -8,13 +8,13 @@ using Volo.Abp.Json.Newtonsoft;
using Volo.Abp.Reflection;
using Volo.Abp.Timing;
-namespace Volo.Abp.AspNetCore.Mvc.Json;
+namespace Volo.Abp.AspNetCore.Mvc.NewtonsoftJson;
-public class AbpMvcJsonContractResolver : DefaultContractResolver, ITransientDependency
+public class AbpNewtonsoftJsonContractResolver : DefaultContractResolver, ITransientDependency
{
private readonly Lazy _dateTimeConverter;
- public AbpMvcJsonContractResolver(IServiceProvider serviceProvider)
+ public AbpNewtonsoftJsonContractResolver(IServiceProvider serviceProvider)
{
_dateTimeConverter = new Lazy(
serviceProvider.GetRequiredService,
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpNewtonsoftJsonFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpNewtonsoftJsonFormatter.cs
new file mode 100644
index 0000000000..aa411bfb61
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpNewtonsoftJsonFormatter.cs
@@ -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 _charPool;
+ private readonly ObjectPoolProvider _objectPoolProvider;
+ private readonly IOptions _mvcOptions;
+ private readonly IOptions _mvcNewtonsoftJsonOptions;
+
+ public AbpNewtonsoftJsonFormatter(
+ ILoggerFactory loggerFactory,
+ ArrayPool charPool,
+ ObjectPoolProvider objectPoolProvider,
+ IOptions mvcOptions,
+ IOptions mvcNewtonsoftJsonOptions)
+ {
+ _loggerFactory = loggerFactory;
+ _charPool = charPool;
+ _objectPoolProvider = objectPoolProvider;
+ _mvcOptions = mvcOptions;
+ _mvcNewtonsoftJsonOptions = mvcNewtonsoftJsonOptions;
+ }
+
+ Task IAbpHybridJsonInputFormatter.CanHandleAsync(Type type)
+ {
+ return Task.FromResult(true);
+ }
+
+ public Task GetTextInputFormatterAsync()
+ {
+ return Task.FromResult(new NewtonsoftJsonInputFormatter(
+ _loggerFactory.CreateLogger(),
+ _mvcNewtonsoftJsonOptions.Value.SerializerSettings,
+ _charPool,
+ _objectPoolProvider,
+ _mvcOptions.Value,
+ _mvcNewtonsoftJsonOptions.Value));
+ }
+
+ Task IAbpHybridJsonOutputFormatter.CanHandleAsync(Type type)
+ {
+ return Task.FromResult(true);
+ }
+
+ public Task GetTextOutputFormatterAsync()
+ {
+ return Task.FromResult(new NewtonsoftJsonOutputFormatter(
+ _mvcNewtonsoftJsonOptions.Value.SerializerSettings,
+ _charPool,
+ _mvcOptions.Value,
+ _mvcNewtonsoftJsonOptions.Value));
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
index 9113c4529e..048c2308e7 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
@@ -29,7 +29,6 @@
-
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonFormatterOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonFormatterOptions.cs
new file mode 100644
index 0000000000..066ebe4413
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonFormatterOptions.cs
@@ -0,0 +1,17 @@
+using Microsoft.AspNetCore.Mvc.Formatters;
+using Volo.Abp.Collections;
+
+namespace Volo.Abp.AspNetCore.Mvc.Json;
+
+public class AbpHybridJsonFormatterOptions
+{
+ public ITypeList TextInputFormatters { get; }
+
+ public ITypeList TextOutputFormatters { get; }
+
+ public AbpHybridJsonFormatterOptions()
+ {
+ TextInputFormatters = new TypeList();
+ TextOutputFormatters = new TypeList();
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs
index 69da26a317..874508ac1f 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs
@@ -1,21 +1,16 @@
-using System.Text;
+using System;
+using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
-using Volo.Abp.Json.SystemTextJson;
+using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public class AbpHybridJsonInputFormatter : TextInputFormatter, IInputFormatterExceptionPolicy
{
- private readonly SystemTextJsonInputFormatter _systemTextJsonInputFormatter;
- private readonly NewtonsoftJsonInputFormatter _newtonsoftJsonInputFormatter;
-
- public AbpHybridJsonInputFormatter(SystemTextJsonInputFormatter systemTextJsonInputFormatter, NewtonsoftJsonInputFormatter newtonsoftJsonInputFormatter)
+ public AbpHybridJsonInputFormatter()
{
- _systemTextJsonInputFormatter = systemTextJsonInputFormatter;
- _newtonsoftJsonInputFormatter = newtonsoftJsonInputFormatter;
-
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
SupportedEncodings.Add(UTF16EncodingLittleEndian);
@@ -24,21 +19,25 @@ public class AbpHybridJsonInputFormatter : TextInputFormatter, IInputFormatterEx
SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationAnyJsonSyntax);
}
- public override async Task ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
+ public async override Task ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
{
- return await GetTextInputFormatter(context).ReadRequestBodyAsync(context, encoding);
+ return await (await GetTextInputFormatterAsync(context)).ReadRequestBodyAsync(context, encoding);
}
- protected virtual TextInputFormatter GetTextInputFormatter(InputFormatterContext context)
+ protected virtual async Task GetTextInputFormatterAsync(InputFormatterContext context)
{
- var typesMatcher = context.HttpContext.RequestServices.GetRequiredService();
+ var options = context.HttpContext.RequestServices.GetRequiredService>().Value;
- if (!typesMatcher.Match(context.ModelType))
+ foreach (var inputFormatterType in options.TextInputFormatters)
{
- return _systemTextJsonInputFormatter;
+ var inputFormatter = context.HttpContext.RequestServices.GetRequiredService(inputFormatterType).As();
+ if (await inputFormatter.CanHandleAsync(context.ModelType))
+ {
+ return await inputFormatter.GetTextInputFormatterAsync();
+ }
}
- return _newtonsoftJsonInputFormatter;
+ throw new AbpException($"The {nameof(AbpHybridJsonInputFormatter)} can't handle '{context.ModelType.GetFullNameWithAssemblyName()}'!");
}
public virtual InputFormatterExceptionPolicy ExceptionPolicy => InputFormatterExceptionPolicy.MalformedInputExceptions;
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOptionsSetup.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOptionsSetup.cs
deleted file mode 100644
index 794bc79af9..0000000000
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOptionsSetup.cs
+++ /dev/null
@@ -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
-{
- private readonly IOptions _jsonOptions;
- private readonly IOptions _mvcNewtonsoftJsonOptions;
- private readonly ILoggerFactory _loggerFactory;
- private readonly ArrayPool _charPool;
- private readonly ObjectPoolProvider _objectPoolProvider;
-
- public AbpHybridJsonOptionsSetup(
- IOptions jsonOptions,
- IOptions mvcNewtonsoftJsonOptions,
- ILoggerFactory loggerFactory,
- ArrayPool 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());
-
- var newtonsoftJsonInputFormatter = new NewtonsoftJsonInputFormatter(
- _loggerFactory.CreateLogger(),
- _mvcNewtonsoftJsonOptions.Value.SerializerSettings,
- _charPool,
- _objectPoolProvider,
- options,
- _mvcNewtonsoftJsonOptions.Value);
-
- options.InputFormatters.RemoveType();
- options.InputFormatters.RemoveType();
- 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();
- options.OutputFormatters.RemoveType();
- options.OutputFormatters.Add(new AbpHybridJsonOutputFormatter(systemTextJsonOutputFormatter, newtonsoftJsonOutputFormatter));
- }
-}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs
index f4c5df1dc9..2960ff1635 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs
@@ -1,21 +1,16 @@
-using System.Text;
+using System;
+using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
-using Volo.Abp.Json.SystemTextJson;
+using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public class AbpHybridJsonOutputFormatter : TextOutputFormatter
{
- private readonly SystemTextJsonOutputFormatter _systemTextJsonOutputFormatter;
- private readonly NewtonsoftJsonOutputFormatter _newtonsoftJsonOutputFormatter;
-
- public AbpHybridJsonOutputFormatter(SystemTextJsonOutputFormatter systemTextJsonOutputFormatter, NewtonsoftJsonOutputFormatter newtonsoftJsonOutputFormatter)
+ public AbpHybridJsonOutputFormatter()
{
- _systemTextJsonOutputFormatter = systemTextJsonOutputFormatter;
- _newtonsoftJsonOutputFormatter = newtonsoftJsonOutputFormatter;
-
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
@@ -24,19 +19,24 @@ public class AbpHybridJsonOutputFormatter : TextOutputFormatter
SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationAnyJsonSyntax);
}
- public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
+ public async override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
- await GetTextInputFormatter(context).WriteResponseBodyAsync(context, selectedEncoding);
+ await (await GetTextInputFormatter(context)).WriteResponseBodyAsync(context, selectedEncoding);
}
- protected virtual TextOutputFormatter GetTextInputFormatter(OutputFormatterWriteContext context)
+ protected virtual async Task GetTextInputFormatter(OutputFormatterWriteContext context)
{
- var typesMatcher = context.HttpContext.RequestServices.GetRequiredService();
- if (!typesMatcher.Match(context.ObjectType))
+ var options = context.HttpContext.RequestServices.GetRequiredService>().Value;
+
+ foreach (var outputFormatterType in options.TextOutputFormatters)
{
- return _systemTextJsonOutputFormatter;
+ var outputFormatter = context.HttpContext.RequestServices.GetRequiredService(outputFormatterType).As();
+ if (await outputFormatter.CanHandleAsync(context.ObjectType))
+ {
+ return await outputFormatter.GetTextOutputFormatterAsync();
+ }
}
- return _newtonsoftJsonOutputFormatter;
+ throw new AbpException($"The {nameof(AbpHybridJsonOutputFormatter)} can't handle '{context.ObjectType.GetFullNameWithAssemblyName()}'!");
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpSystemTextJsonFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpSystemTextJsonFormatter.cs
new file mode 100644
index 0000000000..e680d54fa5
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpSystemTextJsonFormatter.cs
@@ -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;
+ private readonly ILoggerFactory _loggerFactory;
+
+ public AbpSystemTextJsonFormatter(AbpSystemTextJsonUnsupportedTypeMatcher unsupportedTypeMatcher,
+ IOptions jsonOptions,
+ ILoggerFactory loggerFactory)
+ {
+ _unsupportedTypeMatcher = unsupportedTypeMatcher;
+ _jsonOptions = jsonOptions;
+ _loggerFactory = loggerFactory;
+ }
+
+ Task IAbpHybridJsonInputFormatter.CanHandleAsync(Type type)
+ {
+ return Task.FromResult(!_unsupportedTypeMatcher.Match(type));
+ }
+
+ public virtual Task GetTextInputFormatterAsync()
+ {
+ return Task.FromResult(new SystemTextJsonInputFormatter(
+ _jsonOptions.Value,
+ _loggerFactory.CreateLogger()));
+ }
+
+ Task IAbpHybridJsonOutputFormatter.CanHandleAsync(Type type)
+ {
+ return Task.FromResult(!_unsupportedTypeMatcher.Match(type));
+ }
+
+ public Task 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(new SystemTextJsonOutputFormatter(jsonSerializerOptions));
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/IAbpHybridJsonInputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/IAbpHybridJsonInputFormatter.cs
new file mode 100644
index 0000000000..0a167e58d4
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/IAbpHybridJsonInputFormatter.cs
@@ -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 CanHandleAsync(Type type);
+
+ Task GetTextInputFormatterAsync();
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/IAbpHybridJsonOutputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/IAbpHybridJsonOutputFormatter.cs
new file mode 100644
index 0000000000..06418b88d4
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/IAbpHybridJsonOutputFormatter.cs
@@ -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 CanHandleAsync(Type type);
+
+ Task GetTextOutputFormatterAsync();
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs
index 2d3a834d09..39a4e0670a 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs
@@ -1,9 +1,8 @@
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
-using Microsoft.Extensions.ObjectPool;
-using Volo.Abp.Json;
namespace Volo.Abp.AspNetCore.Mvc.Json;
@@ -11,18 +10,23 @@ public static class MvcCoreBuilderExtensions
{
public static IMvcCoreBuilder AddAbpHybridJson(this IMvcCoreBuilder builder)
{
- var abpJsonOptions = builder.Services.ExecutePreConfiguredActions();
- if (!abpJsonOptions.UseHybridSerializer)
+ builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpJsonOptionsSetup>());
+
+ builder.Services.Configure(options =>
{
- builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpMvcNewtonsoftJsonOptionsSetup>());
- builder.AddNewtonsoftJson();
- return builder;
- }
+ options.InputFormatters.RemoveType();
+ options.InputFormatters.Add(new AbpHybridJsonInputFormatter());
+
+ options.OutputFormatters.RemoveType();
+ options.OutputFormatters.Add(new AbpHybridJsonOutputFormatter());
+ });
+
+ builder.Services.Configure(options =>
+ {
+ options.TextInputFormatters.Add();
+ options.TextOutputFormatters.Add();
+ });
- builder.Services.TryAddTransient();
- builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpJsonOptionsSetup>());
- builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpMvcNewtonsoftJsonOptionsSetup>());
- builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpHybridJsonOptionsSetup>());
return builder;
}
}
diff --git a/framework/src/Volo.Abp.Json.Core/Volo/Abp/Json/AbpJsonOptions.cs b/framework/src/Volo.Abp.Json.Core/Volo/Abp/Json/AbpJsonOptions.cs
index 73b1d4506d..ffbd510b93 100644
--- a/framework/src/Volo.Abp.Json.Core/Volo/Abp/Json/AbpJsonOptions.cs
+++ b/framework/src/Volo.Abp.Json.Core/Volo/Abp/Json/AbpJsonOptions.cs
@@ -9,17 +9,10 @@ public class AbpJsonOptions
///
public string DefaultDateTimeFormat { get; set; }
- ///
- /// It will try to use System.Json.Text to handle JSON if it can otherwise use Newtonsoft.
- /// Affects both AbpJsonModule and AbpAspNetCoreMvcModule.
- ///
- public bool UseHybridSerializer { get; set; }
-
public ITypeList Providers { get; }
public AbpJsonOptions()
{
Providers = new TypeList();
- UseHybridSerializer = true;
}
}
diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
index 4b15408b51..895c9bcfe4 100644
--- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
+++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
@@ -11,16 +11,11 @@ public class AbpJsonSystemTextJsonModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
- context.Services.TryAddEnumerable(ServiceDescriptor
- .Transient, AbpSystemTextJsonSerializerOptionsSetup>());
+ context.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpSystemTextJsonSerializerOptionsSetup>());
- var preActions = context.Services.GetPreConfigureActions();
Configure(options =>
{
- if (preActions.Configure().UseHybridSerializer)
- {
- options.Providers.Add();
- }
+ options.Providers.Add();
});
}
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
index 53a9bd3747..f577746665 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
@@ -25,7 +25,7 @@
-
+
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
index e303a0fb5d..76a95a09cf 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
@@ -11,6 +11,7 @@ using Volo.Abp.AspNetCore.Mvc.Authorization;
using Volo.Abp.AspNetCore.Mvc.GlobalFeatures;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.Localization.Resource;
+using Volo.Abp.AspNetCore.Mvc.NewtonsoftJson;
using Volo.Abp.AspNetCore.Security.Claims;
using Volo.Abp.AspNetCore.TestBase;
using Volo.Abp.Authorization;
@@ -29,7 +30,7 @@ namespace Volo.Abp.AspNetCore.Mvc;
[DependsOn(
typeof(AbpAspNetCoreTestBaseModule),
typeof(AbpMemoryDbTestModule),
- typeof(AbpAspNetCoreMvcModule),
+ typeof(AbpAspNetCoreMvcNewtonsoftModule),
typeof(AbpAutofacModule)
)]
public class AbpAspNetCoreMvcTestModule : AbpModule
diff --git a/nupkg/common.ps1 b/nupkg/common.ps1
index b39e3b1ec2..9f44b11c6d 100644
--- a/nupkg/common.ps1
+++ b/nupkg/common.ps1
@@ -112,6 +112,7 @@ $projects = (
"framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common",
"framework/src/Volo.Abp.AspNetCore.Mvc.Contracts",
"framework/src/Volo.Abp.AspNetCore.Mvc",
+ "framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson",
"framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap",
"framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling.Abstractions",
"framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling",