在WebAPI Put方法中区分必需和无效验证ErrorMessage

时间:2016-04-15 07:19:11

标签: c# json asp.net-web-api2

使用以下命令测试WebAPI 2.0 POST:

(1)身体:

{"Description" : 'a', "Priority" : '1', "IsActive":  'x'}

应该返回:

{"errors": [{
   "code": 1020,
   "message": "The isActive field must have a value of either true, false"
}]}

(2)身体:

{"Description" : 'a', "Priority" : '1'}

应该返回:

{"errors": [{
    "Code": 1010
    "Message":"The isActive field is required"
}]}

(3a)身体:

{"Description" : 'a', "Priority" : '1', "IsActive":  true}

应该返回一个空身

(3b)身体:

{"Description" : 'a', "Priority" : '1', "IsActive":  "true"}

应该返回一个空身

(3c)身体:

{"Description" : 'a', "Priority" : '1', "IsActive":  0}

应该返回一个空身

(3d)身体:

{"Description" : 'a', "Priority" : '1', "IsActive":  1}

应该返回一个空身

(3e)身体:

{"Description" : 'a', "Priority" : '1', "IsActive":  "1"}

应该返回一个空身

(3f)身体:

{"Description" : 'a', "Priority" : '1', "IsActive":  "0"}

应该返回一个空身

然而,AC表示当IsActive缺失时应该是:

这是我使用的字段,它是代表Body的类的一部分。

[Required(ErrorMessage = "The isActive field must have a value of either true, false")]

//When IsActive is missing, message should be: The IsActive field is Required
//when IsActive is not the correct type, message should be: The isActive field must have a value of either true, false"

[JsonConverter(typeof(JsonBoolConverter))] 
public bool? IsActive { get; set; }

这里是JsonBoolConverter

public class JsonBoolConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(bool?);
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            bool @return = true;
            bool? @nullable = null;

            if (reader.Value != null)
            {
                if (TryConvertToBoolean(reader.Value.ToString(), out @return))
                {
                    @nullable = @return;
                }
            }

            return @nullable;
        }

        private static readonly List<string> TrueString = new List<string>(new string[] { "true", "1", });

        private static readonly List<string> FalseString = new List<string>(new string[] { "false", "0", });

        public static bool TryConvertToBoolean(string input, out bool result)
        {
            // Remove whitespace from string and lowercase
            string formattedInput = input.Trim().ToLower();

            if (TrueString.Contains(formattedInput))
            {
                result = true;
                return true;
            }
            else if (FalseString.Contains(formattedInput))
            {
                result = false;
                return true;
            }
            else
            {
                result = false;
                return false;
            }
        }
    }

如果我将ErrorMessage从Required属性中删除,那么两者都得到1010。 如果我将ErrorMessage添加到Required属性,那么两者都得到1020。

您能否建议我如何为这两种情况获取不同的信息? 我好几天都在看这个。

1 个答案:

答案 0 :(得分:1)

如果您需要这种灵活性,则无法使用bool?字段。这是因为模型验证仅在请求体被反序列化为对象之后才运行。这意味着,在反序列化之后,您将丢失任何与您的属性类型不匹配的信息(在您的情况下,由于您的自定义bool?JsonConverter的无效条目将被映射为null

一种解决方法,如果你真的需要告诉用户他在JSON字段中插入了一个无效值(并且你接受字符串作为输入)是使属性本身为string,而不是使用它来验证它正则表达式:

[Required(ErrorMessage = "The isActive field is required")]
[RegularExpression("^(?:true|false|0|1)$", ErrorMessage = "The isActive field must have a value of either true, false")]
public string IsActive { get; set; }

您可以使用您喜欢的任何方法将字符串转换为bool。例如,您可以创建一个新的只读属性(从不序列化),返回bool?值:

[JsonIgnore]
public bool? IsActiveBool {
    get {
        bool? result = null;

        if (IsActive != null)
        {
            if (TryConvertToBoolean(IsActive , out result)) // <-- Your method here
            {
                return result;
            }
        }
        return null;
   }
}