Как проверить одно поле, связанное со значением другого, в ASP .NET MVC 3 - PullRequest
15 голосов
/ 18 января 2012

У меня было два поля, например, номер телефона и номер мобильного телефона.Что-то вроде ..

    [Required]
    public string Phone { get; set; }

    [Required]
    public string Mobile{ get; set; }

Но пользователь может вводить данные в любой из них.Один является обязательным.Как их обрабатывать, т.е. как отключить обязательный валидатор поля для одного поля, когда пользователь вводит данные в другое поле и наоборот.В каком случае я должен обработать это в javascript и какие сценарии мне нужно добавить для этого.Может кто-нибудь, пожалуйста, помогите найти решение ...

Ответы [ 2 ]

41 голосов
/ 18 января 2012

Одна возможность - написать пользовательский атрибут проверки:

public class RequiredIfOtherFieldIsNullAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string _otherProperty;
    public RequiredIfOtherFieldIsNullAttribute(string otherProperty)
    {
        _otherProperty = otherProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(_otherProperty);
        if (property == null)
        {
            return new ValidationResult(string.Format(
                CultureInfo.CurrentCulture, 
                "Unknown property {0}", 
                new[] { _otherProperty }
            ));
        }
        var otherPropertyValue = property.GetValue(validationContext.ObjectInstance, null);

        if (otherPropertyValue == null || otherPropertyValue as string == string.Empty)
        {
            if (value == null || value as string == string.Empty)
            {
                return new ValidationResult(string.Format(
                    CultureInfo.CurrentCulture,
                    FormatErrorMessage(validationContext.DisplayName),
                    new[] { _otherProperty }
                ));
            }
        }

        return null;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "requiredif",
        };
        rule.ValidationParameters.Add("other", _otherProperty);
        yield return rule;
    }
}

, которое вы примените к одному из свойств модели представления:

public class MyViewModel
{
    [RequiredIfOtherFieldIsNull("Mobile")]
    public string Phone { get; set; }

    public string Mobile { get; set; }
}

тогда у вас может быть контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

и, наконец, представление, в котором вы зарегистрируете адаптер для подключения проверки на стороне клиента для этого пользовательского правила:

@model MyViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
    jQuery.validator.unobtrusive.adapters.add(
        'requiredif', ['other'], function (options) {

            var getModelPrefix = function (fieldName) {
                return fieldName.substr(0, fieldName.lastIndexOf('.') + 1);
            }

            var appendModelPrefix = function (value, prefix) {
                if (value.indexOf('*.') === 0) {
                    value = value.replace('*.', prefix);
                }
                return value;
            }

            var prefix = getModelPrefix(options.element.name),
                other = options.params.other,
                fullOtherName = appendModelPrefix(other, prefix),
                element = $(options.form).find(':input[name="' + fullOtherName + '"]')[0];

            options.rules['requiredif'] = element;
            if (options.message) {
                options.messages['requiredif'] = options.message;
            }
        }
    );

    jQuery.validator.addMethod('requiredif', function (value, element, params) {
        var otherValue = $(params).val();
        if (otherValue != null && otherValue != '') {
            return true;
        }
        return value != null && value != '';
    }, '');
</script>

@using (Html.BeginForm())
{
    <div>
        @Html.LabelFor(x => x.Phone)
        @Html.EditorFor(x => x.Phone)
        @Html.ValidationMessageFor(x => x.Phone)
    </div>

    <div>
        @Html.LabelFor(x => x.Mobile)
        @Html.EditorFor(x => x.Mobile)
        @Html.ValidationMessageFor(x => x.Mobile)
    </div>

    <button type="submit">OK</button>
}

Довольно больные вещи для чего-то настолько простого, как правило валидации, с которым мы сталкиваемся в нашей повседневной жизни. Я не знаю, о чем думали разработчики ASP.NET MVC, когда решили выбрать декларативный подход для проверки вместо императивного.

В любом случае, поэтому я использую FluentValidation.NET вместо аннотаций данных для проверки моих моделей. Реализация таких простых сценариев проверки реализована так, как должно быть - просто.

10 голосов
/ 11 марта 2014

Я знаю, что этот вопрос не очень острый, потому что его задавали относительно давно, тем не менее, я собираюсь поделиться с немного другой идеей решения такой проблемы.Я решил реализовать механизм, который предоставляет условные атрибуты для вычисления результатов проверки на основе значений других свойств и отношений между ними, которые определены в логических выражениях.

Ваша проблема может быть определена и автоматически решена с помощью следующих аннотаций:

[RequiredIf("Mobile == null",
    ErrorMessage = "At least email or phone should be provided.")]
public string Phone{ get; set; }

[RequiredIf("Phone == null",
    ErrorMessage = "At least email or phone should be provided.")]
public string Mobile { get; set; }

Если вы считаете, что это будет полезно для ваших целей, дополнительную информацию о библиотеке ExpressiveAnnotations можно найти здесь .Проверка на стороне клиента также поддерживается "из коробки".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...