我想使用自定義的DataAnnotationsAttribute來驗證我的模型的DTO屬性上的各種電話號碼屬性。我不想將DataAnnotations複製到ViewModels上,以保持代碼乾爽,而是使用DataAnnotationsModelValidatorProvider爲客戶端驗證註冊了自定義適配器。此適配器提供了RemoteClientValidationRemoteRules,通常由RemoteAttribute使用。 jQuery unobtrusive驗證然後調用我的驗證操作,驗證單個字段。使用DataAnnotationsModelValidator適配器MVC3遠程驗證
但是,這種設置並不是很合適。
該屬性當前使用其ContainerType來確定要調用哪個 驗證操作。 DTO用於不同的視圖模型 不同級別的嵌套,但是,所以我們並不知道在動作上使用哪些前綴。根據ProfileDto 模型層次結構的位置,動作前綴將需要改變
驗證操作使用Request.Form.Keys去尋找哪些 財產應驗證。我知道這是最好的做法,以 遠離在行動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);
}