整数值模型验证

时间:2014-08-17 13:07:25

标签: asp.net asp.net-web-api2 model-validation

我的模型中有一个常规的Integer(不可为空):

    [Required]
    [Range(0, Int32.MaxValue - 1)]
    public int PersonId
    {
        get;
        set;
    }

在我的WebApi行动中,我接受了一个具有该属性的对象。

    public IHttpActionResult Create([FromBody] Person person)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest("Some error message.");
        } 
        //Do some stuff with person...
    }

现在,尽管Required上有一个PersonId属性,当有人发布此操作时,ModelState.IsValid属性为true

我想这是因为Person是使用默认值创建的,它是0,如果传入的JSON /查询字符串请求中没有PersonId字段,我想抛出一个错误。

我可以将PersonId设置为Nullable,但这没有意义。

有没有简单的方法来验证字段是否存在且整数是否大于0? (没有针对该简单要求的自定义验证器)

4 个答案:

答案 0 :(得分:2)

据我所知,设置[Required]属性对int没有任何作用。所有[Required]都会确保该值不为空。 您可以设置[Range(1, Int32.MaxValue)]以确保添加正确的值。

如果您还没有这样做,那么为您的视图制作不同的模型并在此模型上进行数据注释可能是个好主意。我使用视图模型来确保我不会污染我的"真实的"具有与整个域无关的内容的模型。这样,您的PersonId只能在您的视图模型中可以为空,这是有意义的。

答案 1 :(得分:1)

BindRequiredAttribute可用于

引用此nice blog post关于[Required][BindRequired]

的信息
  

它的工作方式与RequiredAttribute相同,只是它要求它   值来自请求 - 所以它不仅拒绝空值,   还有默认(或“未绑定”)值。

所以这会拒绝未绑定的整数值:

[BindRequired]
[Range(0, Int32.MaxValue - 1)]
public int PersonId
{
    get;
    set;
}

答案 2 :(得分:0)

在这种情况下,我倾向于使用int?(nullable int),然后根据需要标记它们。然后我在整个代码中使用myInt.Value并假设它可以安全使用,因为它不会通过验证。

和@andreas说的一样,我确保在这样的时候使用“视图模型”,所以我不会将我的视图模型作为业务或数据层模型进行污染。

答案 3 :(得分:0)

实际上,对于缺少不可为空的整数参数的模型验证无效。 Newtonsoft.Json引发了JSON解析异常。 您可以采用以下变通办法来解析并在模型验证中包括异常。 如下创建自定义验证属性,然后在WebApiConfig.cs中注册。

public class ValidateModelAttribute : ActionFilterAttribute {
    public override void OnActionExecuting(HttpActionContext actionContext) {
        // Check if model state is valid
        if (actionContext.ModelState.IsValid == false) {
            // Return model validations object
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest,
                                                                            new ValidationResultModel(100001, actionContext.ModelState));
        }
    }

    public class ValidationError {
        public string Field { get; }

        public string Message { get; }

        public ValidationError(string field, string message) {
            Field = field != string.Empty ? field : null;
            Message = message;
        }
    }

    public class ValidationResultModel {
        public int Code { get; set; }
        public string Message { get; }
        public IDictionary<string, IEnumerable<string>> ModelState { get; private set; }

        public ValidationResultModel(int messageCode, ModelStateDictionary modelState) {
            Code = messageCode;
            Message = "Validation Failed";

            ModelState = new Dictionary<string, IEnumerable<string>>();

            foreach (var keyModelStatePair in modelState) {
                var key = string.Empty;
                key = keyModelStatePair.Key;
                var errors = keyModelStatePair.Value.Errors;
                var errorsToAdd = new List<string>();

                if (errors != null && errors.Count > 0) {
                    foreach (var error in errors) {
                        string errorMessageToAdd = error.ErrorMessage;

                        if (string.IsNullOrEmpty(error.ErrorMessage)) {
                            if (key == "model") {
                                Match match = Regex.Match(error.Exception.Message, @"'([^']*)");
                                if (match.Success)
                                    key = key + "." + match.Groups[1].Value;

                                errorMessageToAdd = error.Exception.Message;
                            } else {
                                errorMessageToAdd = error.Exception.Message;
                            }
                        }

                        errorsToAdd.Add(errorMessageToAdd);
                    }

                    ModelState.Add(key, errorsToAdd);
                }
            }
        }
    }
}

//在WebApiConfig.cs中注册

// Model validation           
   config.Filters.Add(new ValidateModelAttribute());