MVC 모델에는 true가 필요합니다.


86

데이터 주석을 통해 부울 속성을 true로 설정하도록 요구하는 방법이 있습니까?

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

이것의 사용 사례는 정확히 무엇입니까? 속성을 읽기 전용으로두고 항상 true를 반환 할 수는 없습니까?
Jan Thomä 2011

1
말이 많이 돼요 ... 이봐 요, 당신은 동의 함을 확인하는 것을 잊었습니다. 모델을 무효화해야합니다.
Marty Trenouth

나는 이것이 당신이 클라이언트 측을 처리하고 싶은 것이라고 생각합니다.
PsychoCoder 2011 년

15
@PsychoCoder : 클라이언트 측뿐만 아니라 양쪽 모두에서 처리해야합니다. 간단한 데이터 주석을 추가하여 처리 할 수 ​​있는지 확인하려고했습니다.
Marty Trenouth

답변:


49

자신 만의 유효성 검사기를 만들 수 있습니다.

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
}

다른 답변에 언급 된 원격 유효성 검사를 사용하는 대신 여기에 설명 된 눈에 띄지 않는 철자를 사용하십시오 .jacopretorius.net / 2011 / 01 / client-side-validation-in-mvc-3 .html
SamStephens 2011

이것은 우리에게 좋은 (그리고 테스트 된) 빠른 솔루션입니다. @dazbradbury의 솔루션 (또한 좋은 솔루션)에서 클라이언트 측 검증 없이도 할 수 있습니다. 설문 조사의 지난 페이지에있는 하나의 확인란에만이 옵션이 필요하기 때문입니다.
Seth

return (bool) value == true;중복 비교입니다
T-moty

130

서버 측과 클라이언트 측 모두에 대한 유효성 검사기를 만들 것입니다. 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; }

마지막으로 View에 다음 스크립트를 추가하여 클라이언트 측 유효성 검사를 활성화합니다.

<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"
    };
}

3
감사합니다-잘 작동합니다! 재정의 FormatErrorMessage 메서드를 제거하면 더 잘 작동합니다. 리소스 파일의 오류 메시지 지역화가 작동합니다. 내 사용법 : [EnforceTrue (ErrorMessageResourceType = typeof (ValidationMessages), ErrorMessageResourceName = "TermsAndConditionsRequired")]
Matt Frear

2
클라이언트 측 유효성 검사가 작동하지 않고 내가 뭘 잘못하고 있는지 말할 수없는 것 같습니다. javacsript를 정확히 어디에 넣어야합니까? 헤드 태그에? 컨트롤러 옆에?
vsdev

나는이 대답해야한다, 동의
Simua

1
맞춤형 유효성 검사 속성의 힘을 보여주는 훌륭한 솔루션! 재사용을 위해 스크립트를 뷰가 아닌 전역 적으로 참조되는 js 파일에 넣는 것이 좋습니다. 또한 메시지 문자열을 추가 할 수있는 모든 방법을 처리하는 것이 가장 좋습니다. 제공되지 않은 경우 기본값, 메시지 문자열 또는 리소스 파일에서.
jeepwran 2014

1
훌륭한 솔루션입니다. 게시 해 주셔서 감사합니다. 클라이언트 측 유효성 검사가 작동하지 않는 사람들을 위해 : 유효성을 검사 할 컨트롤이로드되기 전에 jQuery 유효성 검사를 확장해야하므로 스크립트를 window.onload / $ (document)가 아닌 헤드에 넣으십시오. ) .ready () 이벤트.
Evert

93

나는 이것이 오래된 게시물이라는 것을 알고 있지만 이것을 수행하는 간단한 서버 측 방법을 공유하고 싶었습니다. 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 AgreeTerms { get; set; }

면도기 코드

@Html.CheckBoxFor(m => Model.AgreeTerms, new { id = "AgreeTerms", @checked = "checked" })
<label asp-for="AgreeTerms" class="control-label"></label>
<a target="_blank" href="/Terms">Read</a>
<br />
@Html.ValidationMessageFor(model => model.AgreeTerms, "", new { @class = "text-danger" })
@Html.HiddenFor(x => Model.isTrue)

12
단순함을 위해 +1. 참고 :이 작업을 수행하려면 'isTrue'속성을 공개해야했습니다.
토드 Birdsall 의장님

비교는 MVC4에서 나를 위해이 없다
마이클 루드 Evanchik

슈퍼 솔루션 훌륭한 솔루션
Sreerejith SS 2015-08-02

9
당신이 "isTrue"속성에 대한 숨겨진을 추가하는 경우, 당신은 클라이언트 측 유효성 검사 얻을
billoreid

2
이 멋진 솔루션은 나를 위해 작동하지 않았습니다. Mvc 5.2.3에서 테스트되었습니다.
harvzor

22

몇 가지 솔루션을 시도했지만 클라이언트 및 서버 측 유효성 검사를 모두 수행하는 데 완전히 효과가 없었습니다. 그래서 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>

1
매력적인 솔루션!
Tobias

3
숨겨진 필드의 값 ( "true")을 관리하십시오!
Tobias

10

사람들을 다음 Fiddle로 안내하고 싶습니다 : 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);
    }
}

9

문자열 표현이 다음과 같은지 확인하십시오 True.

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

@JeradRose 서버에서 잘 확인되었습니다. 클라이언트 측 유효성 검사를 언급하고 있습니까?
ta.speot.is

3
확정이 서버 측이 아닌 클라이언트 측 작동
매트 Frear

서버 측 유효성 검사에 bool을 문자열과 비교하려는 유형 불일치 예외가있을 수 있다고 생각했습니다.
Jerad Rose

RegularExpressionAttribute내부적으로 Convert.ToString속성 값의 문자열 표현을 가져 오는 데 사용 합니다 (으로 전달됨 object).
ta.speot.is

나는이 대답이 날의 필드 케이지 +1 @보다 간단 생각
아론 Hudon

5

고유 한 속성을 만들거나 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.");
    }
  }


3

들어 ASP.NET 코어 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; }

이 솔루션을 사용할 때 이것을 고려 하십시오 . "jquery $document.ready()/ $(function() { });" 외부에 자바 스크립트 코드를 넣으십시오 .
Igor

다음 required과 같이 HTML 입력 에 속성을 두지 않는 또 다른 팁 :<input asp-for="..." class="..." id="..." type="checkbox" required/>
Igor

3

ta.speot.is의 게시물과 Jerad Rose의 댓글에 대한 후속 조치 :

주어진 게시물은 눈에 띄지 않는 유효성 검사로 클라이언트 측에서 작동하지 않습니다. 이것은 두 캠프 (클라이언트 및 서버)에서 작동합니다.

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

이것이 최신 버전 문제인지 모르겠지만 jquery.validate 1.19.2 및 jquery.validate.unobtrusive 3.2.11에서는 작동하지 않습니다. 문제는 regexunobtrusive 메소드가 jquery.validate가 선택되지 않은 확인란을 선택 사항으로 간주한다는 점을 제외하고는 정규식을 확인하기 전에 확인란이 선택 사항인지 여부를 먼저 확인 하는 것 같습니다 . tl; dr 체크 박스에서만 정규식을 실행합니다. regex validator메서드 에 대한 shim을 추가 하거나 사용자 지정 유효성 검사기를 만들 수 있습니다.
xr280xr

3

.NET Core MVC-데이터 주석이있는 필수 확인란

public class MyModel
{
    [Display(Name = "Confirmation")]
    [Range(typeof(bool), "true", "true", ErrorMessage = "Please check the Confirmation checkbox.")]
    public bool IsConfirmed { get; set; }   
}

<div class="custom-control custom-checkbox col-10">
    <input type="checkbox" asp-for="IsConfirmed" class="custom-control-input" />
    <label class="custom-control-label" for="IsConfirmed">
        "By clicking 'submit', I confirm."
    </label>
    <span asp-validation-for="IsConfirmed" class="text-danger"></span>
</div>

<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>

<script type="text/javascript">
    $(document).ready(function () {
        // extend range validator method to treat checkboxes differently
        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);
            }
        }
    });
</script>


2

DataAnnotations를 통해 방법을 모르지만 이것은 컨트롤러에서 쉽게 수행됩니다.

public ActionResult Add(Domain.Something model)
{

    if (!model.MyCheckBox)
        ModelState.AddModelError("MyCheckBox", "You forgot to click accept");

    if (ModelState.IsValid) {
        //'# do your stuff
    }

}

유일한 다른 옵션은 서버 측에 대한 사용자 정의 유효성 검사기와 클라이언트 측에 대한 원격 유효성 검사기를 구축하는 것입니다 (원격 유효성 검사는 MVC3 +에서만 사용 가능).


이미 부울 플래그를 확인하는 방법이 이미 새로운 것 같습니다 .... 데이터 주석이 있는지 알고 싶었습니다.
Marty Trenouth

2

당신은이 있는가 의 Web.config에서 설정 적절한 항목을 ?

이로 인해 유효성 검사가 작동하지 않을 수 있습니다.

사용자 정의 유효성 검사 속성을 만들 수도 있습니다 ( [Required]존재 여부 만 신경 쓰고 값에 신경을 쓰므로).

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
sealed public class RequiredTrueAttribute : ValidationAttribute
{
    // Internal field to hold the mask value.
    readonly bool accepted;

    public bool Accepted
    {
        get { return accepted; }
    }

    public RequiredTrueAttribute(bool accepted)
    {
        this.accepted = accepted;
    }

    public override bool IsValid(object value)
    {
        bool isAccepted = (bool)value;
        return (isAccepted == true);
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(CultureInfo.CurrentCulture,
          ErrorMessageString, name, this.Accepted);
    }
}

그런 다음 사용법 :

[RequiredTrue(ErrorMessage="{0} requires acceptance to continue.")]
public bool Agreement {get; set;}

에서 여기 .


2

이것이 나를 위해 일한 것입니다. 다른 것은 없습니다. Mvc 5 :

모델

public string True
{
  get
  {
    return "true";
  }
}

[Required]
[Compare("True", ErrorMessage = "Please agree to the Acknowlegement")]
public bool Acknowlegement { get; set; }

전망

  @Html.HiddenFor(m => m.True)
  @Html.EditorFor(model => model.Acknowlegement, new { htmlAttributes = Model.Attributes })
  @Html.ValidationMessageFor(model => model.Acknowlegement, "", new { @class = "text-danger" })

여기에 이미지 설명 입력

여기에 이미지 설명 입력


1

나는 fields.cage의 대답을 사용하려고 시도했지만 그것은 나를 위해 잘 작동하지 않았지만 더 단순한 일이 있었고 정확히 왜인지 모르겠습니다 (다른 Razor 버전, 아마도?).하지만 내가해야 할 일은 이것뿐이었습니다.

[Required]
[Range(typeof(bool), "true", "true", ErrorMessage = "Agreement required.")]
[Display(Name = "By clicking here, I agree that my firstborn child will etc etc...")]
public bool Agreement1Checked { get; set; }

그리고 .cshtml 파일에서 :

@Html.CheckBoxFor(m => m.Agreement1Checked)
@Html.LabelFor(m => m.Agreement1Checked)
@Html.ValidationMessageFor(m => m.Agreement1Checked)

이것은 나를 위해 클라이언트 측에서 작동하지 않습니다. 어떤 이유로 jquery.validate 규칙 메서드에 전달 된 매개 변수는 [NaN, NaN]이 있어야 할 곳에[true, true]
xr280xr

@ xr280xr 사용자가 체크 박스를 체크해도?
Dronz

0

이 문제를 처리하는 가장 좋은 방법은 상자가 참인지 컨트롤러를 확인하고 그렇지 않으면 모델에 오류를 추가하고 뷰를 다시 표시하는 것입니다.

앞서 언급했듯이 [필수]는 값이 있는지 확인하고 체크하지 않은 경우에도 여전히 거짓이됩니다.



0
/// <summary> 
///  Summary : -CheckBox for or input type check required validation is not working the root cause and solution as follows
///
///  Problem :
///  The key to this problem lies in interpretation of jQuery validation 'required' rule. I digged a little and find a specific code inside a jquery.validate.unobtrusive.js file:
///  adapters.add("required", function (options) {
///  if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
///    setValidationValues(options, "required", true);
///    }
///   });
///   
///  Fix: (Jquery script fix at page level added in to check box required area)
///  jQuery.validator.unobtrusive.adapters.add("brequired", function (options) {
///   if (options.element.tagName.toUpperCase() == "INPUT" && options.element.type.toUpperCase() == "CHECKBOX") {
///              options.rules["required"] = true;
///   if (options.message) {
///                   options.messages["required"] = options.message;
///                       }
///  Fix : (C# Code for MVC validation)
///  You can see it inherits from common RequiredAttribute. Moreover it implements IClientValidateable. This is to make assure that rule will be propagated to client side (jQuery validation) as well.
///  
///  Annotation example :
///   [BooleanRequired]
///   public bool iAgree { get; set' }
/// </summary>


public class BooleanRequired : RequiredAttribute, IClientValidatable
{

    public BooleanRequired()
    {
    }

    public override bool IsValid(object value)
    {
        return value != null && (bool)value == true;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        return new ModelClientValidationRule[] { new ModelClientValidationRule() { ValidationType = "brequired", ErrorMessage = this.ErrorMessage } };
    }
}

이 링크가 질문에 답할 수 있지만 여기에 답변의 필수 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 무효화 될 수 있습니다.
Ravi Dhoriya ツ

그것은 검증 -에 실패하는 이유는 이유가이 링크를 확인 작동 itmeze.com/2010/12/06/...을
dhandapani 하리 크리슈 난을

오늘은 작동합니다. 5 년, 10 년 후에도 계속 작동 할 것이라고 확신 할 수 있습니까? 이 Q & A DB도 미래의 사용자를 위해 만든
Eliyahu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.