如何验证我的MVC视图模型不接受整数的十六进制数?

时间:2016-02-13 00:18:08

标签: c# validation razor asp.net-mvc-5

我正在使用带有Razor Views的ASP.Net MVC 5。我的viewmodel中有以下字段:

[Range(1 to 500)]
public int? MyNumber { get; set; }

如果我在相应的Web表单上输入#125并提交,则该值将被解释为十六进制数并转换为其十进制等值(我猜这是在模型绑定期间发生的)。只要转换后的数字通过了范围测试,就会通过验证。

原始请求中的值为%23125。当viewmodel获取它时,它变为293

是否有可以捕获此功能的模型注释或其他服务器端验证技术?

到目前为止,我尝试使用非可空整数和正则表达式属性。两者都没有奏效。

2 个答案:

答案 0 :(得分:2)

如果您怀疑在模型绑定期间正在转换十六进制,则需要在客户端上添加一些验证以防止在字段中输入非整数值。理想情况下,所有验证都在客户端和服务器上执行。

客户端验证可以像"模式一样简单"属性只有整数的正则表达式。在服务器上,您可以使用以下正则表达式将RegularExpressionAttribute添加到属性中(接受任何正整数):

客户验证:

<form>
    <label>Your int: 
      <input type="text" pattern="^[1-9]\d*$" required />
<input type="submit" value="Submit" />
</form>

服务器验证:

[RegularExpression(@"^[1-9]\d*$", ErrorMessage = "Only integer values are allowed.")]
[Range(1 to 500)]
public int? MyNumber { get; set; }

答案 1 :(得分:0)

唯一的服务器端方法似乎是自定义模型绑定器。我还必须为MVC认为危险的特殊字符添加处理。我提出的解决方案发布在下面:

在Global.asax(Application_Start)中:

ModelBinders.Binders.DefaultBinder = new CustomModelBinder();

新班级:

public class CustomModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult result;

        try
        {
            result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        }
        catch (Exception ex)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, $"The field {bindingContext.ModelMetadata.DisplayName} contains bad data.");
            return bindingContext.Model;
        }

        if (bindingContext.ModelName == "MyNumber" || bindingContext.ModelName == "MyNumber2")
        {
            return StripAndBindModel(bindingContext, result);
        }

        return base.BindModel(controllerContext, bindingContext);
    }

    private object StripAndBindModel(ModelBindingContext bindingContext, ValueProviderResult result)
    {
        var strippedInput = result.AttemptedValue.Replace("#", string.Empty);

        int value;

        if (int.TryParse(strippedInput, out value))
        {
            return value;
        }

        bindingContext.ModelState.AddModelError(bindingContext.ModelName, $"The field {bindingContext.ModelMetadata.DisplayName} must be a valid number.");
        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, result);

        return bindingContext.Model;
    }
}