.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> .