ASP.NET MVC 3复杂模型绑定问题

时间:2013-03-08 08:53:25

标签: c# asp.net-mvc asp.net-mvc-3

我正在尝试自学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'由字段组成:'Field'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)
} 

我们将进入第二部分视图。因为首先我在没有部分视图'RemarkTemplateField'的情况下尝试了此操作,并且在POST操作'索引'中只有2个参数(注释+模板)。我的问题是'template'参数的'fields'属性仍为'null'。我还注意到关于模板的所有内容都没有发布,直到我使用'EditorFor'作为模板的name属性。 然而,'remark'参数在其TemplateID属性中包含正确的模板ID,所以我想如果我至少可以得到字段,模板无关紧要。这就是我添加第二部分视图的时候:

@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>

它显示完美。非常好。但是回归到索引操作会一直返回一个空的“模板”(因为我把它变成了编辑器,而不是真实网站上的选项,所以填充了模板的“名称”)并且“字段”列表为空。如您所见,我再次将内容上的文本框更改为EditorFor。但是,唉,没有魔力。

所以我的问题是我的亲爱的专家,如何在MVC中正确绑定这样一个更复杂的模型?如何在控制器的操作中获取字段的填写内容,以便最终可以将带有正确填写模板的注释持久保存到数据库中?我非常感谢你的帮助。如果你不想拼出来,请指教我,这可以帮助我。请给我一些先发制人。我现在一直在工作日......

1 个答案:

答案 0 :(得分:0)

我认为你要找的是收藏品的绑定。这可能有所帮助:http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx