StackOverflow 上有很多类似的问题,但没有人谈论我的问题。
我有 REST API 控制器,方法如下:
[HttpGet("Lists")]
public Codebook GetFilterLists([FromQuery] FilterQuery? filterQuery = null)
{
// some select and return code
}
FilterQuery
类的所有属性在 Swagger UI 上显示为可选。
当我将它们全部留空并单击“执行”按钮时,Swagger UI 会进行以下 GET 查询:
https://localhost:7137/api/PublicWeb/Lists
即便如此,
filterQuery
参数也具有值 - 具有默认值的filterQuery
实例。
我尝试更改 Program.cs 中的
JsonSerializerOptions.DefaultIgnoreCondition
设置,但对此没有效果。
你知道我做错了什么吗?
好吧,一开始我想分享的是,你可能知道nullable和Optional是完全不同的概念。如果您使用
int?
声明一个参数,将其标记为可为空,但它不是可选的:您必须传递非空整数值或 null。但是,添加 = null
是声明 可选参数 的默认值所需的语法。您可以在这里查看更多详细信息。
.NET Core Web API 可选查询参数仍然不为空。你知道我做错了什么吗?
您所得到的行为是预期的,因为如果属性是简单类型,则该属性被设置为 null 或默认值,但您的属性是复杂类型,因此,值设置不为 null。
除此之外,不可空值类型设置为
default(T)
。意味着它创建了一个实例,但你的实例可以为空,这违反了约定,因此它不会找到任何与其匹配的源属性,从而导致不为空。
注意:您可以在官方文档中找到更多详细信息。
我尝试更改 JsonSerializerOptions.DefaultIgnoreCondition 设置 在 Program.cs 中,但对此没有任何影响。
不,JsonSerializerOptions 无法解决您的问题。您需要自定义模型绑定器来实现您所期望的。这里我给你提供了一个示例图,但是你必须根据你的要求来改进它。
定制模型活页夹:
public class NullEntityBinder : IModelBinder
{
public NullEntityBinder()
{
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model = new FilterQuery();
if (bindingContext.ValueProvider.GetValue("AreaOfAdjustmentId").FirstOrDefault() != null)
{
model.AreaOfAdjustmentId = Convert.ToUInt32(bindingContext.ValueProvider.GetValue("AreaOfAdjustmentId").FirstOrDefault());
}
if (bindingContext.ValueProvider.GetValue("DocumentName").FirstOrDefault() != null)
{
model.DocumentName = bindingContext.ValueProvider.GetValue("DocumentName").FirstOrDefault();
}
if (model.AreaOfAdjustmentId == null && model.DocumentName == null)
{
bindingContext.Result = ModelBindingResult.Success(null);
}
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
用活页夹包裹你的模型:
[ModelBinder(BinderType = typeof(NullEntityBinder))]
public class FilterQuery
{
public uint? AreaOfAdjustmentId { get; set; }
public string? DocumentName { get; set; }
}
注意: 在我的测试中我使用了两个属性进行演示;您还需要根据您的其他属性实现逻辑。
输出:
注意:如果您想了解更多详细信息,您可以在此处查看我们的官方文档
据我所知,模型绑定是如何工作的,现在这是不可能的;它总是尝试用默认值填充类。
我认为,从他们如何设置路由和绑定的角度来看,推荐的方法是使用两种不同的路由来处理两种情况:一种是如果您试图给它一个过滤器查询,另一种是如果您不这样做。或者只是检查 filterquery 对象内部的值,看看它是否有效或只是默认值。