为模型绑定到集合类型指定相等比较器

我有一个 API,您可以在其中指定要获取的名称列表。不允许出现重复名称,如果两个名称仅因大小写不同而被视为重复名称。


GET /api/people?names=john&names=alice

在我自己的 .NET 代码中,我将HashSet使用自定义相等比较器将所有这些名称收集到一个中。


var names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

但我认为 ASP.NET Core 模型绑定不够灵活。


// GET /api/people?names=john&names=JOHN

[HttpGet("api/people")]

public GetPeople([FromQuery] HashSet<string> names)

{

    // this works but names contains both john and JOHN

}

我必须更改什么才能使该names集合仅包含 john 而不是 JOHN?


呼如林
浏览 170回答 3
3回答

蝴蝶刀刀

您可以List<string>在方法头中使用 a ,然后根据您的规则将其加载到 HashSet 中:public GetPeople([FromQuery] List<string> names){&nbsp; &nbsp; var hashed = new HashSet<string>(names, StringComparer.OrdinalIgnoreCase);}作为替代方案,您可以查看自定义模型绑定,但只有在多个地方需要它时才值得付出努力。

智慧大石

您可以使用HashSet<string>设置为始终使用的导数StringComparer.OrdinalIgnoreCase:// Case Insensitive String HashSet, or CIStringSet for short.public class CIStringSet : HashSet<string>{&nbsp; &nbsp; public CIStringSet() : base(StringComparer.OrdinalIgnoreCase)&nbsp; &nbsp; {&nbsp; &nbsp; }}使用它非常简单,如下所示:public object GetPeople([FromQuery] CIStringSet names){&nbsp; &nbsp; return Json(names);}经过测试,它有效:

婷婷同学_

一个完全没有错误处理的静态解决方案,但有效的是以下粘合剂:public Task BindModelAsync(ModelBindingContext bindingContext){&nbsp; &nbsp; var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);&nbsp; &nbsp; bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);&nbsp; &nbsp; var values = valueProviderResult.Values.Select(value => value).ToHashSet(StringComparer.OrdinalIgnoreCase);&nbsp; &nbsp; bindingContext.Result = ModelBindingResult.Success(values);&nbsp; &nbsp; return Task.CompletedTask;}端点:[HttpGet]public IActionResult Test([ModelBinder(typeof(HashSetBinder))] IEnumerable<string> values){&nbsp; &nbsp; return Ok(new&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; values&nbsp; &nbsp; });}然后像这样打开网址:http://localhost:5000/api/mycontroller?values=1&values=1&values=1&values=2结果将是 {"values":["1","2"]}这可以通过模型绑定提供程序全局注册,但为此它需要实现更多检查。
打开App,查看更多内容
随时随地看视频慕课网APP