我为验证消息的输出编写了一个自定义的HTTML帮助程序标记。它可以正常运行,但是始终存在。
@Html.MyValidationMsg(m => m.FirstName)
public static IHtmlContent MyValidationMsg<TModel, TProperty>(this IHtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
var reqAttrib = memberExpression.Member
.GetCustomAttributes(typeof(RequiredAttribute), false)
.Cast<RequiredAttribute>()
.SingleOrDefault();
var displayAttrib = memberExpression.Member
.GetCustomAttributes(typeof(DisplayAttribute), false)
.Cast<DisplayAttribute>()
.SingleOrDefault();
var errMsg = reqAttrib.ErrorMessage ?? displayAttrib.Name + " is required.";
var content = new HtmlContentBuilder()
.AppendHtml("<div class=\"rvt-inline-alert rvt-inline-alert--standalone rvt-inline-alert--danger\">")
.AppendHtml("<span class=\"rvt-inline-alert__icon\">")
.AppendHtml("<svg aria-hidden=\"true\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\">")
.AppendHtml("<g fill=\"currentColor\">")
.AppendHtml("<path d=\"M8,0a8,8,0,1,0,8,8A8,8,0,0,0,8,0ZM8,14a6,6,0,1,1,6-6A6,6,0,0,1,8,14Z\" />")
.AppendHtml("<path d=\"M10.83,5.17a1,1,0,0,0-1.41,0L8,6.59,6.59,5.17A1,1,0,0,0,5.17,6.59L6.59,8,5.17,9.41a1,1,0,1,0,1.41,1.41L8,9.41l1.41,1.41a1,1,0,0,0,1.41-1.41L9.41,8l1.41-1.41A1,1,0,0,0,10.83,5.17Z\"/>")
.AppendHtml("</g>")
.AppendHtml("</svg>")
.AppendHtml("</span>")
.AppendHtml("<span class=\"rvt-inline-alert__message\" role=\"alert\" id=\"radio-list-message\">")
.AppendHtml(errMsg)
.AppendHtml("</span>")
.AppendHtml("</div>");
return content;
}
我如何在“剃刀页面”初始加载时将其隐藏,并且当该字段无效时使其显示?
谢谢您的帮助
答案 0 :(得分:1)
总是出现此消息有两个原因。
就像@Sonal Borkar所说的那样,第一个原因是您的var errMsg = reqAttrib.ErrorMessage ?? displayAttrib.Name + " is required."
即使没有[Required]
属性,也要使其返回一些值。
但是不要将其更改为var errMsg = reqAttrib.ErrorMessage != null ? displayAttrib.Name + " is required."
,因为reqAttrib
可能是null
。相反,您可以按以下方式更改代码:
var errMsg = reqAttrib==null ?
"":
reqAttrib?.ErrorMessage ?? displayName + " is required.";
其次,您忘记了检查当前属性是否已经有值。假设我们有一个装饰了[Required]
属性的属性,并且确实分配了一个值,那么我们就不应该显示诸如“要求xxx”之类的消息。
此外,您的代码中还有null object reference
的其他错误:
var displayAttrib = memberExpression.Member
.GetCustomAttributes(typeof(DisplayAttribute), false)
.Cast<DisplayAttribute>()
.SingleOrDefault();
var errMsg = reqAttrib.ErrorMessage ?? displayAttrib.Name + " is required.";
reqAttrib
可能是null
,所以reqAttrib.ErrorMessage
可能会抛出错误。displayAttrib
也可能是null
displayAttrib
为空,我们应该退回到memberExpression.Member.Name
要修复错误,请按如下所示更改代码:
public static IHtmlContent MyValidationMsg<TModel, TProperty>(this IHtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
var reqAttrib = memberExpression.Member
.GetCustomAttributes(typeof(RequiredAttribute), false)
.Cast<RequiredAttribute>()
.SingleOrDefault();
var contentBuilder = new HtmlContentBuilder();
// if the current property has no [Required] attribute, there's no need to display required message
if(reqAttrib == null ){return contentBuilder; }
// check the value of current property
var compiled = expression.Compile();
var model = (TModel) helper.ViewData.Model ;
if(model == null){
throw new Exception("No Model associated with the view !");
}
var propValue = (TProperty) compiled.Invoke(model);
// I just test nullable props here, you might custom it to fulfill your requirements, eg : whether the length of string matches
if(propValue != null){ return contentBuilder; }
var member = memberExpression.Member;
var displayName= member
.GetCustomAttributes(typeof(DisplayAttribute), false)
.Cast<DisplayAttribute>()
.SingleOrDefault()
?.Name // might be null
?? member.Name; // fall back
var errMsg = reqAttrib==null ?
"":
reqAttrib?.ErrorMessage ?? displayName + " is required.";
if(String.IsNullOrEmpty(errMsg)){ return contentBuilder; }
return contentBuilder
.AppendHtml("<div class=\"rvt-inline-alert rvt-inline-alert--standalone rvt-inline-alert--danger\">")
.AppendHtml("<span class=\"rvt-inline-alert__icon\">")
.AppendHtml("<svg aria-hidden=\"true\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\">")
.AppendHtml("<g fill=\"currentColor\">")
.AppendHtml("<path d=\"M8,0a8,8,0,1,0,8,8A8,8,0,0,0,8,0ZM8,14a6,6,0,1,1,6-6A6,6,0,0,1,8,14Z\" />")
.AppendHtml("<path d=\"M10.83,5.17a1,1,0,0,0-1.41,0L8,6.59,6.59,5.17A1,1,0,0,0,5.17,6.59L6.59,8,5.17,9.41a1,1,0,1,0,1.41,1.41L8,9.41l1.41,1.41a1,1,0,0,0,1.41-1.41L9.41,8l1.41-1.41A1,1,0,0,0,10.83,5.17Z\"/>")
.AppendHtml("</g>")
.AppendHtml("</svg>")
.AppendHtml("</span>")
.AppendHtml("<span class=\"rvt-inline-alert__message\" role=\"alert\" id=\"radio-list-message\">")
.AppendHtml(errMsg)
.AppendHtml("</span>")
.AppendHtml("</div>");
}
答案 1 :(得分:1)
非常感谢@itminus ,抽出宝贵的时间让我走上正确的路。
我最终完全放弃了这条路,而赞成重写jquery.validate。还使用javascript / jquery处理DOM以获得所需的结果。
所需的错误消息输出:
<div class="rvt-inline-alert rvt-inline-alert--danger">
<span class="rvt-inline-alert__icon">
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true">
<g fill="currentColor">
<path d="M8,0a8,8,0,1,0,8,8A8,8,0,0,0,8,0ZM8,14a6,6,0,1,1,6-6A6,6,0,0,1,8,14Z"/>
<path d="M10.83,5.17a1,1,0,0,0-1.41,0L8,6.59,6.59,5.17A1,1,0,0,0,5.17,6.59L6.59,8,5.17,9.41a1,1,0,1,0,1.41,1.41L8,9.41l1.41,1.41a1,1,0,0,0,1.41-1.41L9.41,8l1.41-1.41A1,1,0,0,0,10.83,5.17Z"/>
</g>
</svg>
</span>
<span class="rvt-inline-alert__message" role="alert">Your Name is required.</span>
</div>
输入_ValidationScriptsPartial.cshtml
中的代码以达到神奇效果:
<script type="text/javascript">
var settings = {
errorElement: "span",
errorClass: "rvt-validation-danger", //around textbox on error
errorPlacement: function (error, element) {
var avg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
avg.setAttribute("width", "16");
avg.setAttribute("height", "16");
avg.setAttribute("viewBox", "0 0 16 16");
avg.setAttribute("aria-hidden", "true");
var g = document.createElement("g");
g.setAttribute("fill", "currentColor");
var p1 = document.createElement("path");
p1.setAttribute("d", "M8,0a8,8,0,1,0,8,8A8,8,0,0,0,8,0ZM8,14a6,6,0,1,1,6-6A6,6,0,0,1,8,14Z");
var p2 = document.createElement("path");
p2.setAttribute("d", "M10.83,5.17a1,1,0,0,0-1.41,0L8,6.59,6.59,5.17A1,1,0,0,0,5.17,6.59L6.59,8,5.17,9.41a1,1,0,1,0,1.41,1.41L8,9.41l1.41,1.41a1,1,0,0,0,1.41-1.41L9.41,8l1.41-1.41A1,1,0,0,0,10.83,5.17Z");
g.appendChild(p1);
g.appendChild(p2);
avg.appendChild(g);
var spanIcon = document.createElement("span");
spanIcon.setAttribute("class", "rvt-inline-alert__icon");
spanIcon.innerHTML += avg.outerHTML;
var spanMsg = document.createElement("span");
spanMsg.setAttribute("class", "rvt-inline-alert__message");
spanMsg.setAttribute("role", "alert");
spanMsg.innerHTML += error[0].innerHTML;
var c = document.createElement("div");
c.setAttribute("class", "rvt-inline-alert rvt-inline-alert--danger");
c.innerHTML += spanIcon.outerHTML + spanMsg.outerHTML;
error.replaceWith(c);
}
};
$.validator.unobtrusive.options = settings;
</script>