Модель MVC требует истинного - PullRequest
72 голосов
/ 19 января 2011

Есть ли способ аннотации данных требовать, чтобы булево свойство было установлено в true?

public class MyAwesomeObj{
    public bool ThisMustBeTrue{get;set;}
}

Ответы [ 16 ]

125 голосов
/ 27 января 2012

Я бы создал валидатор как для сервера, так и для клиента. Используя MVC и ненавязчивую проверку форм, это можно сделать, просто выполнив следующее:

Во-первых, создайте класс в своем проекте для выполнения проверки на стороне сервера следующим образом:

public class EnforceTrueAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        if (value == null) return false;
        if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");
        return (bool)value == true;
    }

    public override string FormatErrorMessage(string name)
    {
        return "The " + name + " field must be checked in order to continue.";
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = String.IsNullOrEmpty(ErrorMessage) ? FormatErrorMessage(metadata.DisplayName) : ErrorMessage,
            ValidationType = "enforcetrue"
        };
    }
}

После этого аннотируйте соответствующее свойство в вашей модели:

[EnforceTrue(ErrorMessage=@"Error Message")]
public bool ThisMustBeTrue{ get; set; }

И, наконец, включите проверку на стороне клиента, добавив следующий скрипт в представление:

<script type="text/javascript">
    jQuery.validator.addMethod("enforcetrue", function (value, element, param) {
        return element.checked;
    });
    jQuery.validator.unobtrusive.adapters.addBool("enforcetrue");
</script>

Примечание. Мы уже создали метод GetClientValidationRules, который помещает нашу аннотацию в представление из нашей модели.

Если вы используете файлы ресурсов для сообщения об ошибке интернационализации, удалите вызов FormatErrorMessage (или просто вызовите базу) и настройте метод GetClientValidationRules следующим образом:

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
    string errorMessage = String.Empty;
    if(String.IsNullOrWhiteSpace(ErrorMessage))
    {
        // Check if they supplied an error message resource
        if(ErrorMessageResourceType != null && !String.IsNullOrWhiteSpace(ErrorMessageResourceName))
        {
            var resMan = new ResourceManager(ErrorMessageResourceType.FullName, ErrorMessageResourceType.Assembly);
            errorMessage = resMan.GetString(ErrorMessageResourceName);
        }
    }
    else
    {
        errorMessage = ErrorMessage;
    }

    yield return new ModelClientValidationRule
    {
        ErrorMessage = errorMessage,
        ValidationType = "enforcetrue"
    };
}
78 голосов
/ 19 июля 2013

Я знаю, что это старый пост, но хотел поделиться простым серверным способом сделать это.Вы создаете публичное свойство со значением true и сравниваете bool с этим свойством.Если ваш bool не отмечен (по умолчанию false), форма не будет проверена.

public bool isTrue
{ get { return true; } }

[Required]
[Display(Name = "I agree to the terms and conditions")]
[Compare("isTrue", ErrorMessage = "Please agree to Terms and Conditions")]
public bool iAgree { get; set; }
46 голосов
/ 19 января 2011

Вы можете создать свой собственный валидатор:

public class IsTrueAttribute : ValidationAttribute
{
    #region Overrides of ValidationAttribute

    /// <summary>
    /// Determines whether the specified value of the object is valid. 
    /// </summary>
    /// <returns>
    /// true if the specified value is valid; otherwise, false. 
    /// </returns>
    /// <param name="value">The value of the specified validation object on which the <see cref="T:System.ComponentModel.DataAnnotations.ValidationAttribute"/> is declared.
    ///                 </param>
    public override bool IsValid(object value)
    {
        if (value == null) return false;
        if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");

        return (bool) value;
    }

    #endregion
}
11 голосов
/ 03 октября 2017

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

В вашей ViewModel (для проверки на стороне сервера):

public bool IsTrue => true;

[Required]
[Display(Name = "I agree to the terms and conditions")]
[Compare(nameof(IsTrue), ErrorMessage = "Please agree to Terms and Conditions")]
public bool HasAcceptedTermsAndConditions { get; set; }

На вашей странице Razor (для проверки на стороне клиента):

<div class="form-group">
   @Html.CheckBoxFor(m => m.HasAcceptedTermsAndConditions)
   @Html.LabelFor(m => m.HasAcceptedTermsAndConditions)
   @Html.ValidationMessageFor(m => m.HasAcceptedTermsAndConditions)

   @Html.Hidden(nameof(Model.IsTrue), "true")
</div>
8 голосов
/ 27 мая 2016

Я просто хотел бы направить людей к следующей скрипте: https://dotnetfiddle.net/JbPh0X

Пользователь добавил [Range(typeof(bool), "true", "true", ErrorMessage = "You gotta tick the box!")] к своему логическому свойству, которое вызывает проверку на стороне сервера.

Для того, чтобычтобы также работала проверка на стороне клиента, они добавили следующий скрипт:

// extend jquery range validator to work for required checkboxes
var defaultRangeValidator = $.validator.methods.range;
$.validator.methods.range = function(value, element, param) {
    if(element.type === 'checkbox') {
        // if it's a checkbox return true if it is checked
        return element.checked;
    } else {
        // otherwise run the default validation function
        return defaultRangeValidator.call(this, value, element, param);
    }
}
6 голосов
/ 17 января 2014

Просто проверьте, равно ли его строковое представление True:

[RegularExpression("True")]
public bool TermsAndConditions { get; set; }
5 голосов
/ 10 октября 2011
Атрибут

[Required] означает, что требуется любое значение - может быть как true, так и false. Для этого вам придется использовать другую проверку.

5 голосов
/ 19 января 2011

Вы можете создать свой собственный атрибут или использовать атрибут CustomValidationAttribute .

. Таким образом вы будете использовать атрибут CustomValidationAttribute:

[CustomValidation(typeof(BoolValidation), "ValidateBool")]

, где BoolValidation определяется как:

public class BoolValidation
{
  public static ValidationResult ValidateBool(bool boolToBeTrue)
  {
    if (boolToBeTrue)
    {
      return ValidationResult.Success;
    }
    else
    {
      return new ValidationResult(
          "Bool must be true.");
    }
  }
2 голосов
/ 23 августа 2018

Для ASP.NET Core MVC - это проверка клиента и сервера на основе решения dazbradbury

public class EnforceTrueAttribute : ValidationAttribute, IClientModelValidator
{
    public override bool IsValid(object value)
    {
        if (value == null) return false;
        if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");
        return (bool)value;
    }

    public void AddValidation(ClientModelValidationContext context)
    {
        MergeAttribute(context.Attributes, "data-val", "true");
        var errorMessage = ErrorMessage ?? 
            $"The value for field {context.ModelMetadata.GetDisplayName()} must be true.";
        MergeAttribute(context.Attributes, "data-val-enforcetrue", errorMessage);
    }

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

А потом на клиенте:

$.validator.addMethod("enforcetrue", function (value, element, param) {
    return element.checked;
});

$.validator.unobtrusive.adapters.addBool("enforcetrue");

Тогда использование:

[EnforceTrue(ErrorMessage = "Please tick the checkbox")]
public bool IsAccepted { get; set; }
2 голосов
/ 17 февраля 2016

После сообщения ta.speot.is и комментария от Джерада Роуза:

Данный пост не будет работать на стороне клиента с ненавязчивой проверкойЭто должно работать в обоих лагерях (клиент и сервер):

[RegularExpression("(True|true)")]
public bool TermsAndConditions { get; set; }
...