为什么我的 JQuery 自定义数据验证在提交时没有执行?

Why my JQuery custom data validation don't get executed on submit?

我想弄清楚为什么当我按下下面的 "submit"(即分享)按钮时我的自定义验证(即 IsEmailValid 方法)没有被执行。 Required 执行得很好,但我的自定义验证属性 - IsEmailAttribute 没有被调用。有人可以指点一下吗。

那是我的 index.cshtml 我的表单是通过 Html.RenderPartial:

呈现的
@using System.Security.Principal
@using DNAAnalysisCore.Resources
@model DNAAnalysisCore.ViewModels.WorkbookViewModel

@section BodyFill
    {
    <div id="shareFormContainer">
        @{ Html.RenderPartial("_ShareView", new WorkbookShareModel());}
    </div>

    <table class="table">
        <tbody>
        @foreach (var workbook in Model.Workbooks)
        {
            <tr class="@trClassName">
                <td>@Html.ActionLink(linkText, "Open", "OpenAnalytics", new { id = Model.Id, workbook = workbook.Name })</td>
                <td class="last-modified-date" title="Last Modified Date">@workbook.ModifiedDate.ToShortDateString()</td>
                <td class="share">
                    <button title="Share" class="share-button" onclick='showSharingView("@workbook.Name", "@workbook.Id", "@Model.Id")'>&nbsp;</button>
                </td>
            </tr>
        }
        </tbody>
    </table>
}

@section Scripts
    {
    <!--Load JQuery 'unobtrusive' validation -->
    @await Html.PartialAsync("_ValidationScriptsPartial")
    <script type="text/javascript">

        function showSharingView(title, workbookId, id) {            
            var isEmailAdapterName = 'isEmail';        
            $('#shareFormModal').modal("show");

            // client-side email validation
            $.validator.addMethod(isEmailAdapterName, IsEmailValid);
            // register the 'isEmail' attribute with the 'unobtrusive' validation
            $.validator.unobtrusive.adapters.add(isEmailAdapterName,
                [],
                function(options) {
                    // add a 'isEmail' rule to the options so that JQuery can find it when it's checking the rules collection
                    options.rules.isEmail = {};
                    // add a message for the 'isEmail' rule ('message' will have the 'ShareModel' attribute 'ErrorMessage' value)
                    options.messages[isEmailAdapterName] = options.message;
                });
        }

        function hideDialog() {
            var form = $("#partialform");
            // only hide the dialog if the form is valid
            if (form.valid()) {
                $('#shareFormModal').modal("hide");
            }
        }

        // Helper method that validates list of emails
        function IsEmailValid(emailList, element, parameters) {
            // EMAIL VALIDATION LOGIC HERE
        }
    </script>
}

那是我的模特:

public class WorkbookShareModel
{
    [HiddenInput]
    public string Id { get; set; }
    [HiddenInput] 
    public string WorkbookId { get; set; }
    [HiddenInput]
    public string Title { get; set; }
    [Required(ErrorMessageResourceType = typeof(Resources.BaseLanguage), ErrorMessageResourceName = "Email_Requirement_Warning")]
    [IsEmailAttribute(ErrorMessageResourceType = typeof(Resources.BaseLanguage), ErrorMessageResourceName = "Email_Invalid_Message")]
    public IList<string> Emails { get; set; }
}

public class IsEmailAttribute : ValidationAttribute, IClientModelValidator
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var share = (WorkbookShareModel)validationContext.ObjectInstance;

        foreach (var email in share.Emails)
        {
            var convertedEmail = email.Trim().ToLower();
            var match = Regex.Match(convertedEmail, Constants.EmailPattern);
            // if one of the emails does not match the pattern, break out of the look and return the error message
            if (!match.Success)
                return new ValidationResult(ErrorMessage);
        }

        return ValidationResult.Success;
    }

    public void AddValidation(ClientModelValidationContext context)
    {
        MergeAttribute(context.Attributes, "data-val", "true");
        var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
        MergeAttribute(context.Attributes, "data-val-isEmail", errorMessage);
    }

    private void MergeAttribute(IDictionary<string, string> attributes, string key, string value)
    {
        if (attributes.ContainsKey(key))
            return;

        attributes.Add(key, value);
    }
}
}

这是我的表格:

@using DNAAnalysisCore.Resources
@model DNAAnalysisCore.Models.WorkbookShareModel

<!-- Modal -->
<div onclick="activateShareButtons()" class="modal fade" id="shareFormModal" role="dialog">
    <div class="modal-dialog modal-md">
        <!-- Modal content-->
        <div class="modal-content">
            <div class="modal-header">
                <h4 id="dialogDisplayTitle" class="modal-title">THIS VALUE IS SET VIA JAVASCRIPT</h4>
            </div>

            @using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post, new { @id = "partialform" }))
            {
                <div class="modal-body">

                    <label>@BaseLanguage.Share_workbook_Instruction_text</label>
                    <div class="form-group">
                        <textarea class="form-control" asp-for="Emails" rows="4" cols="50" placeholder="@BaseLanguage.ShareDialogPlaceholder"></textarea>
                        <span asp-validation-for="Emails" class="text-danger"></span>
                    </div>

                    <input asp-for="Title" />
                    <input asp-for="Id" />
                    <input asp-for="WorkbookId"/>
                </div>
                <div class="modal-footer">
                    <button onclick="hideDialog()" type="submit" class="btn btn-primary">Share</button>
                    <button onclick="activateShareButtons()" id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                </div>
            }

        </div>
    </div>
</div>

我设法通过将 $.validator.addMethod$.validator.unobtrusive.adapters.add 方法调用移到 showSharingView 方法之外解决了我的问题。那行得通并且我的自定义错误显示正确。但是,我不确定为什么:

<script type="text/javascript">

    var isEmailAdapterName = 'isEmail';
    // client-side email validation
    $.validator.addMethod(isEmailAdapterName, IsEmailValid);
    // register the 'isEmail' attribute with the 'unobtrusive' validation
    $.validator.unobtrusive.adapters.add(isEmailAdapterName,
        [],
        function(options) {
            // add a 'isEmail' rule to the options so that JQuery can find it when it's checking the rules collection
            options.rules[isEmailAdapterName] = {};
            // add a message for the 'isEmail' rule ('message' will have the 'ShareModel' attribute 'ErrorMessage' value)
            options.messages[isEmailAdapterName] = options.message;
        });

    function showSharingView(title, workbookId, id) {
        $('.share-button').prop('disabled', true); // Disable all share buttons to avoid opening multiple dialogs
        // reset the 'Emails' textarea 
        $('#Emails').val('');
        // set the dialog's control values
        $('#Title').val(title);
        $('#Id').val(id);
        $('#WorkbookId').val(workbookId);
        // set the dialog's title 
        $('#dialogDisplayTitle').html("Share Workbook - " + title);

        $('#shareFormModal').modal("show");
    }