在 ASP.NET Core Web Api 的 post 正文中将 List<T> 作为可选参数发送
Send List<T> as an optional parameter in the post body in ASP.NET Core Web Api
我有这个模型,它为 post 请求主体采用可选参数:
public class ReportFilterModel
{
public int? ReportStatusId { get; set; }
public Guid? AreaID { get; set; }
}
这将根据用户提供的过滤器在数据库中进行搜索:
var report = _context.tbl_Reports.AsQueryable();
if (model.ReportStatusId.IsNotNull())
report = report.Where(x => x.IsDeleted == false && x.ReportStatusId == (StatusEnum)model.ReportStatusId.Value);
if (model.Area.IsNotNull())
report = report.Where(x => x.IsDeleted == false && x.Area.Id == model.AreaId);
然后它终于 return 这个:
finalReports = await report
.Where(x => x.IsDeleted == false)
.Select(x => new ReportsWithFiltersModel
{
Id = x.Id,
Area = Id,
UserId = x.UserId,
ReportStatus = x.ReportStatusId.GetEnumDescription(),
}).ToListAsync();
所有这些都工作得很好,但现在我想给出一个可选参数列表,如下所示:
public class ReportFilterModel
{
public List<int>? ReportStatusId { get; set; }
public List<Guid>? AreaID { get; set; }
}
这是一个例外
'List<int>' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'List<int>' could be found (are you missing a using directive or an assembly reference?)
我该如何解决这个问题?
?不代表可选。这意味着 Nullable,其中 T 是值类型(它适用于值类型并使它们可以为空)。
引用类型,例如列表已经可以为 null。
List<int> x = null; //valid version of what you are trying to achieve with List<int>?
int? or Nullable<int> //valid
List<int?> x or List<Nullable<int>> ; //valid
您正在混淆两个概念 nullable value types and nullable reference types (added in C# 8.0). Nullabale value types marked with ?
are basically shortcut for Nullable<T>
and they have Value
属性。 List<T>
(在你的情况下 List<int>
和 List<Guid>
)是引用类型,它没有 Value
属性 并用 ?
标记使编译器请注意此 属性 可以包含 null
引用并使其能够执行规则以确保您已正确检查此 属性 是否存在空引用。因此,简而言之,您的 List<int>? ReportStatusId
和 List<Guid>? AreaID
已经 "optional" 和 ?
让编译器意识到这一点。
急于解决这个问题?
改变
if (model.ReportStatusId.IsNotNull())
report = report.Where(x => x.IsDeleted == false && x.ReportStatusId == (StatusEnum)model.ReportStatusId.Value);
到
if (model.ReportStatusId.IsNotNull() && model.ReportStatusId.Any())
var statuses = model.ReportStatusId.Cast<StatusEnum>().ToList();
report = report.Where(x => x.IsDeleted == false && statuses.Contains(x.ReportStatusId));
我有这个模型,它为 post 请求主体采用可选参数:
public class ReportFilterModel
{
public int? ReportStatusId { get; set; }
public Guid? AreaID { get; set; }
}
这将根据用户提供的过滤器在数据库中进行搜索:
var report = _context.tbl_Reports.AsQueryable();
if (model.ReportStatusId.IsNotNull())
report = report.Where(x => x.IsDeleted == false && x.ReportStatusId == (StatusEnum)model.ReportStatusId.Value);
if (model.Area.IsNotNull())
report = report.Where(x => x.IsDeleted == false && x.Area.Id == model.AreaId);
然后它终于 return 这个:
finalReports = await report
.Where(x => x.IsDeleted == false)
.Select(x => new ReportsWithFiltersModel
{
Id = x.Id,
Area = Id,
UserId = x.UserId,
ReportStatus = x.ReportStatusId.GetEnumDescription(),
}).ToListAsync();
所有这些都工作得很好,但现在我想给出一个可选参数列表,如下所示:
public class ReportFilterModel
{
public List<int>? ReportStatusId { get; set; }
public List<Guid>? AreaID { get; set; }
}
这是一个例外
'List<int>' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'List<int>' could be found (are you missing a using directive or an assembly reference?)
我该如何解决这个问题?
?不代表可选。这意味着 Nullable,其中 T 是值类型(它适用于值类型并使它们可以为空)。
引用类型,例如列表已经可以为 null。
List<int> x = null; //valid version of what you are trying to achieve with List<int>?
int? or Nullable<int> //valid
List<int?> x or List<Nullable<int>> ; //valid
您正在混淆两个概念 nullable value types and nullable reference types (added in C# 8.0). Nullabale value types marked with ?
are basically shortcut for Nullable<T>
and they have Value
属性。 List<T>
(在你的情况下 List<int>
和 List<Guid>
)是引用类型,它没有 Value
属性 并用 ?
标记使编译器请注意此 属性 可以包含 null
引用并使其能够执行规则以确保您已正确检查此 属性 是否存在空引用。因此,简而言之,您的 List<int>? ReportStatusId
和 List<Guid>? AreaID
已经 "optional" 和 ?
让编译器意识到这一点。
急于解决这个问题?
改变
if (model.ReportStatusId.IsNotNull())
report = report.Where(x => x.IsDeleted == false && x.ReportStatusId == (StatusEnum)model.ReportStatusId.Value);
到
if (model.ReportStatusId.IsNotNull() && model.ReportStatusId.Any())
var statuses = model.ReportStatusId.Cast<StatusEnum>().ToList();
report = report.Where(x => x.IsDeleted == false && statuses.Contains(x.ReportStatusId));