我有一个枚举:
public enum FilterOperator
{
[EnumMember(Value = "eq")]
Equals,
[EnumMember(Value = "gt")]
GreaterThan,
[EnumMember(Value = "lt")]
LessThan,
[EnumMember(Value = "in")]
In,
[EnumMember(Value = "like")]
Like
}
以及包含枚举属性的类:
public class GridFilter
{
[JsonProperty("operator")]
[JsonConverter(typeof(StringEnumConverter))]
public FilterOperator Operator { get; set; }
}
通过WebAPI操作传入对象,并按照预期反序列化"类似"和" in"但它并不适用于" lg"或" gt"。知道为什么吗?
更新:原因"喜欢"和" in"工作是他们匹配枚举名称。将GreaterThan重命名为Gt(etc)可以正常工作。那么真正的问题是为什么没有使用StringEnumConverter?
答案 0 :(得分:2)
感谢大家的帮助!我意识到我做了什么。可悲的是,这是相当愚蠢的,我道歉为此事而道歉。
由于我使用GET,我将参数作为url查询参数发送,因此WebAPI使用普通的ModelBinder来映射名称而不是JSON.NET。我实际上并没有发送JSON,所以这是完全有道理的。这个问题让我意识到这一点: Complex type is getting null in a ApiController parameter
我的选择是创建一个自定义模型绑定器,正确处理枚举或更改为POST并使用JSON.stringify()发送数据。
答案 1 :(得分:2)
好吧,如果要在外部反序列化时使用[JsonConverter(typeof(StringEnumConverter))]
声明,则必须将enum
属性直接放在Operator
声明而不是GridFilter
GridFilter
属性上班级[JsonConverter(typeof(StringEnumConverter))] // Add this
public enum FilterOperator
{
[EnumMember(Value = "eq")]
Equals,
[EnumMember(Value = "gt")]
GreaterThan,
[EnumMember(Value = "lt")]
LessThan,
[EnumMember(Value = "in")]
In,
[EnumMember(Value = "like")]
Like
}
public class GridFilter
{
[JsonProperty("operator")]
//[JsonConverter(typeof(StringEnumConverter")] // Remove this
public FilterOperator Operator { get; set; }
}
的上下文:
$('#form').attr('action', window.siteRoot + 'Users/Cards/').submit();
答案 2 :(得分:0)
这只是猜测,我还没有测试过。
我查看了EnumMemberAttribute
的文档,并说:
要使用
EnumMemberAttribute
,请创建枚举并将DataContractAttribute
属性应用于枚举。然后将EnumMemberAttribute
属性应用于需要在序列化流中的每个成员。
那当然是DataContractSerializer
,但我想也许JSON.net会考虑同样的规则?
我尝试将[DataContract]
应用于enum
。
[DataContract]
public enum FilterOperator
{
[EnumMember(Value = "eq")]
Equals,
[EnumMember(Value = "gt")]
GreaterThan,
[EnumMember(Value = "lt")]
LessThan,
[EnumMember(Value = "in")]
In,
[EnumMember(Value = "like")]
Like
}
似乎是武断的,多余的。而且我知道JSON.net通常 依赖于那种东西,但也许在这种情况下呢?
我还注意到DataContractSerializer
如果[EnumMember]
存在,[DataContract]
忽略没有EnumMemberAttribute
的元素,那么它可能必须采用这种方式才能向后兼容。再次,不是超级逻辑。但这就是我所拥有的一切。
编辑以真正的开发人员方式,而不仅仅是测试,我进入了源代码。可以在第55行找到n2 = f.GetCustomAttributes(typeof(EnumMemberAttribute), true)
.Cast<EnumMemberAttribute>()
.Select(a => a.Value)
.SingleOrDefault() ?? f.Name;
的{{1}}部分,并执行此操作:
public enum FilterOperator
{
[EnumMember(Value = "eq")]
Equals,
[EnumMember(Value = "gt")]
GreaterThan,
[EnumMember(Value = "lt")]
LessThan,
[EnumMember(Value = "in")]
In,
[EnumMember(Value = "like")]
Like
}
public class GridFilter
{
[JsonProperty("operator")]
[JsonConverter(typeof(StringEnumConverter))]
public FilterOperator Operator { get; set; }
}
[TestMethod]
public void enumTest()
{
GridFilter gf = new GridFilter()
{
Operator = FilterOperator.GreaterThan
};
var json = JsonConvert.SerializeObject(gf);
// json yields {"operator":"gt"}
var ret = JsonConvert.DeserializeObject<GridFilter>(json);
// ret.Operator yields FilterOperator.GreaterThan
}
这让我觉得你所拥有的应该是有效的。
编辑2:
好吧,所以这很奇怪。我自己尝试过,发现它有效。
{{1}}