問題
かみそりのビューによって出力された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)
};
これは、適切なクライアント側のプロパティを見つけるのに役立つはずです。次に、満たす必要のある他の条件を記述します。