我使用模型第一种方法创建了一个包含Entity Framework的数据库。除此之外,我有ContentEntry
类型和Tag
类型。每个ContentEntry
可以包含多个Tag
,每个Tag
可以由多个ContentEntry
使用。它应该是这样的,在db中没有标记存在两次,因为这是n:m关系:
现在,我尝试创建一个控制器/视图,以创建一个带有ContentEntry
的新Tag
。我不知道如何创建一个ListBox,将所有他的项目返回给控制器。 JavaScript(使用jQuery)对我来说没问题:
<span class="label">Tags</span>
@Html.ListBoxFor(model => model.Tags,
new MultiSelectList(Model.Tags),
new { id = "lbTags" })
<input type="text" id="tbTag" />
<input type="button" value="add" onclick="addTag();" />
<input type="button" value="delete" onclick="delTags();" />
<script>
function addTag() {
$('#lbTags').append($('<option>',
{ value: $("#tbTag").val(), text: $("#tbTag").val() }));
}
function delTags() {
$("#lbTags option:selected").remove();
}
</script>
@Html.ValidationMessageFor(model => model.Tags, "", new { @class = "input-error" })
但我的Tags
集合始终为空:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateBlogEntry
([Bind(Include = "Id,Published,Title,AccountId,HtmlContent,Tags")]BlogEntry blogEntry)
{
//blogEntry.Tags is always empty
if (ModelState.IsValid
{
db.ContentEntrySet.Add(blogEntry);
db.SaveChanges();
return RedirectToAction("Index");
}
BlogEntry
是ContentEntry
的推导,ContentEntry.Tags
是ICollection<Tag>
。
有谁知道如何解决这个问题?
修改: 这是我对CreateBlogEntry的GET方法:
public ActionResult CreateBlogEntry()
{
//ViewBag.Tags = db.TagSet;
return View(new BlogEntry()
{
Published = DateTime.Now,
});
}
答案 0 :(得分:3)
默认模型绑定器会将多选中的选定值绑定到集合。
将您的观点更改为
@Html.ListBox("SelectedTags"
, new MultiSelectList(Model.Tags,"Name","Name")
, new { id = "lbTags" })
这种方式即使您从服务器加载值也可以。请注意,我没有使用ListBoxFor
,因为我想设置集合的名称。
进入BlogEntry
方法的CreateBlogEntry
模型将具有如下所示的属性
public IEnumerable<string> SelectedTags{ get; set; }
然后,您可以使用此SelectedTags
属性并创建一个进入数据库的新模型。
如果您不想要此行为,则必须覆盖默认模型活页夹的行为。您可以找到关于绑定器in this MSDN post的所有信息。我将尝试使用模型绑定器更新答案,但这足以在同一时间解锁您。
另外请注意,您使用的所有属性BlogEntry
都不需要绑定。你可以删除它。
更新 - 自定义模型绑定器版本
您可以创建自己的活页夹,如下所示:
public class FancyBinder:DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext
,ModelBindingContext bindingContext
,Type modelType)
{
if (modelType.Name == "BlogEntry")
{
return BindBlogEntry(controllerContext, bindingContext, modelType);
}
return base.CreateModel(controllerContext, bindingContext, modelType);
}
private static object BindBlogEntry(ControllerContext controllerContext
,ModelBindingContext bindingContext
,Type modelType)
{
var tagsOnForm = controllerContext.HttpContext.Request.Form["Tags"];
return new BlogEntry
{
Content = controllerContext.HttpContext.Request.Form["Content"],
Tags = GetTags(tagsOnForm)
};
}
private static List<Tag> GetTags(string tagsOnForm)
{
var tags = new List<Tag>();
if (tagsOnForm == null)
return tags;
tagsOnForm.Split(',').ForEach(t=>tags.Add(new Tag {Name = t}));
return tags;
}
}
您可以在global.asax中连接此绑定器,如下所示:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
ModelBinders.Binders.DefaultBinder = new FancyBinder();
}
}
我希望这很清楚。如果您有疑问,请告诉我。