我正在使用带有Razor Views的ASP.Net MVC 5。我的viewmodel中有以下字段:
[Range(1 to 500)]
public int? MyNumber { get; set; }
如果我在相应的Web表单上输入#125
并提交,则该值将被解释为十六进制数并转换为其十进制等值(我猜这是在模型绑定期间发生的)。只要转换后的数字通过了范围测试,就会通过验证。
原始请求中的值为%23125
。当viewmodel获取它时,它变为293
。
是否有可以捕获此功能的模型注释或其他服务器端验证技术?
到目前为止,我尝试使用非可空整数和正则表达式属性。两者都没有奏效。
答案 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;
}
}