[英]Custom validation for a EditorTemplate ASP MVC 5
我有以下型号
public class A
{
public string Ecuation { get; set; }
...
public B B { get; set; }
}
public class B // validation attributes omitted
{
public int Number1 { get; set; }
public int Number2 { get; set; }
public int Number3 { get; set; }
}
和B
的EditorTemplate
(在其他视图中重用)
@model B
<div id="EcuationGenerator">
@Html.EditorFor(x => x.Number1)
@Html.ValidationMessageForBootstrap(x => x.Number1)
.... // ditto for other properties
<button id="sendEcuation">Fill Ecuation</button>
</div>
<script>
$('#sentEcuation').on('click', function (e) {
e.preventDefault();
$.ajax({
cache: false,
type: "POST",
url: '@Url.Action("ValidateB")',
data: $('#EcuationGenerator :input').serialize(),
dataType: "json"
})
.done(function (data) {
if (data.Valid) {
// working here about how can i get the 'Ecuation' to fill the input
return;
}
$.each(data.Errors, function (key, value) {
// The following is not working to update the error messages
if (value != null) {
key = key.replace('.', '\\.');
$(":input[name='" + key + "']").addClass("is-invalid");
key = key.replace('[', '\\['); key = key.replace(']', '\\]');
$("#Err_" + key).text(value[value.length - 1].ErrorMessage);
}
});
})
.fail(function (xhr) {
alert(xhr.responseText);
alert("Critical Error!. Failed to call the server.");
});
});
</script>
ValidationMessageForBootstrap()
扩展方法在哪里
public static MvcHtmlString ValidationMessageForBootstrap<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, object htmlAttributes = null)
{
if (expression == null) { throw new ArgumentNullException("Campo vacío"); }
string result = string.Empty;
try
{
Func<TModel, TValue> deleg = expression.Compile();
result = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression));
}
catch { }
var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
attributes["class"] += " invalid-feedback";
attributes["id"] += "Err_" + result;
TagBuilder generador = new TagBuilder("div");
generador.MergeAttributes(new RouteValueDictionary(attributes));
return new MvcHtmlString(generador.ToString());
}
主要的观点是
@model A
....
@Html.EditorFor(x => x.Ecuation, new {htmlAttributes = new { @readonly = "readonly" }})
<button class="btn btn-outline-dark rounded-right" data-keyboard="false" data-toggle="modal" data-target="#modal" id="abrirConexionado" type="button">Fill Ecuation!</i></button>
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
@Html.EditorFor(m => m.B })
</div>
</div>
</div>
</div>
当我单击模板中的按钮时,我进行了ajax调用,以将模板中的输入值发布到执行一些服务器端计算的控制器方法。 如果输入值无效,则会收到ModelState
错误并返回JsonResult
,然后将其用于更新ValidationMessageForBootstrap()
方法生成的元素中的消息。
控制器方法是
public JsonResult ValidateB(B b)
{
var valid = TryUpdateModel(b)
if(valid)
{
error = false;
//More Logic
}
return Json(new
{
EcuationResult = //logic,
Valid = valid,
Errors = getErrorsForModel()
});
}
getErrorsForModel()
方法返回IDictionary<string, object>
ModelState错误的IDictionary<string, object>
。
我的问题是,在JsonResult
中返回的属性的名称只是Number1
等,并且不包括视图中生成的全名(即B.Number1
),而我在ajax .done()
函数中的代码却没有更新消息。
如何在视图中找到正确的元素以更新错误消息?
您需要做的第一件事是删除ValidationMessageForBootstrap()
扩展方法,并使用内置的@Html.ValidationMessageFor()
正确生成客户端和服务器端验证消息的占位符。 如果检查它生成的<span>
,它具有data-valmsg-for
属性,其值是属性的全名,可用于查找与该属性关联的消息占位符。
接下来,从模板中删除脚本-脚本进入主视图或其布局,而不是局部视图。
您的EditorTemplate
应该是
@model B
<div id="EcuationGenerator">
@Html.EditorFor(x => x.Number1)
@Html.ValidationMessageFor(m => m.x.Number1) // add
... // ditto for other properties
<button type="button" id="sendEcuation">Fill Ecuation</button> // add type="button"
</div>
然后在server方法中更改代码以使用获取验证消息的集合
var errors = ModelState.Keys.Where(k => ModelState[k].Errors.Count > 0)
.Select(k => new { propertyName = k, errorMessage = ModelState[k].Errors[0].ErrorMessage });
并将其分配给JsonResult
的Errors
属性。
然后,您可以使用javascript .split()
, pop()
和.join()
方法确定属性名称的“前缀”,然后附加在错误集合中返回的propertyName
,以找到关联的输入及其消息占位符,然后更新这些元素的消息文本和类名称
然后脚本(在主视图中)将是
$('#sentEcuation').click(function() {
// Determine the prefix of the property names
var fullName = $('#EcuationGenerator').find('input').first().attr('name'); // returns "B.Number1"
var parts = fullName.split('.'); // returns [ "B", "Number1" ]
parts.pop(); // returns [ "B" ]
var prefix = parts.join('.') + '.'; returns "B."
$.ajax({
....
})
.done(function (data) {
if (data.Valid) {
// Update input with the result
$('#Ecuation').val(data.EcuationResult);
return;
}
$.each(data.Errors, function (index, item) {
var fullName = prefix + item.propertyName;
// Get the validation message placeholder
var element = $('[data-valmsg-for="' + fullName + '"]');
// Update message
element.append($('<span></span>').text(item.errorMessage));
// Update class names
element.removeClass('field-validation-valid').addClass('field-validation-error');
$('[name="' + fullName + '"]').removeClass('valid').addClass('input-validation-error');
});
})
.fail(function (xhr) {
....
});
});
为了避免不必要的ajax调用,还应该验证EditorTemplate
的输入,如果无效,则取消ajax调用。 有关仅验证模板中的表单控件的示例,请参阅关于元素组的MVC Force jQuery验证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.