質問
サーバー側のプロパティレベルの検証属性を作成しました。しかし、それを個々のフィールドに適用する代わりに、私はそれをリストに適用しました。これにより、モデル全体を検証できます。
ここで、MVC 3に組み込まれている目立たないクライアント側の検証を使用して、これを機能するように変換する方法を知る必要があります。
私の現在のコードは私の問題を説明するために以下にあります...
シナリオ
基本的なシナリオは、GroupNoフィールドでグループ化されたリストのすべての行のすべての数量値を合計する機能でした。いずれかのグループの合計が10を超える場合は、エラーが表示されます。
私は以前の投稿で、リストに対する検証属性を使用してこの作業をサーバー側にするための回答を親切に与えられました...
モデル:
public class ItemDetails
{
public int SerialNo { get; set; }
public string Description { get; set; }
public int GroupNo { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
}
public class MyViewModel
{
[EnsureMaxGroupItems(10, ErrorMessage = "You cannot have more than 10 items in each group")]
public IList<ItemDetails> Items { get; set; }
}
および検証属性自体:
[AttributeUsage(AttributeTargets.Property)]
public class EnsureMaxGroupItemsAttribute : ValidationAttribute
{
public int MaxItems { get; private set; }
public EnsureMaxGroupItemsAttribute(int maxItems)
{
MaxItems = maxItems;
}
public override bool IsValid(object value)
{
var items = value as IEnumerable<ItemDetails>;
if (items == null)
{
return true;
}
return items
.GroupBy(x => x.GroupNo)
.Select(g => g.Sum(x => x.Quantity))
.All(quantity => quantity <= MaxItems);
}
}
そして最後に、コントローラーのアクションはビューモデルで機能します。
public ActionResult ListItems()
{
var model = new MyViewModel
{
Items = ItemsRepository.GetItems()
};
return View(model);
}
[HttpPost]
public ActionResult ListItems(MyViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
...
}
次に、対応する強く型付けされたビュー:
@model MyViewModel
@Html.ValidationSummary()
@using (Html.BeginForm())
{
@Html.EditorFor(x => x.Items)
<button type="submit">Go go go</button>
}
~/Views/Shared/EditorTemplates/ItemDetails.cshtml
最後のビットは、Itemsコレクションの各要素に対して自動的にレンダリングされる対応するエディターテンプレートであるため、forループ( )を記述する必要はありません。
@model ItemDetails
@Html.HiddenFor(x => x.SerialNo)
@Html.LabelFor(x => x.Description)
@Html.HiddenFor(x => x.GroupNo)
@Html.LabelFor(x => x.Price)
@Html.TextBoxFor(x => x.Quantity)
クライアント側の控えめな検証は可能ですか?
目立たないMVC検証を使用してすべてを検証したいと思います。しかし、リスト全体に対してEnsureMaxGroupItemsAttribute属性を目立たないように検証する方法を理解できません。
IClientValidatableを次のように実装しました。
Public Function GetClientValidationRules(metadata As System.Web.Mvc.ModelMetadata, context As System.Web.Mvc.ControllerContext) As System.Collections.Generic.IEnumerable(Of System.Web.Mvc.ModelClientValidationRule) Implements System.Web.Mvc.IClientValidatable.GetClientValidationRules
Dim result = New List(Of ModelClientValidationRule)
Dim rule = New ModelClientValidationRule() With { _
.ErrorMessage = "You cannot have more than 10 items in each group", _
.ValidationType = "itemscheck"}
result.Add(rule)
Return result
End Function
注:VBとC#の組み合わせは、前の質問がC#で回答されたためです。プロジェクトはVBですが、C#での回答は問題ありません。
JSファイルにアダプターを作成しました。
jQuery.validator.unobtrusive.adapters.addBool("itemscheck");
... と ...
jQuery.validator.addMethod("itemscheck", function (value, element, params) {
// The check has been omitted for the sake of saving space.
// However this method never gets called
return false;
});
これを接続して目立たないように機能させる方法はありますか?