MVC検証の基礎(エンティティフレームワークを使用)
シナリオ:
私は以下のようなモデルクラスを持っています(Entity Framework EF.x DbContext Generatorを介して自動生成されます)。
(現在、ビューモデルはありません)。
public partial class Activity
{
public int Id { get; set; }
public byte Progress { get; set; }
public decimal ValueInContractCurrency { get; set; }
public System.DateTime ForecastStart { get; set; }
public System.DateTime ForecastEnd { get; set; }
public int DepartmentId { get; set; }
public int OwnerId { get; set; }
public int StageId { get; set; }
public int StatusId { get; set; }
public virtual Department Department { get; set; }
public virtual Owner Owner { get; set; }
public virtual Stage Stage { get; set; }
public virtual Status Status { get; set; }
}
強く型付けされたビューで空白のフォームを送信すると、次の検証メッセージが表示されます。
Progressフィールドは必須です。
ValueInContractCurrencyフィールドは必須です。
ForecastStartフィールドは必須です。
ForecastEndフィールドは必須です。
つまり、dbテーブルのすべてのフィールド。
これらを入力して再度送信すると、コントローラーが呼び出されます。その後、IsValidがfalseであるため、コントローラーはビューページに戻ります。
次に、画面が次の検証メッセージとともに再表示されます。
StageIdフィールドは必須です。
DepartmentIdフィールドは必須です。
StatusIdフィールドは必須です。
OwnerIdフィールドは必須です。
つまり、dbテーブルのすべての外部キーフィールド(これらもすべて選択ボックスです)。
これらを入力すると、フォームは正常に送信され、データベースに保存されます。
質問:
[必須]属性を使用していない場合、検証はどこから行われますか?これはエンティティフレームワークと関係がありますか?
フォームがクライアント側ですべてをすぐに検証しないのはなぜですか。外部キー(または選択ボックス)は、空であるため明らかに無効であるにもかかわらず、IsValid()によってのみチェックされるという違いは何ですか?
ユーザーがフォームを2回送信する必要がなく、すべての検証メッセージが一度に表示されるように、すべてを1つのステップ(空のフィールドの場合)で検証するにはどうすればよいですか?クライアント側の検証をオフにする必要がありますか?
([Required]属性を外部キーフィールドに追加しようとしましたが、違いは見られませんでした(おそらく、IsValidにのみ影響します)。Html.EnableClientValidation()も呼び出してみましたが、違いはありませんでした。 )。
4 ..最後に、検証に[MetadataType [MetadataType(typeof(...)]]を使用している人を見てきましたが、ビューモデルがある場合はなぜそうするのですか、そうでない場合のみですか?
明らかに私はここでいくつかの基本を見逃しているので、さらに、属性に関する別のエッセイではなく、MVC検証プロセスがJavaScript /コントローラー呼び出しを含むステップバイステップでどのように正確に機能するかについての詳細なチュートリアルを知っている人がいれば、私は行うことができますそれへのリンクもあります:c)
ミステリーマンの詳細:
次のようなソリューションのセットアップ:
.NET4
MVC3
EF5
EF5.xDbコンテキストジェネレーター
EF.x Dbコンテキストジェネレータファイル(.ttファイル)を関連付けるためにedmxデザインサーフェスで使用される「コード生成アイテムの追加」
コントローラは次のようになります。
// GET: /Activities/Create
public ActionResult Create()
{
ViewBag.DepartmentId = new SelectList(db.Departments, "Id", "Name");
ViewBag.OwnerId = new SelectList(db.Owners, "Id", "ShortName");
ViewBag.ContractId = new SelectList(db.Contracts, "Id", "Number");
ViewBag.StageId = new SelectList(new List<string>());
ViewBag.StatusId = new SelectList(db.Status.Where(s => s.IsDefaultForNewActivity == true), "Id", "Name");
return View();
}
// POST: /Activities/Create
[HttpPost]
public ActionResult Create(Activity activity)
{
if (ModelState.IsValid)
{
db.Activities.Add(activity);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.DepartmentId = new SelectList(db.Departments, "Id", "Name");
ViewBag.OwnerId = new SelectList(db.Owners, "Id", "ShortName");
ViewBag.ContractId = new SelectList(db.Contracts, "Id", "Number");
ViewBag.StageId = new SelectList(db.Stages, "Id", "Number");
ViewBag.StatusId = new SelectList(db.Status, "Id", "Name");
return View(activity);
}
ビューは次のようになります。
<!-- this refers to the EF.x DB Context class shown at the top of this post -->
@model RDMS.Activity
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Activity</legend>
<div class="editor-label">
@Html.LabelFor(model => model.StageId, "Stage")
</div>
<div class="editor-field">
@Html.DropDownList("StageId", String.Empty)
@Html.ValidationMessageFor(model => model.StageId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Progress)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Progress)
@Html.ValidationMessageFor(model => model.Progress)
</div>
<!-- ETC...-->
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}