Ale*_*lex 48 javascript c# validation asp.net-mvc
有时用户输入并非严格无效,但可能会被视为有问题.
例如:
Name
字段中输入长句子.他可能应该使用该Description
字段.Name
内容与现有实体非常相似.也许他正在输入相同的实体,但没有意识到它已经存在,或者某些并发用户刚刚输入它.其中一些可以在客户端轻松检查,一些需要服务器端检查.
在这种情况下DataAnnotations
,为验证用户提供警告的最佳方法是什么?这里的关键是用户必须能够覆盖警告并仍然提交表单(或重新提交表单,具体取决于实现).
想到的最可行的解决方案是创建一些类似于a的属性,CustomValidationAttribute
它可以进行AJAX调用并显示一些警告文本,但不会影响ModelState
.预期用途是:
[WarningOnFieldLength(MaxLength = 150)]
[WarningOnPossibleDuplicate()]
public string Name { get; set; }
Run Code Online (Sandbox Code Playgroud)
在视图中:
@Html.EditorFor(model => model.Name)
@Html.WarningMessageFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
Run Code Online (Sandbox Code Playgroud)
那么,有什么想法吗?
Ser*_*lov 48
整体设计
首先,我相信如果用户选择忽略警告,你必须以某种方式跟踪.一种简单而透明的方法是使用" 忽略警告"复选框,用户必须在提交之前进行检查.另一种选择是让他们两次提交表格并忽略第二次提交时的警告; 然后你可能需要一个IgnoreWarnings隐藏字段.可能还有其他设计,但为了简单起见,我将选择第一个选项.
简而言之,方法是创造
请注意,下面的代码只是说明了这种方法,在不知道完整的上下文的情况下我必须承担很多事情.
查看模型
在这种情况下,最好将视图模型与实际模型分开,这无论如何都是一个好主意.一种可能的方法是为所有支持警告的视图模型提供基类:
public abstract class BaseViewModel
{
public bool IgnoreWarnings { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
模型需要分离的关键原因是将IgnoreWarnings
属性存储在数据库中没有多大意义.
您的派生视图模型将如下所示:
public class YourViewModel : BaseViewModel
{
[Required]
[StringLengthWarning(MaximumLength = 5, ErrorMessage = "Your Warning Message")]
public string YourProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
StringLengthWarning
是服务器和客户端验证的自定义数据注释属性.它只支持最大长度,并可以轻松扩展任何其他必要的属性.
数据注释属性
属性的核心是IsValid(value, validationContext
方法.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class StringLengthWarningAttribute : ValidationAttribute, IClientValidatable
{
public int MaximumLength { get; set; }
public override bool IsValid(object value)
{
return true;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var model = validationContext.ObjectInstance as BaseViewModel;
var str = value as string;
if (!model.IgnoreWarnings && (string.IsNullOrWhiteSpace(str) || str.Length > MaximumLength))
return new ValidationResult(ErrorMessage);
return base.IsValid(value, validationContext);
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new StringLengthWarningValidationRule(MaximumLength, ErrorMessage);
}
}
Run Code Online (Sandbox Code Playgroud)
该属性实现IClientValidatable
并使用自定义客户端验证规则:
public class StringLengthWarningValidationRule : ModelClientValidationRule
{
public StringLengthWarningValidationRule(int maximumLength, string errorMessage)
{
ErrorMessage = errorMessage;
ValidationType = "stringlengthwarning";
ValidationParameters.Add("maximumlength", maximumLength);
ValidationParameters.Add("ignorewarningsfield", "IgnoreWarnings");
}
}
Run Code Online (Sandbox Code Playgroud)
客户端JavaScript
最后,要使其工作,您需要从视图中引用以下JavaScript:
$(function () {
$.validator.addMethod('stringlengthwarning', function (value, element, params) {
var maximumlength = params['maximumlength'];
var ignorewarningsfield = params['ignorewarningsfield'];
var ctl = $("#" + ignorewarningsfield);
if (ctl == null || ctl.is(':checked'))
return true;
return value.length <= maximumlength;
});
$.validator.unobtrusive.adapters.add("stringlengthwarning", ["maximumlength", "ignorewarningsfield"], function (options) {
var value = {
maximumlength: options.params.maximumlength,
ignorewarningsfield: options.params.ignorewarningsfield
};
options.rules["stringlengthwarning"] = value;
if (options.message) {
options.messages["stringlengthwarning"] = options.message;
}
});
}(jQuery));
Run Code Online (Sandbox Code Playgroud)
JavaScript会做一些您可能想要重新访问的假设(复选框名称等).
更新:HTML助手
要分别显示错误和警告的验证消息,需要几个帮助程序.以下类提供了一个示例:
public static class MessageHelpers
{
public static MvcHtmlString WarningMessageFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
if (htmlHelper.ViewData.ModelState["IgnoreWarnings"] != null)
return htmlHelper.ValidationMessageFor(expression);
return MvcHtmlString.Empty;
}
public static MvcHtmlString ErrorMessageFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
if (htmlHelper.ViewData.ModelState["IgnoreWarnings"] == null)
return htmlHelper.ValidationMessageFor(expression);
return MvcHtmlString.Empty;
}
}
Run Code Online (Sandbox Code Playgroud)
在视图中,它们可以照常使用:
@Html.EditorFor(model => model.YourProperty)
@Html.ErrorMessageFor(model => model.YourProperty)
@Html.WarningMessageFor(model => model.YourProperty)
Run Code Online (Sandbox Code Playgroud)