我想使用自定义DataAnnotationsAttribute验证模型的DTO属性上的各种电话号码属性。我不想将DataAnnotations复制到ViewModel上,以保持代码DRY,而是使用DataAnnotationsModelValidatorProvider为客户端验证注册了自定义适配器。此适配器提供ModelClientValidationRemoteRules,通常由RemoteAttribute使用。 jQuery不显眼的验证然后调用我的验证操作,验证各个字段。
然而,这种设置并不合适。
该属性当前使用其ContainerType来计算出哪个 要调用的验证操作。 DTO用于不同的视图模型 然而,在不同的筑巢水平,所以我们不知道到底是什么 在动作上使用的前缀。取决于ProfileDto的位置 在模型层次结构中,操作前缀需要更改
验证操作使用Request.Form.Keys来确定哪个 属性应该验证。我知道这是最好的做法 为单位而远离Action中的Request对象 测试等。
是否有一种很好的方法可以在回发中包含要验证的字段名称,因此我可以将其作为附加参数而不是使用Request.Form?
有没有办法让模型绑定器绑定我的属性,因为它们将使用取决于子模型名称的前缀回发?
提前致谢!
该属性如下:
public class PhoneNumberAttribute : ValidationAttribute
{
public PhoneNumberType RequiredType { get; set; }
public PhoneNumberAttribute()
: base("{0} is not a valid phone number.")
{
}
public override bool IsValid(object value)
{
string s = value as string;
if (s == null)
{
return false;
}
if (!PhoneNumberUtils.IsValidNumber(s, RequiredType))
{
return false;
}
return true
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name);
}
}
和适配器:
public class PhoneNumberAttributeAdapter : DataAnnotationsModelValidator<PhoneNumberAttribute>
{
public PhoneNumberAttributeAdapter(ModelMetadata metadata, ControllerContext context, PhoneNumberAttribute attribute)
: base(metadata, context, attribute)
{
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
var errorMessage = Attribute.FormatErrorMessage(Metadata.GetDisplayName());
var routeData = new RouteValueDictionary {
{ "controller", "Validate" },
{ "action", Metadata.ContainerType.Name },
};
var path = RouteTable.Routes.GetVirtualPathForArea(ControllerContext.RequestContext, routeData);
var rule = new ModelClientValidationRemoteRule(
errorMessage,
path.VirtualPath,
"POST",
"*." + Metadata.PropertyName);
return new[] { rule };
}
}
这是行动:
public ActionResult ProfileDto([Bind(Prefix = "Dto")]ProfileDto model)
{
string fieldToValidate = Request.Form.Keys[0];
if (ModelState.IsValidField(fieldToValidate))
{
return Json(true);
}
var fieldErrors = ModelState[fieldToValidate].Errors;
return Json(fieldErrors.First().ErrorMessage);
}