.NET 8 Worker模式Azure Functions集成AspNetCore后无法配置Newtonsoft序列化器
Azure Functions 隔离模式下配置Newtonsoft.Json支持[FromBody]序列化问题
将Azure Functions从进程内模式迁移至带AspNetCore集成的Worker隔离模式后,无法将序列化器设置为Newtonsoft.Json以保留[FromBody]特性的原有行为。
现有代码
Program.cs
IHost host = new HostBuilder() .ConfigureFunctionsWebApplication(workerAppBuilder => { workerAppBuilder.UseWhen<AuthorizationMiddleware>(c => { string triggerType = c.FunctionDefinition.InputBindings.Values.First(a => a.Type.EndsWith("Trigger", StringComparison.Ordinal)).Type; return string.Equals(triggerType, "httpTrigger", StringComparison.Ordinal); }); }) .ConfigureAppConfiguration(builder => { builder.SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .AddUserSecrets(Assembly.GetExecutingAssembly(), optional: true); }) .ConfigureServices((context, services) => ConfigureServices(services, context.Configuration)) .ConfigureLogging(builder => builder.AddFilter<ApplicationInsightsLoggerProvider>(string.Empty, LogLevel.Information)) .Build(); await host.RunAsync(); static void ConfigureServices(IServiceCollection services, IConfiguration configuration) { services.AddApplicationInsightsTelemetryWorkerService(); services.ConfigureFunctionsApplicationInsights(); // 其他服务注册.. }
HttpTrigger函数示例
using FromBodyAttribute = Microsoft.Azure.Functions.Worker.Http.FromBodyAttribute; public async Task<IActionResult> RunAsync( [HttpTrigger( AuthorizationLevel.Anonymous, "post", Route = "companies/search")] HttpRequest request, [FromBody] SearchCompaniesQuery searchCompaniesQuery, CancellationToken ct) { return new OkObjectResult(await companyService.SearchCompaniesAsync(searchCompaniesQuery, ct)); }
已尝试的解决方案
方案1:在
ConfigureServices中添加以下代码,可运行但无官方文档支持,存在兼容性顾虑services.AddMvcCore().AddNewtonsoftJson();已安装
Microsoft.AspNetCore.Mvc.NewtonsoftJson8.0.0版本方案2:修改
ConfigureFunctionsWebApplication配置.ConfigureFunctionsWebApplication(workerAppBuilder => workerAppBuilder.UseNewtonsoftJson())方案3:配置
WorkerOptions指定全局序列化器.ConfigureServices((context, services) =>{ services.Configure<WorkerOptions>(workerOptions => { JsonSerializerSettings settings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings(); settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); settings.NullValueHandling = NullValueHandling.Ignore; workerOptions.Serializer = new NewtonsoftJsonObjectSerializer(settings); }) })
当前异常信息
[2023-12-06T09:35:04.528Z] Function 'createOrUpdate', Invocation id '172f2590-9810-48b0-8fa7-bdb1b02b1ea6': An exception was thrown by the invocation. [2023-12-06T09:35:04.530Z] Result: Function 'createOrUpdate', Invocation id '172f2590-9810-48b0-8fa7-bdb1b02b1ea6': An exception was thrown by the invocation. Exception: System.InvalidOperationException: The JSON value could not be converted to System.Nullable`1[System.Guid]. Path: $.repeatIntervalUnitsId | LineNumber: 0 | BytePositionInLine: 27. [2023-12-06T09:35:04.534Z] [2023-12-06T09:35:04.536Z] at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FromBodyConverstionFeature.ConvertAsync(FunctionContext context, Type targetType) in D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FromBodyConverstionFeature.cs:line 91 [2023-12-06T09:35:04.537Z] at Microsoft.Azure.Functions.Worker.Extensions.Http.Converters.FromBodyConverter.HandleResultAsync(ValueTask`1 result) in D:\a\_work\1\s\extensions\Worker.Extensions.Http\src\FromBodyConverter.cs:line 28 [2023-12-06T09:35:04.548Z] at Microsoft.Azure.Functions.Worker.Context.Features.DefaultInputConversionFeature.AwaitAndReturnConversionTaskResult(ValueTask`1 conversionTask) in D:\a\_work\1\s\src\DotNetWorker.Core\Context\Features\DefaultInputConversionFeature.cs:line 103 [2023-12-06T09:35:04.549Z] Executed 'Functions.createOrUpdate' (Failed, Id=172f2590-9810-48b0-8fa7-bdb1b02b1ea6, Duration=343ms) [2023-12-06T09:35:04.555Z] at Microsoft.Azure.Functions.Worker.Context.Features.DefaultInputConversionFeature.ConvertAsync(ConverterContext converterContext) in D:\a\_work\1\s\src\DotNetWorker.Core\Context\Features\DefaultInputConversionFeature.cs:line 43[2023-12-06T09:35:04.556Z] System.Private.CoreLib: Exception while executing function: Functions.createOrUpdateTask. System.Private.CoreLib: Result: Failure
正确解决方案
启用AspNetCore集成后,[FromBody]的解析由AspNetCore输入转换管道处理,需在ConfigureFunctionsWebApplication中配置AspNetCore服务使用NewtonsoftJson,而非仅配置Worker全局序列化器:
- 确保已安装
Microsoft.AspNetCore.Mvc.NewtonsoftJson包(版本与项目.NET版本匹配,如.NET 8用8.0.x) - 修改
Program.cs中的ConfigureFunctionsWebApplication配置:
.ConfigureFunctionsWebApplication(workerAppBuilder => { // 配置AspNetCore使用NewtonsoftJson处理请求序列化 workerAppBuilder.Services.AddControllers().AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; // 可添加其他NewtonsoftJson配置,如日期格式、自定义转换器等 }); workerAppBuilder.UseWhen<AuthorizationMiddleware>(c => { string triggerType = c.FunctionDefinition.InputBindings.Values.First(a => a.Type.EndsWith("Trigger", StringComparison.Ordinal)).Type; return string.Equals(triggerType, "httpTrigger", StringComparison.Ordinal); }); })
说明
WorkerOptions.Serializer仅控制函数非HTTP绑定(如Blob、Queue等)的序列化,对[FromBody]的HTTP请求解析无效- 使用
AddControllers().AddNewtonsoftJson()是AspNetCore集成模式下的标准配置方式,符合官方设计逻辑,不存在兼容性风险
内容的提问来源于stack exchange,提问作者David P
相关产品推荐
相关产品推荐

