使用Aspnet [FromQuery]模型绑定中的Enummember值的枚举
通过使用标准[FromQuery],将查询字符串供应到.NET对象中
[Route("[controller]")]
public class SamplesController
: ControllerBase
{
[HttpGet]
public IActionResult Get([FromQuery]QueryModel queryModel)
{
if (!queryModel.Status.HasValue)
{
return BadRequest("Problem in deserialization");
}
return Ok(queryModel.Status.Value.GetEnumDisplayName());
}
}
该项目
public class QueryModel
{
/// <summary>
/// The foo parameter
/// </summary>
/// <example>bar</example>
public string? Foo { get; init; } = null;
/// <summary>
/// The status
/// </summary>
/// <example>on-hold</example>
public Status? Status { get; set; } = null;
}
我在.net 6 microsoft.net.sdk.sdk.web
项目中有一个端点, > enummember 属性我想用来从中挑选的值。
public enum Status
{
[EnumMember(Value = "open")]
Open,
[EnumMember(Value = "on-hold")]
OnHold
}
默认情况下,.NET 6在必要时不考虑 enummember
。
目标是能够
http://localhost:5000/Samples?Foo=bar&Status=on-hold
通过使用其 status.onhold
值来发送诸如控制器的操作 QueryModel
QueryModel 。 >
我尝试过没有运气的扩展库,其中包含一个转换器,但是使用 [FromQuery]
时,转换器不会触发。请参阅 https://github.com/macross-software/core/core/issues/30
我添加了一个重现问题的项目,并作为提供解决方案的沙箱** https://gitlab.com/sunnyatticsoftware/issues/string-to-to-enum-mvc/-/tree/feature/1-original-problem
注意:我需要一个解决方案枚举和不需要任何外部依赖性(仅.NET SDK)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
自定义枚举转换器可能是您的选择。通过利用现有的
enumConverter
类,我们需要的是具有自定义的convertfrom
方法:然后将转换器装饰到您的模型类:
然后我们可以获得“ on-hold” “解析。您可能还需要覆盖用于打印
enummember
值的contergo()
。有点骇客,但是如果您想要纯的.NET解决方案,这应该是最小的可行解决方案之一。A custom Enum converter might be your choice. By leveraging the existing
EnumConverter
class what we need is to have a customizedConvertFrom
method:And then decorate the converter to your Model class:
then we can get the "on-hold" parsed. You might also want to override the
ConverTo()
for printing theEnumMember
value to swagger. It is a bit hacky, but if you want a pure .NET solution this should be one of the minimal viable solutions.之后的文档指南,您可以创建自己的Microsoft类的版本 , (和基类 )取代传入枚举通过
enummemberattribute
用原始枚举名称重命名的值名称:然后在绑定之前:然后在
configureservices()
中添加粘合剂, so:so:notes:
enumtypemodelbinder
和基类SimpleTypemodelbinder
没有提供有用的扩展点来自定义输入值字符串的解析,因此有必要复制一些逻辑。精确模拟
simperepepemodelbinder
的逻辑有些困难,因为它支持数字和文本枚举值 - 包括两个枚举的混合物。上面的活页夹保留了该功能,但还允许成功绑定原始枚举名称。因此,值on-hold
和onhold
将绑定到status.onhold
。。
相反,如果您不想支持枚举数字值的绑定,则可以调整
jsonenummberstringenumconverter
来自此答案 to system.text.json:如何为枚举值指定自定义名称? 。演示小提琴在这里。这种方法还避免了与原始的,未悔的枚举名称结合。将覆盖名称与原始枚举名称匹配是对情况不敏感的,因此不支持仅支持的覆盖名称。
Following the documentation guide Custom Model Binding in ASP.NET Core, you can create your own versions of Microsoft's classes
EnumTypeModelBinderProvider
,EnumTypeModelBinder
(and base classSimpleTypeModelBinder
) that replace incoming enum value names that have been renamed viaEnumMemberAttribute
with the original enum names before binding:Then add the binder in
ConfigureServices()
like so:Notes:
EnumTypeModelBinder
and base classSimpleTypeModelBinder
provide no useful extension points to customize the parsing of the incoming value string, thus it was necessary to copy some of their logic.Precisely emulating the logic of
SimpleTypeModelBinder
is somewhat difficult because it supports both numeric and textual enum values -- including mixtures of both for flags enums. The binder above retains that capability, but at a cost of also allowing original enum names to be bound successfully. Thus the valueson-hold
andonhold
will be bound toStatus.OnHold
.Conversely, if you do not want to support binding of numeric values for enums, you could adapt the code of
JsonEnumMemberStringEnumConverter
from this answer to System.Text.Json: How do I specify a custom name for an enum value?. Demo fiddle here. This approach also avoids binding to the original, unrenamed enum names.Matching of override names with original enum names is case-insensitive, so override names that differ only in case are not supported.