2

私はMVCアプリで SimonInceによって作成されたカスタムRequiredIf属性を使用しています。

次のようなビューに渡されるビューモデルがあります。

public class HistoryViewModel
{
    public Contact ContactModel { get; set; }
    public Account AccountModel { get; set; }
    public Person PersonModel { get; set; }
 }

すべての小道具が含まれているモデルがたくさんあります(つまり、contact.cs、account.cs、person.cs)

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsAdult { get; set; }        
    [RequiredIf("IsAdult", "Yes", Errormessage="Please leave a comment")]
    public string Comments { get; set; }
 }

RequiredIfビューモデルを通過したときに検証が機能していないようです。プロパティをビューモデルに直接移動すると、正常に機能します. All other[必須] `属性は、モデルからビューモデルを介して機能します。

では、すべてのプロパティをビューモデルに移動する必要がありますか?それらにRequiredIfが必要ですか?または、これを回避する別の方法はありますか?

4

2 に答える 2

6

MVC FoolProof検証を試しましたか?クライアントサイドをサポートするRequiredIf(およびその他のかなりの数)をサポートしています。少しバグがある場合もありますが、最新バージョンは悪くありません。

上記と同じように機能します(FoolProofに切り替える前に試しました)

   public bool Married { get; set; }

    [RequiredIfTrue("Married")]
    public string MaidenName { get; set; }
于 2012-09-27T23:54:16.197 に答える
2

問題

かみそりのビューによって出力されたhtmlを見ると、ここで問題になっていることがわかります。

ビューモデルがない場合は、次のコードを生成する必要があります(少しクリーンアップ)。

<input type="checkbox" name="IsAdult" id="IsAdult" />
<input type="text" name="Comments" id="Comments"
       data-val-requiredif-dependprop="IsAdult" 
       data-val-requiredif-value="Yes"
       data-val-requiredif="Please leave a comment" />

ビューモデルを使用すると、次のようになります。

<input type="checkbox" name="PersonModel.IsAdult" id="PersonModel_IsAdult" />
<input type="text" name="PersonModel.Comments" id="PersonModel_Comments"
       data-val-requiredif-dependprop="IsAdult" 
       data-val-requiredif-value="Yes"
       data-val-requiredif="Please leave a comment" />

プロパティが別のプロパティ内にネストされている場合は常に、MVCはプレフィックスのスタックを構築して一意のIDと名前を生成します。最初のケースでわかるようにIsAdult、フィールドを識別するには十分ですが、ネストされると、IDが変更されます。data-attributes目立たない検証(属性に格納されたルール)では、他のプロパティを見つける方法を含め、要素を検証する方法について知る必要があるすべてのものをに送信する必要があります。

ソリューション

クラスのデータ属性は、呼び出されているコンテキストを認識したり気にしたりしてはならないため、クラスが依存している相対属性を盲目的に指摘し続けます。

public bool IsAdult { get; set; }
[RequiredIf("IsAdult", "Yes", Errormessage="Please leave a comment")]
public string Comments { get; set; }

したがって、サーバーまたはクライアントのいずれかでコンテキストを確立する必要があります。

サーバー上-いいえ!

の一部としてpublic class RequiredIfAttribute : ValidationAttribute, IClientValidatable、次のようなクライアント側の検証ルールを発行するメソッドがあります。

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
    ModelClientValidationRule requiredIfRule = new ModelClientValidationRule();
    requiredIfRule.ErrorMessage = ErrorMessageString;
    requiredIfRule.ValidationType = "requiredif";
    requiredIfRule.ValidationParameters.Add("dependprop", this._propertyName);
    requiredIfRule.ValidationParameters.Add("value", Json.Encode(this._value));     

    yield return requiredIfRule;
}

ここでの誘惑は、viewContext.ViewData.TemplateInfoを返すためにナビゲートするGetFullHtmlFieldIdことですが、私が知る限り、この情報はまだ利用できません

クライアント-不安定ですが機能しています:

クライアントでは、次のような方法でアダプターを接続します。

$.validator.unobtrusive.adapters.add('requiredif', ['dependprop', 'value'], function (options) {
    options.rules["requiredif"] = { 
        id: '#' + options.params['dependprop'],
        value: JSON.parse(options.params.value) 
    };
    options.messages['requiredif'] = options.message;
});

これはまだ単純な古いプロパティ名を取り、オブジェクトを見つけるためのIDとして使用できると想定していることに注意してください。

いくつかの合理的な仮定を行うことにより、完全な依存関係プロパティIDを構築できます。requiredif呼び出し要素が、識別したプロパティと同じスコープ内にあることが常に当てはまるはずです(これにより、リフレクションを介してサーバー上で要素を見つけることができました)。

したがって、送信者からそのコンテキストを取得し、そのプロパティの名前を削除して、次のように独自のコンテキストを次のように追加します$.validator.unobtrusive.adapters.add

var curId = options.element.id;               // get full id      i.e. ViewModel_Comments
var context = curId.replace(/[^_]+$/, "");    // remove last prop i.e. ViewModel_
var targetProp = options.params['dependprop'] // target name      i.e. IsAdult
var targetId = '#' + context + targetProp;    // build target ID  i.e. #ViewModel_IsAdult

options.rules["requiredif"] = {
    id: targetId,
    value: JSON.parse(options.params.value)
};

これは、適切なクライアント側のプロパティを見つけるのに役立つはずです。次に、満たす必要のある他の条件を記述します。

于 2016-09-27T13:09:00.840 に答える