正如在docs https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-7.0#configure-json-deserialization-options-for-body-binding:
正文绑定源使用 System.Text.Json 进行反序列化。这是not可以更改此默认值
但也有解决方法。
根据我的理解,最小 API 依赖于一些有关类型绑定的约定。据我所知,他们搜索具有下一个签名的方法 -ValueTask<TModel?> BindAsync(HttpContext context, ParameterInfo parameter)
在类型上,否则将尝试使用httpContext.Request.ReadFromJsonAsync https://github.com/dotnet/aspnetcore/blob/a450cb69b5e4549f5515cdb057a68771f56cefd7/src/Http/Http.Extensions/src/RequestDelegateFactory.cs#L588其内部使用System.Text.Json
这无法改变,所以services.Add...().AddNewtonsoftJson((options) => //options);
方法不会起作用。
To use Newtonsoft.Json
您可以尝试下一步(除了通过直接处理请求app.MapPost("/pst", (HttpContext c) => c.Request...)
):
如果您可以控制需要使用它反序列化的所有类,您可以从某个通用基类继承它们,该基类将具有具有所需签名的方法(您也可以使用接口实现静态方法 https://github.com/DamianEdwards/MinimalApiPlayground/blob/main/src/MinimalApiPlayground/Properties/IInterfaceBinder.cs):
public class BaseModel<TModel>
{
public static async ValueTask<TModel?> BindAsync(HttpContext context, ParameterInfo parameter)
{
if (!context.Request.HasJsonContentType())
{
throw new BadHttpRequestException(
"Request content type was not a recognized JSON content type.",
StatusCodes.Status415UnsupportedMediaType);
}
using var sr = new StreamReader(context.Request.Body);
var str = await sr.ReadToEndAsync();
return JsonConvert.DeserializeObject<TModel>(str);
}
}
及用法:
class PostParams : BaseModel<PostParams>
{
[JsonProperty("prop")]
public int MyProperty { get; set; }
}
// accepts json body {"prop": 2}
app.MapPost("/pst", (PostParams po) => po.MyProperty);
注意BaseModel<TModel>
这个例子中的实现非常简单,可能可以改进(查看HttpRequestJsonExtensions.ReadFromJsonAsync https://github.com/dotnet/aspnetcore/blob/a450cb69b5e4549f5515cdb057a68771f56cefd7/src/Http/Http.Extensions/src/HttpRequestJsonExtensions.cs#L50至少)。
如果您无法控制模型或不想从某个基础继承它们,您可以考虑创建包装器:
public class Wrapper<TModel>
{
public Wrapper(TModel? value)
{
Value = value;
}
public TModel? Value { get; }
public static async ValueTask<Wrapper<TModel>?> BindAsync(HttpContext context, ParameterInfo parameter)
{
if (!context.Request.HasJsonContentType())
{
throw new BadHttpRequestException(
"Request content type was not a recognized JSON content type.",
StatusCodes.Status415UnsupportedMediaType);
}
using var sr = new StreamReader(context.Request.Body);
var str = await sr.ReadToEndAsync();
return new Wrapper<TModel>(JsonConvert.DeserializeObject<TModel>(str));
}
}
用法更改为:
class PostParams
{
[JsonProperty("prop")]
public int MyProperty { get; set; }
}
// accepts json body {"prop": 2}
app.MapPost("/pst", (Wrapper<PostParams> po) => po.Value.MyProperty);
一些额外有用的链接:
-
MVC 模型绑定器 https://github.com/davidfowl/MinimalApiPlayground/blob/main/src/MinimalApiPlayground/Properties/ModelBinderOfT.cs——大卫·福勒着。虽然我没能让它发挥作用
services.AddControllers().AddNewtonsoftJson((options) => //options);
-
参数绑定器 https://github.com/davidfowl/MinimalApiPlayground/blob/main/src/MinimalApiPlayground/Properties/ParameterBinders.cs- 达米安·爱德华兹 (Damian Edwards) 的类似方法