Web API - 复杂类型的枚举的表单编码输入允许无效值

时间:2014-12-16 15:56:15

标签: c# asp.net-web-api enums

我有一个包含许多属性的复杂类型,包括一个枚举。当将数据(application / x-www-form-urlencoded)输入到具有此类型作为参数的Web API方法时,它似乎允许为枚举属性的值传递任何字符串值。如果传递的值是枚举的其中一个成员,则它会正确分配值,但如果传递的值无效,则只会分配枚举的第一个成员。

描述问题的简单示例 - 给定模型类:

public enum EdibleFarmAnimal {
   Sheep = 0,
   Cow = 1,
   Chicken = 2
}

public class ExampleModel {
    public EdibleFarmAnimal EatThis { get; set; }
    public string AnotherIrrelevantProperty { get; set; }
}

...以及网络API方法:

[HttpPut]
[ActionName("Put")]
public void Put(long id, ExampleModel model) {
    // Do something with the model
}

如果我将EatThis=Cow&AnotherIrrelevantProperty=cheese放到相关的URL上,它按预期工作,并且model.EatThis等于EdibleFarmAnimal.Cow,但是如果我PUT EatThis=Horse&AnotherIrrelevantProperty=cheese则model.EatThis设置为EdibleFarmAnimal。绵羊,虽然我希望(并期望)某种错误被抛出,因为输入对于被反序列化的类型无效。

2 个答案:

答案 0 :(得分:2)

C#中的{p> Enum默认值为0,因此当它无法解析您的输入时,默认为0,代表您枚举中的Sheepmsdn article on this)。

您可以做的是创建Invalid枚举元素并将其分配给0

public enum EdibleFarmAnimal {
   Invalid = 0,
   Sheep = 1,
   Cow = 2,
   Chicken = 3
}

然后检查您的输入是否有效。

答案 1 :(得分:1)

感谢Vsevolod的回答,我能够理解它为什么分配它的值,但是检测方案的解决方案是检查Web API方法中的ModelState.IsValid属性 - 这是设置的如果无法解析枚举值或日期时间,或者您添加到模型中的任何特定验证属性未通过给定输入,则为false。如this article

中所述
  

验证失败时,Web API不会自动向客户端返回错误。由控制器操作来检查模型状态并做出适当的响应。

因此,要更正原始示例,现在它会抛出相应的错误:

[HttpPut]
[ActionName("Put")]
public void Put(long id, ExampleModel model) {
    if (!ModelState.IsValid) throw new HttpResponseException(HttpStatusCode.BadRequest);
    // Do something with the model
}

This answer描述了一种通过使用自定义属性来应用此类验证的好方法,作为检查每个API调用的替代方法。