ibe*_*dev 7 enums jsonserializer custom-model-binder asp.net-core system.text.json
我在 .NET 6 项目中有一个端点Microsoft.NET.Sdk.Web,它使用标准 [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());
}
}
Run Code Online (Sandbox Code Playgroud)
该模型包含一个枚举
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;
}
Run Code Online (Sandbox Code Playgroud)
枚举具有EnumMember我想用来反序列化的值的属性。
public enum Status
{
[EnumMember(Value = "open")]
Open,
[EnumMember(Value = "on-hold")]
OnHold
}
Run Code Online (Sandbox Code Playgroud)
默认情况下,.NET 6 不考虑EnumMember反序列化时的情况。
目标是能够发送请求,例如
http://localhost:5000/Samples?Foo=bar&Status=on-hold
Run Code Online (Sandbox Code Playgroud)
并让控制器的操作使用QueryModel正确的值反序列化Status.OnHoldEnumMember
我尝试过包含转换器的扩展库,但没有成功,但是在使用[FromQuery]. 请参阅https://github.com/Macross-Software/core/issues/30
我添加了一个项目来重现问题并作为沙箱提供解决方案** https://gitlab.com/sunnyatticsoftware/issues/string-to-enum-mvc/-/tree/feature/1-original-problem
注意:我需要一个解决方案,其中 Enum 不需要任何外部依赖项(只需 .NET sdk)。
自定义枚举转换器可能是您的选择。通过利用现有的EnumConverter类,我们需要一个定制的ConvertFrom方法:
public class CustomEnumConverter : EnumConverter
{
public CustomEnumConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields)] Type type) : base(type)
{
}
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{
if (value is string strValue)
{
try
{
foreach (var name in Enum.GetNames(EnumType))
{
var field = EnumType.GetField(name);
if (field != null)
{
var enumMember = (EnumMemberAttribute)(field.GetCustomAttributes(typeof(EnumMemberAttribute), true).Single());
if (strValue.Equals(enumMember.Value, StringComparison.OrdinalIgnoreCase))
{
return Enum.Parse(EnumType, name, true);
}
}
}
}
catch (Exception e)
{
throw new FormatException((string)value, e);
}
}
return base.ConvertFrom(context, culture, value);
}
}
Run Code Online (Sandbox Code Playgroud)
然后将转换器装饰到您的 Model 类:
[TypeConverter(typeof(CustomEnumConverter))]
public enum Status
{
[EnumMember(Value = "open")]
Open,
[EnumMember(Value = "on-hold")]
OnHold
}
Run Code Online (Sandbox Code Playgroud)
然后我们就可以解析“on-hold”。您可能还想覆盖将值ConverTo()打印EnumMember为 swagger。这有点 hacky,但如果您想要一个纯粹的 .NET 解决方案,这应该是最小可行的解决方案之一。
| 归档时间: |
|
| 查看次数: |
2213 次 |
| 最近记录: |