C# 如何使我的自定义数据批注工作(它位于列表中,列表中的每个项目都会覆盖上一个验证测试)
我在asp.net mvc 3.0中的自定义验证遇到问题 我想让它做什么C# 如何使我的自定义数据批注工作(它位于列表中,列表中的每个项目都会覆盖上一个验证测试),c#,asp.net-mvc,validation,asp.net-mvc-3,data-annotations,C#,Asp.net Mvc,Validation,Asp.net Mvc 3,Data Annotations,我在asp.net mvc 3.0中的自定义验证遇到问题 我想让它做什么 在属性上设置(现在我只知道如何在类上设置) 要足够聪明,意识到有多个实例正在使用 场景 textbox(id=“textbox1”) 下拉列表(id=“ddl1”) textbox(id=“textbox2”) 4下拉列表(id=“ddl2”) dropdownlist中的值相同。(“天”和“分钟”) 现在用户在TextBox130中键入,并在ddl1中选择“天”。然后,他在文本框2中键入10000,在ddl2中键入“天”
[ReminderFormat(ErrorMessage = "test")]
public class ReminderViewModel
{
public List<SelectListItem> DurationTypes { get; set; }
public DurationTypes SelectedDurationType { get; set; }
public string ReminderLength { get; set; }
}
问题1
如您所见,我在类上有注释,而在提醒长度属性上有注释
问题2
现在我只有30天的时间,所以打字就少了(我以后会修改)。我现在发现的问题是,如果textbox1中有31个,那么我的验证就会失败
这是正确的。但如果textbox2的值为1,它将通过验证。这也是正确的
不正确的是,它将覆盖第一个无效验证。所以现在它认为所有的验证都通过了,并进入了我的操作方法。当它应该拒绝它并返回视图并告诉用户textbox1未通过验证时。以下是我将如何处理您的验证属性:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ReminderFormatAttribute: ValidationAttribute, IClientValidatable
{
public string DurationProperty { get; set; }
public ReminderFormatAttribute(string durationProperty)
{
DurationProperty = durationProperty;
ErrorMessage = "{0} value doesn't work for selected duration";
}
public override string FormatErrorMessage(string propName)
{
return string.Format(ErrorMessage, propName);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var durationType = validationContext.ObjectType.GetProperty(DurationProperty).GetValue(validationContext.ObjectInstance, null);
var reminderLength = value;
// Do your switch statement on durationType here
// Here is a sample of the correct return values
switch (durationType)
{
case DurationTypes.Days:
if (reminderLength > 30)
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
else
{
return null;
}
}
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "reminderformat",
};
rule.ValidationParameters["durationproperty"] = DurationProperty;
yield return rule;
}
}
当验证取决于另一个属性的值时,我通常就是这样做的。GetClientValidationRules方法是服务器端的一部分,您需要通过jQueryValidate连接到不引人注目的客户端验证中。
查看此链接了解另一个ValidationAttribute示例:
这个网站上的例子还用于编写必要的jQuery以配合客户机验证我在MVC2中的一个项目中工作,在那里我们有非常复杂的验证规则,许多规则(一些愚蠢的;-)和许多依赖性。。。。。最后,我发现使用fluent验证框架check更容易完成这种验证htt://fluentvalidation.codeplex.com@Dai-Bok-有趣的是,我看到它适用于客户端,但我没有看到任何示例。它是否使用jquery验证和通畅的javascript?@chobo2。在这一点上,我可能已经过时了,但上次我看到这一点时,没有使用复杂规则进行客户端验证的框架,特别是应用程序核心中的其他对象的依赖性。在FV中可以进行简单的客户端验证,例如最大长度、范围或正则表达式。这里是一个MVC@Dai-Bok的例子-除非它是内置的受支持的复杂验证,否则应该有。然而,如果它是定制的,那么当然不是,因为您需要构建服务器端和客户端。因此,我想知道我是否可以自己进行验证如果我使用fluent,我可以编写jquery验证部分来执行客户端吗?是的,我们提出了一个解决方案,基本上是编写自定义jquery客户端验证脚本,并将此脚本包含在需要它们的页面上。这是一个特定的jquery脚本,与我们的自定义fluentvalidation分离(打破了干式:-(两组验证的原则)。另一种方法是编写一个解析器来解析自定义fluentvalidation规则(甚至自定义数据注释)并生成验证页面所需的适当的非突兀JQuery Javascript。
// do a for loop through the viewModel ( List<ReminderViewModel> )
// generate a textbox html box and drop down list for each one
// set attribute to class for now but I want it on a property but I can't
// figure out how to get SelectedDurationType and pass it in. if I have my attribute on ReminderLength
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ReminderFormatAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
var reminderViewModel = (ReminderViewModel)value;
switch (reminderViewModel.SelectedDurationType)
{
case DurationTypes.Days:
int length = Convert.ToInt32(reminderViewModel.ReminderLength);
if (length > 30)
{
return false;
}
else
{
return true;
}
default:
throw new ArgumentOutOfRangeException();
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ReminderFormatAttribute: ValidationAttribute, IClientValidatable
{
public string DurationProperty { get; set; }
public ReminderFormatAttribute(string durationProperty)
{
DurationProperty = durationProperty;
ErrorMessage = "{0} value doesn't work for selected duration";
}
public override string FormatErrorMessage(string propName)
{
return string.Format(ErrorMessage, propName);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var durationType = validationContext.ObjectType.GetProperty(DurationProperty).GetValue(validationContext.ObjectInstance, null);
var reminderLength = value;
// Do your switch statement on durationType here
// Here is a sample of the correct return values
switch (durationType)
{
case DurationTypes.Days:
if (reminderLength > 30)
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
else
{
return null;
}
}
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "reminderformat",
};
rule.ValidationParameters["durationproperty"] = DurationProperty;
yield return rule;
}
}
[ReminderFormat("SelectedDurationType")]
public string ReminderLength { get; set; }