私のモデルを以下に説明します。Application.References コレクションの最初の 2 つの項目については、参照フィールドのサブセットのみを要求したいと考えています。クライアント側とサーバー側の両方の検証でこれが発生することを望みます。以下に説明する作業方法がありますが、クライアント側はかなり面倒だと感じているので、これを処理するためのより良い方法があるのではないかと思います. サブセットを検証するために Application オブジェクトに他のいくつかのコレクションがあるため、可能であれば一般的になりたいと思います。
EFモデル
public class Application
{
//...EF framework code...
public EntityCollection<Reference> References
{
//get, set
}
}
public partial class Reference : EntityObject
{
public global::System.String FullName
{
//get, set
}
public global::System.String Relationship
{
//get, set
}
public global::System.String PhoneNumber
{
//get, set
}
public global::int? RelationshipLength //radio button
{
//get, set
}
public global::int? ReferenceType //radio button
{
//get, set
}
}
ReferenceMetaData.cs
[MetadataType(typeof(ReferenceMetadata))]
public partial class Reference
{
}
public class ReferenceMetadata
{
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("Full Name")]
public string FullName { get; set; }
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("Reference Type")]
public string ReferenceType { get; set; }
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("How long have you known this person?")]
public string RelationshipLength { get; set; }
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("Relationship")]
public string Relationship { get; set; }
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("Phone")]
public string Phone { get; set; }
//...more properites
}
私は現在、Pro ASP.NET MVC 2 Frameworkの Steven Sanderson の RuleException と RulesViolationExceptionExtensions を使用して、次のようにサーバー側の検証を手動で行っています。
public static class ApplicationBusinessLogic
{
public static void RunServerValidation(Application app)
{
var errors = new RulesException<Application>();
for (int i = 0; i < 3; i ++)
{
if (string.IsNullOrEmpty(app.References.ElementAt(i).FullName))
errors.ErrorFor(x => x.References.ElementAt(i).FullName, "The Full Name for a first and second reference are required.");
if (app.References.ElementAt(i).ReferenceType == null)
errors.ErrorFor(x => x.References.ElementAt(i).ReferenceType, "The Reference Type for a first and second reference are required.");
if (app.References.ElementAt(i).RelationshipLength == null)
errors.ErrorFor(x => x.References.ElementAt(i).RelationshipLength, "The Relationship Length for a first and second reference are required.");
if (string.IsNullOrEmpty(app.References.ElementAt(i).Relationship))
errors.ErrorFor(x => x.References.ElementAt(i).Relationship, "The Relationship for a first and second reference are required.");
if (string.IsNullOrEmpty(app.References.ElementAt(i).Phone))
errors.ErrorFor(x => x.References.ElementAt(i).Relationship, "The Phone Number for a first and second reference are required.");
}
if (errors.Errors.Any())
throw errors;
}
}
コントローラーから RunServerValidation メソッドを呼び出し、例外をキャッチして、ModelState にコピーするだけです。問題なく動作しますが、クライアント側でこれを処理する方法がわかりません。[必須] メタデータを使用した場合、コレクション内の 3 つのアイテムすべてにこれらのフィールドが必須になります。3分の2だけ欲しい。
私がクライアントの検証を接続した厄介な方法は、次のように入力をレンダリングしながら、ビューで data-val および data-val-required 属性を指定することです。
@for (int i = 0; i < 3; i++)
{
ViewData.TemplateInfo.HtmlFieldPrefix = "Application.References[" + i + "]";
<h3>Reference @i</h3>
@Html.ValidationMessageFor(model => model.Application.References.ElementAt(i).FullName)
<div class="editor-label">
@Html.LabelFor(model => model.Application.References.ElementAt(i).FullName)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.Application.References.ElementAt(i).FullName, new { maxlength = "100", data_val="true", data_val_required="The Full Name for a first and second reference are required." })
</div>
@* and so on for other properties... *@
}
動作しますが、これは理想的ではありません。汎用の ValidationAttribute を作成できるのではないかと考えましたが、それは複雑になると思います。Application.References メンバーについて考え[RequiredFieldsForFirstXCollectionItems(FirstXItems=2, Fields= new [] {"FullName", "ReferenceType" /* etc */})]
ていましたが、一般的な方法でそれを行う方法がわかりません。私はその考えで正しい軌道に乗っていますか?その後、クライアント側とサーバー側をそのように実装できますが、かなり複雑なコードになると思います。
2011 年 4 月 26 日更新:
入力タグに data-val および data-val-required html5 属性を配置するよりも、 $(document).ready 関数で jquery.Validation プラグインを使用してクライアント側の検証を追加する方がおそらく良いと思います。それから少なくとも、クライアントの検証のための集中的な場所があります。これが私がやったことです:
@*End of Razor View file*@
<script type="text/javascript>
function addValidationRules() {
//references
for (var i = 0; i < 2; i++) {
$("#Application_References_" + i + "__FullName").rules("add", {
required: true,
messages: {
required: "The Full Name for a first and second reference are required."
}
});
//etc. for other properties
}//end for-loop
}//end addValidationRules()
$(document).ready(function () {
addValidationRules();
//more js code...
});
</script>
もちろん、エラー メッセージにリソース ファイルを使用するようになると、javascript を .js ファイルに移動することにした場合、少し複雑になる可能性があります。関数をビューに保持すれば、必要に応じてリソース ファイルを読み取ることができるはずです。