私は自分自身にMVCを教えようとしています。現在抱えている実際の問題を反映するために、ダミープロジェクトをモックアップしました。
私のモデル:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcPersistPartialView.Models {
public class RemarkModels {
public static List<RemarkTemplateModel> GetTemplateAll() {
return new List<RemarkTemplateModel>() {RemarkTemplateModel.Create(1),
RemarkTemplateModel.Create(2),
RemarkTemplateModel.Create(3)};
}
}
public class RemarkModel {
public int ID { get; set; }
public string Content { get; set; }
public int TemplateID { get; set; }
public List<RemarkTemplateModel> Templates { get; set; }
public static RemarkModel Create() {
return new RemarkModel() {
Content = "This is a dummy remark, to learn MVC.",
TemplateID = 1,
Templates = RemarkModels.GetTemplateAll()
};
}
}
public class RemarkTemplateModel {
public int ID { get; set; }
public string Name { get; set; }
public List<RemarkTemplateFieldModel> Fields { get; set; }
public static RemarkTemplateModel Create(int id) {
return new RemarkTemplateModel() {
ID = id,
Name = id.ToString(),
Fields = new List<RemarkTemplateFieldModel>() {RemarkTemplateFieldModel.Create("Label A" + id.ToString(),
id.ToString() + "..."),
RemarkTemplateFieldModel.Create("Label B" + id.ToString(),
id.ToString() + "..."),
RemarkTemplateFieldModel.Create("Label C" + id.ToString(),
id.ToString() + "...")}
};
}
}
public class RemarkTemplateFieldModel {
public string Label { get; set; }
public string Content { get; set; }
public static RemarkTemplateFieldModel Create(string label, string content) {
return new RemarkTemplateFieldModel() { Label = label,
Content = content };
}
}
}
上記のモデルに表示されているのは RemarkModel で、「この人は満面の笑顔で問題を隠しています。気をつけてください!」のような人に保存できるコメントを表しています。また、調査などの特定の情報を入力するエンドユーザーの少し複雑な要望に対応する RemarkTemplateModel も表示されます。したがって、この「RemarkModel」はテンプレート「Testtemplate A」を持つことができます。テンプレートは、次のようなフィールド (RemarkTemplateFieldModel) で構成されます。「Testtemplate A」は、「フィールド 'A」、フィールド 'B'、およびフィールド 'C' のフィールドから構成されます (もちろん、一部の 'Testtemplate B' はフィールドから構成される場合があります)。 「D」、「E」、「F」、「G」)。これを明確にしたことを願っています。不明な点はお尋ねください。最後のモデルは RemarkModels (後ろの「s」) です。
私のコントローラー:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcPersistPartialView.Controllers {
public class HomeController : Controller {
public ActionResult Index() {
ViewBag.Message = "Welcome to ASP.NET MVC!";
Models.RemarkModel r = Models.RemarkModel.Create();
return View(r);
}
[HttpPost]
public ActionResult Index(Models.RemarkModel remark, Models.RemarkTemplateModel template, List<Models.RemarkTemplateFieldModel> fields) {
if (ModelState.IsValid) {
//Persist to database.
}
ViewBag.Message = "Welcome to ASP.NET MVC!";
Models.RemarkModel r = Models.RemarkModel.Create();
return View(r);
}
[AcceptVerbs("POST")]
public ActionResult TemplateChosen(string selectedTemplateID) {
Models.RemarkTemplateModel selectedTemp = (from temp in Models.RemarkModels.GetTemplateAll()
where temp.ID == Convert.ToInt32(selectedTemplateID)
select temp).FirstOrDefault();
return PartialView("RemarkTemplate", selectedTemp);
}
public ActionResult About() {
return View();
}
}
}
パラメーターなしの「Index」でわかるように、RemarkModel を作成し、それを厳密に型指定された View Index.cshtml に渡します。このビューは次のようになります。
@model MvcPersistPartialView.Models.RemarkModel
@using (Html.BeginForm()) {
<fieldset>
<div class="editor-label">
@Html.LabelFor(model => model.Content)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Content)
@Html.ValidationMessageFor(model => model.Content)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Templates)
</div>
<div class="editor-field">
@Html.DropDownListFor(
m => m.TemplateID,
new SelectList(Model.Templates, "ID", "Name"),
new {
id = "templateDdl",
data_url = Url.Action("TemplateChosen", "Home")
}
)
<input type="button" value="Change template" id="template-button" />
</div>
<div id="template">
@Html.Partial("RemarkTemplate", Model.Templates.First())
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
ここまでは順調ですね。以前、DropDownListFor について助けを求めるためにここに来ましたが、これは今では魅力的に機能します (コミュニティに感謝します)。質問の核心に迫っています。今までご辛抱いただきありがとうございました。部分ビュー 'RemarkTemplate' は次のようになります。
@model MvcPersistPartialView.Models.RemarkTemplateModel
<div class="display-field">
@Html.Encode(Model.ID)
</div>
<div class="display-field">
@* @Html.Encode(Model.Name)*@
@Html.EditorFor(m => m.Name)
</div>
@foreach (MvcPersistPartialView.Models.RemarkTemplateFieldModel field in Model.Fields) {
@* <div class="editor-label">
@Html.Encode(field.Label)
</div>
<div class="editor-field">
@Html.TextBox("Content", field.Content)
</div>*@
@Html.Partial("RemarkTemplateField", field)
}
2 番目の部分ビューに進みます。最初に、部分ビュー 'RemarkTemplateField' なしでこれを試し、POST アクション 'Index' に 2 つのパラメーター (コメント + テンプレート) のみを使用したためです。私の問題は、'template' パラメータの 'fields' プロパティが 'null' のままになっていることです。また、テンプレートの名前プロパティに「EditorFor」を使用するまで、テンプレートについて実際に何も投稿されていないことに気付きました。ただし、「remark」パラメーターには TemplateID プロパティに正しいテンプレート ID が含まれていたため、少なくともフィールドを取得できれば、テンプレートは問題ではないと考えました。そこで、2 番目の部分ビューを追加しました。
@model MvcPersistPartialView.Models.RemarkTemplateFieldModel
<div class="editor-label">
@Html.Encode(Model.Label)
</div>
<div class="editor-field">
@*@Html.TextBox("Content", Model.Content)*@
@Html.EditorFor(m => m.Content)
</div>
それは完全に表示されます。非常に素晴らしい。しかし、POSTback to the Index アクションは空の「テンプレート」を返し続け (実際の Web サイトではオプションではない EditorFor にしたため、テンプレートの「名前」が入力されています)、「フィールド」リストは空です。 . ご覧のとおり、Content の Textbox を EditorFor に再度変更しました。しかし、悲しいかな、魔法はありません。
私の質問は親愛なる専門家の皆さんです。このようなより複雑なモデルを MVC で適切にバインドするにはどうすればよいでしょうか? コントローラーのアクションのフィールドに入力されたコンテンツを取得するにはどうすればよいですか?最終的には、正しい入力テンプレートで発言をデータベースに永続化できますか? 私はあなたの助けにとても感謝しています. 説明したくない場合は、チュートリアルを教えてください。ちょっと手始めに。私は今、就業日のためにそれに取り組んできました...