.NET 6 使用 Autofac 设置 Newtonsoft.Json 默认选项
.NET 6 set Newtonsoft.Json default options with Autofac
我目前正在重构我的 .NET 6 WebAPI。在重构时,我转而使用 Autofac 作为我的 DI 框架。
为了让我的控制器不 return 空值,我使用 newtonsoft json 和以下选项:
builder.Services.AddControllers().AddDefaultJsonOptions();
public static IMvcBuilder AddDefaultJsonOptions(this IMvcBuilder builder)
{
return builder.AddNewtonsoftJson(options =>
{
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
}
使用 autofac,我将控制器的注册更改为:
builder.Host.ConfigureContainer<Autofac.ContainerBuilder>(builder =>
{
...
var executingAssembly = Assembly.GetExecutingAssembly();
builder.RegisterApiControllers(executingAssembly);
...
});
但是现在如何更改默认的 json 序列化选项?
ASP.NET Core 完全开源的好处是您可以 hit the repo yourself 并进行一些探索以弄清楚这些方法的作用,然后追踪如何解决此类问题。
在这种情况下,让我们看看what AddControllers
actually does:
public static IMvcBuilder AddControllers(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
var builder = AddControllersCore(services);
return new MvcBuilder(builder.Services, builder.PartManager);
}
看来AddControllersCore
里隐藏着很多东西,所以we can scroll down to that:
private static IMvcCoreBuilder AddControllersCore(IServiceCollection services)
{
// This method excludes all of the view-related services by default.
var builder = services
.AddMvcCore()
.AddApiExplorer()
.AddAuthorization()
.AddCors()
.AddDataAnnotations()
.AddFormatterMappings();
if (MetadataUpdater.IsSupported)
{
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IActionDescriptorChangeProvider, HotReloadService>());
}
return builder;
}
有意思。所以 AddControllers
实际上并没有将 文字控制器 添加到服务集 - 它添加了 执行控制器 所需的东西。这是为什么?
我会 fast-forward 一点 - 这是因为 默认情况下控制器没有解析为服务。 惊喜!实际发生的是控制器 参数 被解析,但是 控制器本身 是通过反射创建的,解析的参数传递给构造函数。如果你真的想要控制器 被解析 (比如,支持 属性 注入或其他东西),you need to use AddControllersAsServices
(This is also in the Autofac documentation。)
事实上,您正在使用的 RegisterApiControllers
方法甚至不适用于 ASP.NET Core - 它适用于 ASP.NET Web API, which isn't in .NET 6. You really need to be checking out ASP.NET Core integration,绝对 不 在重构中使用任何经典 ASP.NET 和 Web API 的东西。这不是 mix-and-match。都是 .NET Core / ASP.NET Core。
那么,要回答这个问题,您如何同时注册您的控制器和如何获得您的JSON选项?
继续做你正在做的事情。
builder.Services
.AddControllers()
.AddControllersAsServices()
.AddDefaultJsonOptions();
如果你真的想用 Autofac 手动注册控制器,你可以 re-register 它们(在 你调用 AddControllersAsServices
) 但您会将它们注册为它们自己。
builder.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Services
.AddControllers()
.AddControllersAsServices()
.AddDefaultJsonOptions();
builder.Host
.ConfigureContainer<ContainerBuilder>(b => {
b.RegisterType<MyController>().PropertiesAutowired();
});
但是,再次重申,除非您专门做一些事情来覆盖控制器的注册方式,例如需要设置 lambda 或 属性 注入或其他东西,否则 AddControllersAsServices
将涵盖它。
如果您希望将 Autofac 作为您的容器,您确实需要调用 UseServiceProviderFactory
。 否则,您将获得默认的 Microsoft 容器,即使您调用 ConfigureContainer<T>
.
我目前正在重构我的 .NET 6 WebAPI。在重构时,我转而使用 Autofac 作为我的 DI 框架。
为了让我的控制器不 return 空值,我使用 newtonsoft json 和以下选项:
builder.Services.AddControllers().AddDefaultJsonOptions();
public static IMvcBuilder AddDefaultJsonOptions(this IMvcBuilder builder)
{
return builder.AddNewtonsoftJson(options =>
{
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
}
使用 autofac,我将控制器的注册更改为:
builder.Host.ConfigureContainer<Autofac.ContainerBuilder>(builder =>
{
...
var executingAssembly = Assembly.GetExecutingAssembly();
builder.RegisterApiControllers(executingAssembly);
...
});
但是现在如何更改默认的 json 序列化选项?
ASP.NET Core 完全开源的好处是您可以 hit the repo yourself 并进行一些探索以弄清楚这些方法的作用,然后追踪如何解决此类问题。
在这种情况下,让我们看看what AddControllers
actually does:
public static IMvcBuilder AddControllers(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
var builder = AddControllersCore(services);
return new MvcBuilder(builder.Services, builder.PartManager);
}
看来AddControllersCore
里隐藏着很多东西,所以we can scroll down to that:
private static IMvcCoreBuilder AddControllersCore(IServiceCollection services)
{
// This method excludes all of the view-related services by default.
var builder = services
.AddMvcCore()
.AddApiExplorer()
.AddAuthorization()
.AddCors()
.AddDataAnnotations()
.AddFormatterMappings();
if (MetadataUpdater.IsSupported)
{
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IActionDescriptorChangeProvider, HotReloadService>());
}
return builder;
}
有意思。所以 AddControllers
实际上并没有将 文字控制器 添加到服务集 - 它添加了 执行控制器 所需的东西。这是为什么?
我会 fast-forward 一点 - 这是因为 默认情况下控制器没有解析为服务。 惊喜!实际发生的是控制器 参数 被解析,但是 控制器本身 是通过反射创建的,解析的参数传递给构造函数。如果你真的想要控制器 被解析 (比如,支持 属性 注入或其他东西),you need to use AddControllersAsServices
(This is also in the Autofac documentation。)
事实上,您正在使用的 RegisterApiControllers
方法甚至不适用于 ASP.NET Core - 它适用于 ASP.NET Web API, which isn't in .NET 6. You really need to be checking out ASP.NET Core integration,绝对 不 在重构中使用任何经典 ASP.NET 和 Web API 的东西。这不是 mix-and-match。都是 .NET Core / ASP.NET Core。
那么,要回答这个问题,您如何同时注册您的控制器和如何获得您的JSON选项?
继续做你正在做的事情。
builder.Services
.AddControllers()
.AddControllersAsServices()
.AddDefaultJsonOptions();
如果你真的想用 Autofac 手动注册控制器,你可以 re-register 它们(在 你调用 AddControllersAsServices
) 但您会将它们注册为它们自己。
builder.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Services
.AddControllers()
.AddControllersAsServices()
.AddDefaultJsonOptions();
builder.Host
.ConfigureContainer<ContainerBuilder>(b => {
b.RegisterType<MyController>().PropertiesAutowired();
});
但是,再次重申,除非您专门做一些事情来覆盖控制器的注册方式,例如需要设置 lambda 或 属性 注入或其他东西,否则 AddControllersAsServices
将涵盖它。
如果您希望将 Autofac 作为您的容器,您确实需要调用 UseServiceProviderFactory
。 否则,您将获得默认的 Microsoft 容器,即使您调用 ConfigureContainer<T>
.