Как настроить проверку на стороне клиента для пользовательского атрибута RequiredIf для Asp.NET Core 3.0

Мне не удалось запустить мой метод проверки на стороне клиента после настройки проверки в соответствии с различными источниками. После долгих усилий я обнаружил, что изменение порядка загрузки скриптов решило проблему. Я предоставил ответ, чтобы показать полную настройку пользовательского атрибута RequiredIf для asp.net core 3.0 MVC. Надеюсь, это сэкономит другим людям драгоценное время.




Ответы (1)


Создайте новый класс, наследующий ValidationAttribute и IClientModelValidator:

    public class RequiredIfAttribute : ValidationAttribute, IClientModelValidator
    {
        private string PropertyName { get; set; }

        private object DesiredValue { get; set; }

        public RequiredIfAttribute(string propertyName, object desiredvalue)
        {
            PropertyName = propertyName;
            DesiredValue = desiredvalue;
        }

        protected override ValidationResult IsValid(object value, ValidationContext context)
        {
            object instance = context.ObjectInstance;
            Type type = instance.GetType();
            object propertyvalue = type.GetProperty(PropertyName).GetValue(instance, null);

            if ((value == null && propertyvalue == DesiredValue) || (value == null && propertyvalue != null && propertyvalue.Equals(DesiredValue)))
            {
                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-requiredif", errorMessage);
            MergeAttribute(context.Attributes, "data-val-requiredif-otherproperty", PropertyName);
            MergeAttribute(context.Attributes, "data-val-requiredif-otherpropertyvalue", DesiredValue == null? "": DesiredValue.ToString());
        }

        private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
        {
            if (attributes.ContainsKey(key))
            {
                return false;
            }
            attributes.Add(key, value);
            return true;
        }
    }
}

Примените атрибут в своей модели в качестве аннотации над своим свойством:

[Display(Name = "Effective Date Column Name")]
[RequiredIf("EffectiveDate", null, ErrorMessage = "Effective Date Column Name is required or Enter an Effective Date.")]
public string ColumnNameEffectiveDate { get; set; }

[Display(Name = "Enter Effective Date")]
public DateTime? EffectiveDate { get; set; }

Добавьте элементы проверки в свой html:

<fieldset>
    <legend class="w-auto">Step 4: Set Effective Date</legend>
    <div class="form-row">
        <div class="form-group col-12">
            <small class="form-text">Select the name of the date column to import, or enter a date.</small>
        </div>
        <div class="form-group col-12 col-lg-4 columnheader">
            <label asp-for="@Model.ColumnNameEffectiveDate" class="slightlyBold"></label>
            <select class="form-control selectpicker"
                    asp-for="@Model.ColumnNameEffectiveDate">
                <option value="">Nothing selected</option>
            </select>
            <span asp-validation-for="@Model.ColumnNameEffectiveDate" class="text-danger"></span> <==== HERE
        </div>
        <div class="form-group col-12 col-lg-2 text-center">
            <label class="slightlyBold pt-4">OR</label>
        </div>
        <div class="form-group col-12 col-lg-4">
            <label asp-for="@Model.EffectiveDate" class="slightlyBold">Enter Effective Date:</label>
            <input type="text" class="datepicker form-control" asp-for="@Model.EffectiveDate">
        </div>
    </div>
</fieldset>

Во время выполнения HTML изменится, чтобы включить теги проверки:

<select class="form-control selectpicker" data-val="true" data-val-requiredif="Effective Date Column Name is required or Enter an Effective Date." data-val-requiredif-otherproperty="EffectiveDate" data-val-requiredif-otherpropertyvalue="" id="ColumnNameEffectiveDate" name="ColumnNameEffectiveDate" disabled="disabled">
    <option value="">Nothing selected</option>
</select>

Создайте файл javascript, который добавит новое правило в ненавязчивый адаптер (я назвал свой файл customValidationRules.js):

$(function () {

    jQuery.validator.unobtrusive.adapters.add("requiredif", ["otherproperty", "otherpropertyvalue"],
        function (options) {
            options.rules["requiredif"] = options.params;
            options.messages["requiredif"] = options.message
        });

}(jQuery));

и второй файл для запуска метода для этого правила (я назвал свой файл customValidationMethods.js):

(function ($) {
    jQuery.validator.addMethod("requiredif",
        function (value, element, parameters) {

            var targetId = parameters.otherproperty;
            var targetValue = parameters.otherpropertyvalue;

            var otherpropertyvalue = (targetValue == null || targetValue == undefined ? "" : targetValue).toString();

            var otherpropertyElement = $('#' + targetId);

            if (!value.trim() && otherpropertyElement.val() == otherpropertyvalue) {
                var isValid = $.validator.methods.required.call(this, value, element, parameters);
                return isValid;
            }

            return true;
        }
    );
})(jQuery);

Обязательно укажите ссылки на необходимые сценарии проверки для страницы. Порядок сценариев - это то, что заставило мою проверку на стороне клиента начать работу для пользовательского атрибута:

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-ajax-unobtrusive/dist/jquery.unobtrusive-ajax.js"></script>
@*These 4 validation scripts must not be changed*@
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script> <==== HERE
<script src="~/js/customValidationMethods.js"></script> <==== HERE
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script> <==== HERE
<script src="~/js/customValidationRules.js"></script> <==== HERE
@*These 4 validation scripts must not be changed*@
<script src="~/lib/popper.js/umd/popper.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>

person Kellie    schedule 01.09.2020