繁体   English   中英

自定义验证EditorTemplate ASP MVC 5

[英]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; }
}

BEditorTemplate (在其他视图中重用)

@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 });

并将其分配给JsonResultErrors属性。

然后,您可以使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM