MVCモデルにはtrueが必要


85

データ注釈を介してブールプロパティをtrueに設定する必要がある方法はありますか?

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

これのユースケースは正確には何ですか?プロパティを読み取り専用にして、常にtrueを返すようにできませんか?
–JanThomä 2011

1
それはほとんど言うことです...ちょっとあなたが私が同意することをチェックするのを忘れた相棒...それはモデルを無効にするはずです。
Marty Trenouth 2011年

これはクライアント側で処理したいものだと思います。
PsychoCoder 2011年

15
@PsychoCoder:クライアント側だけでなく、両側で処理する必要があります。単純なデータ注釈を追加することで処理できるかどうかを調べていました。
Marty Trenouth 2011年

回答:


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
}

クライアント側の実装でこれを強化することを検討します-他の回答で参照されているリモート検証を使用するのではなく、ここに記載されている目立たないスペルト小麦を
SamStephens 2011年

これは私たちにとって良い(そしてテストされた)迅速な解決策です。@dazbradburyのソリューション(これも良いソリューション)では、クライアント側の検証なしで実行できます。これは、調査の過去のページの1つのチェックボックスでのみ必要になるためです。
セス

return (bool) value == true;これは冗長な比較です
T-moty 2017

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

最後に、ビューに次のスクリプトを追加して、クライアント側の検証を有効にします。

<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 2014年

2
クライアント側の検証を機能させることができず、何が間違っているのかわからないようです。javacsriptを正確にどこに置くべきですか?ヘッドタグで?コントローラーの隣?
vsdev 2014年

私は同意します、これが答えになるはずです
Simua 2014

1
カスタム検証属性の力を示す優れたソリューション!スクリプトをビューではなく、グローバルに参照されるjsファイルに入れて、再利用することをお勧めします。また、メッセージ文字列を追加できるすべての方法を処理するのが最適です。提供されていない場合はデフォルト、メッセージ文字列、またはリソースファイルから。
jeepwran 2014

1
素晴らしい解決策、投稿してくれてありがとう。クライアント側の検証を機能させることができない場合:検証するコントロールが読み込まれる前にjQuery検証を拡張する必要があるため、スクリプトをwindow.onload / $(documentではなく先頭に配置します。 ).ready()イベント。
2015

92

私はこれが古い投稿であることを知っていますが、これを行うための簡単なサーバー側の方法を共有したいと思いました。trueに設定されたパブリックプロパティを作成し、ブール値をそのプロパティと比較します。ブール値がチェックされていない場合(デフォルトでは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」プロパティを公開する必要がありました。
Tod Birdsall 2014年

MVC4には比較がありません
Michael Rudner Evanchik 2015年

スーパーソリューションの優れたソリューション
Sreerejith SS 2015

9
また、「isTrue」プロパティに非表示を追加すると、クライアント側の検証が行われます
billoreid 2016

2
この見栄えの良いソリューションを煩わしくすることは私にはうまくいきませんでした。Mvc5.2.3でテスト済み。
harvzor 2017

22

私はいくつかの解決策を試しましたが、クライアント側とサーバー側の両方の検証を取得するために完全に機能するものはありませんでした。それで、MVC5アプリケーションでそれを機能させるために何をしたか:

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
魅力的なソリューション!
トビアス

3
非表示フィールドの値(「true」)に注意してください!
トビアス

10

私は人々を次のフィドルに案内したいと思います: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 2014年

3
確認済み、これはサーバー側では機能しますが、クライアント側では機能しません
Matt Frear 2014年

サーバー側の検証では、ブール値を文字列と比較しようとすると、型の不一致の例外が発生する可能性があると思いました。
ローズ

RegularExpressionAttribute内部Convert.ToString的には、プロパティの値の文字列表現を取得するために使用します(これはとして配信されますobject)。
ta.speot.is 2014年

この答えは私からの@ fields-cage +1よりも簡単だと思います
Aaron Hudon 2015年

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

ta.speot.isによる投稿とJeradRoseからのコメントのフォローアップ:

指定された投稿は、目立たない検証ではクライアント側では機能しません。これは両方のキャンプ(クライアントとサーバー)で機能するはずです:

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

これが新しいバージョンの問題であるかどうかはわかりませんが、jquery.validate1.19.2およびjquery.validate.unobtrusive3.2.11では機能しません。問題はregex、jquery.validateがチェックされていないチェックボックスをオプションと見なすように見えることを除いて、正規表現を検証する前にチェックボックスがオプションであるかどうかを最初にチェックすることを目立たないように定義する方法にあるようです。tl; drチェックされたチェックボックスでのみ正規表現を実行します。regex validatorメソッドにシムを追加することも、カスタムバリデーターを作成することもできます。
xr280xr

3

.NET CoreMVC-データ注釈付きの必須チェックボックス

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 2011年

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

ここに画像の説明を入力してください

ここに画像の説明を入力してください


2

以下のために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; }

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ユーザーがチェックボックスをオンにしても?
ドロンツ

0

これを処理する最善の方法は、ボックスがtrueかどうかをコントローラーでチェックインすることです。そうでない場合は、モデルにエラーを追加して、ビューを再表示します。

前に述べたように、[必須]はすべて値があることを確認することであり、チェックしない場合でもfalseになります。


0

ここで絶対確実な検証をチェックしてください。Nugetからダウンロード/インストールできます。

これは、この種のことのための素晴らしい小さなライブラリです。


Ehhhh ...デフォルトの検証属性はかなりうまく機能します。
パンガンマ2018

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ツ2014

それはvalidation-に失敗した理由で、このリンクをチェックしてください作品itmeze.com/2010/12/06/...
dhandapaniハリクリシュナン

今日それは動作します。5、10年後も機能し続けると確信できますか?これらのQ&A DBは、将来のユーザー向けにも作成されています
Eliyahu 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.