ASP.Net MVC 3 ViewModel,不显眼的JavaScript和自定义验证
问题描述:
我想在我的应用程序中写一个自定义验证方法 - 我有它的工作服务器端,但我试图扩展,以便它也实现不显眼的JavaScript客户端验证。我也使用视图模型,以增加乐趣。ASP.Net MVC 3 ViewModel,不显眼的JavaScript和自定义验证
下面是我作为一个微不足道的测试 - 它很简单 - 一个子对象有三个字段 - 我写的自定义验证是至少有一个字段必须填写(显然我的实际应用程序有一个比这显著更复杂的模型):
型号:
public class Child
{
public int Id { get; set; }
[MustHaveFavouriteValidator("FavouritePudding", "FavouriteGame")]
public string FavouriteToy { get; set; }
public string FavouritePudding { get; set; }
public string FavouriteGame { get; set; }
}
视图模型:
public class ChildViewModel
{
public Child theChild { get; set; }
}
控制器:
public ActionResult Create()
{
var childViewModel = new PeopleAgeGroups.ViewModels.ChildViewModel();
return View(childViewModel);
}
我已经按照什么documentatation我可以在网上找到,并刮起了自定义的验证,看起来像这样:
public class MustHaveFavouriteValidator:ValidationAttribute, IClientValidatable
{
private const string defaultError = "You must have one favourite";
public string firstOtherFavourite { get; set; }
public string secondOtherFavourite { get; set; }
public MustHaveFavouriteValidator(string firstFave, string secondFave)
: base(defaultError)
{
firstOtherFavourite = firstFave;
secondOtherFavourite = secondFave;
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name, firstOtherFavourite, secondOtherFavourite);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var aFavouriteObject = validationContext.ObjectInstance.GetType().GetProperty(firstOtherFavourite);
var bFavouriteObject = validationContext.ObjectInstance.GetType().GetProperty(secondOtherFavourite);
var aFavourite = aFavouriteObject.GetValue(validationContext.ObjectInstance, null);
var bFavourite = bFavouriteObject.GetValue(validationContext.ObjectInstance, null);
if(value==null && aFavourite ==null && bFavourite == null){
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName), new[] { validationContext.MemberName, aFavouriteObject.Name, bFavouriteObject.Name });
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
return new[] { new MustHaveFavourite(FormatErrorMessage(metadata.GetDisplayName()), firstOtherFavourite, secondOtherFavourite) };
}
}
好东西,我的服务器端验证工作。 接下来我有模型客户验证规则:
public class MustHaveFavourite : ModelClientValidationRule
{
public MustHaveFavourite(string errorMessage, string firstotherfavourite, string secondotherfavourite)
{
ErrorMessage = errorMessage;
ValidationType = "musthavefavourite";
ValidationParameters.Add("firstotherfavourite", firstotherfavourite);
ValidationParameters.Add("secondotherfavourite", secondotherfavourite);
}
}
终于,我的自定义JavaScript来将其结合在一起:
(function ($) {
jQuery.validator.addMethod("musthavefavourite", function (value, element, params) {
var $firstOtherFavouriteObject = $('#' + params.firstotherfavourite);
var firstOtherFavourite = $firstOtherFavouriteObject.val();
var $secondOtherFavouriteObject = $('#' + params.secondotherfavourite);
var secondOtherFavourite = $secondOtherFavouriteObject.val();
if (value == '' && firstOtherFavourite == '' && secondOtherFavourite == '') {
return false;
} else {
return true;
}
});
$.validator.unobtrusive.adapters.add("musthavefavourite", ["firstotherfavourite", "secondotherfavourite"],
function (options) {
options.rules['musthavefavourite'] = {
firstotherfavourite: options.params.firstotherfavourite,
secondotherfavourite: options.params.secondotherfavourite
};
options.messages['musthavefavourite'] = options.mesage;
}
);
} (jQuery));
,发生的问题是,在生成的HTML,我得到我的文本元素的ID为前缀“theChild_” - 这是有道理的,因为我的viewmodel声明了一个Child对象,但是,我的自定义函数在元素名称上没有前缀。有没有办法通过对JavaScript来传递前缀,而无需实际黑客它看起来像这样:
jQuery.validator.addMethod("musthavefavourite", function (value, element, params) {
var $firstOtherFavouriteObject = $('#theChild_' + params.firstotherfavourite);
var firstOtherFavourite = $firstOtherFavouriteObject.val();
这在我的脑海里那种失败创建我的验证服务器端,然后钩住这些额外gumf的想法直到经过不显眼的验证,因为我创建了一段只能真正与form/viewmodel组合使用的javascript。
答
您可以修改您的验证器以检查任何前缀,并将前缀添加到要检查的元素的选择器中,如我在回答此问题时概述的那样:MVC3 custom validation: compare two dates。您需要(1)将选择器更改为按名称而不是按ID搜索,或者(2)使用_
而不是.
来拆分ID。