gpt4 book ai didi

c# - JsonConverter 等效于 HTTP GET 参数

转载 作者:行者123 更新时间:2023-11-30 17:31:05 25 4
gpt4 key购买 nike

在为 HTTP POST 函数编写 C# Web API Controller 时,我可以在参数对象的属性上使用 Newtonsoft JSON 中的属性。特别是,我可以使用 JsonConverter attributeenum 类型的属性上将从客户端接收到的字符串表示形式转换为 enum 值之一(对于响应对象,返回):

public class MyArgumentsDTO
{
[JsonConverter(typeof(SomeEnumConverter))]
public SomeEnum MyValue { get; set; }
}

// in the controller:
[Route("doSomething")]
[HttpPost]
public Boolean DoSomething(MyArgumentsDTO options);

但是,对于需要此类 enum 类型参数的 HTTP GET 方法,我应该怎么办?

[Route("getSomething")]
[HttpGet]
public Boolean GetSomething(SomeEnum myValue);

是否有一个属性可以用来装饰相应的参数以指示(字符串到枚举)转换器?

(明确地说,我使用枚举作为示例,因为我经常将这种技术(通过 HTTP POST)与枚举一起使用。据推测,任何适用于枚举的解决方案也适用于任何其他(可能是复杂的)数据类型。)


当然,我可以只将参数声明为 string 并在方法主体中自己进行转换。然而,这似乎不干净,我同意 related answer 中给出的声明。 :

Defining all your enum parameters as strings and then parsing them everywhere means you have to do this on every single action and you will need to come up with a consistent approach such that all parsing errors conform.

不幸的是,我不理解该答案中提出的解决方案,因为它甚至没有涉及使用该问题中提到的 TypeEnum


当我需要枚举参数时,对方法使用 HTTP POST 而不是 HTTP GET 似乎也有某种错误。我认为不应根据此类内部技术来选择 HTTP 方法。

最佳答案

枚举已由 ASP.NET 模型绑定(bind)器正确反序列化。尝试定义一些简单的枚举,例如

public enum Color
{
None,
Green,
Red,
}

[Route("getSomething")]
[HttpGet]
public string Get(Color color)
{
// ...
}

如果您获取 /api/values/color=Green ,颜色将正确设置为 Color.Green 。如果您需要一些自定义值转换(如 #FF0000Color.Red ),使用自定义类型转换器(见下文)的方法将适合您。

ASP.NET 还提供了从 url 反序列化更复杂数据类型的可能性。最简单的方法是实现自定义类型转换器。这是我前段时间开发的应用程序的示例。它使用具有格式为 <department>:<order number> 的唯一标识符的订单,即 NY:123LA:456。模型是

public class OrderId
{
public string DepartmentId { get; }

public int OrderNumber { get; }

public OrderId(string departmentId, int orderNumber)
{
DepartmentId = departmentId;
OrderNumber = orderNumber;
}
}

并且需要通过 HTTP GET 方法传递此类订单 ID:

[HttpGet]
public OrderDetails GetOrderDetails(OrderId orderId)

为了解决这个问题并使 orderId 从 Url 参数正确创建,我们可以实现自定义类型转换器,将字符串值转换为 OrderId 的实例:

public class OrderIdTypeConverter : TypeConverter
{
private static readonly Regex OrderIdRegex = new Regex("^(.+):(\\d+)$", RegexOptions.Compiled);

public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var str = value as string;
if (str != null)
{
int orderId;
var match = OrderIdRegex.Match(str);
if (match.Success && Int32.TryParse(match.Groups[2].Value, out orderId))
{
return new OrderId(match.Groups[1].Value, orderId);
}
}

return base.ConvertFrom(context, culture, value);
}
}

要将此类型转换器与 OrderId 类相关联,只需添加 TypeConverter 属性:

[TypeConverter(typeof(OrderIdTypeConverter))]
public class OrderId

现在,如果我们获得 Url /api/Orders/?orderId=NYC:123,将使用正确填充的 GetOrderDetails 实例调用操作 OrderId

ASP.NET 提供了另一个扩展点,用于从 URL 绑定(bind)模型。它们是 IModelBinderIValueProvider 接口(interface)的自定义实现。查看此 article 了解更多详情。

如果您无法为您无法控制的类型设置类型转换器,那么使用自定义模型联编程序的方法应该适合您。以下是用于自定义枚举值转换的 IModelBinder 实现示例:

public class CustomEnumModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(Color))
{
return false;
}

ValueProviderResult val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (val == null)
{
return false;
}

string rawValue = val.RawValue as string;
if (rawValue == null)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Incorrect input value type");
return false;
}

// Your logic for converting string to enum.
if (rawValue == "FF0000")
{
bindingContext.Model = Color.Red;
return true;
}

bindingContext.ModelState.AddModelError(bindingContext.ModelName, $"Cannot convert {rawValue} to Color");
return false;
}
}

[Route("getSomething")]
[HttpGet]
public string Get([ModelBinder(typeof(CustomEnumModelBinder))] Color color)
{
// ...
}

通过一些额外的工作,您可以实现某种可以聚合现有 Json 转换器的通用模型绑定(bind)器。

关于c# - JsonConverter 等效于 HTTP GET 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48424564/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com