2015-04-05 37 views
2

我使用模型優先方法創建了帶有實體框架的數據庫。除其他外,我有一個ContentEntry類型和Tag類型。每個ContentEntry可以有多個Tag s,並且每個Tag可以被多個ContentEntry使用。應該是這樣的,沒有標籤在數據庫中存在的兩倍,因爲這是在N:M關係: Image of the realtion between Tag and ContentEntryMVC - 將所有ListBox項目傳遞迴控制器

現在,我嘗試創建一個控制器/視圖中創建一個新的ContentEntryTag秒。我不知道如何創建一個列表框,它將全部他的物品返回給控制器。 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"); 
    } 

BlogEntryContentEntry一個衍生物,並ContentEntry.TagsICollection<Tag>

有沒有人有一個想法如何解決這個任務?

編輯: 這裏是我的GET-方法CreateBlogEntry:

public ActionResult CreateBlogEntry() 
{ 
    //ViewBag.Tags = db.TagSet; 
    return View(new BlogEntry() 
    { 
     Published = DateTime.Now, 
    }); 
} 
+0

你能爲'CreateBlogEntry'發佈'GET'方法嗎? – 2015-04-05 23:45:46

+0

@Alundrathedreamwalker我添加了GET方法,我的問題 – Koopakiller 2015-04-06 00:05:56

+0

一種方法來解決這個問題是創建一個視圖模型,將有所有你從 – 2015-04-06 00:29:52

回答

3

默認的模型綁定將選定的值從多選到集合綁定。

即使你從服務器,將工作負載值視圖更改爲

@Html.ListBox("SelectedTags" 
, new MultiSelectList(Model.Tags,"Name","Name") 
, new { id = "lbTags" }) 

這樣。請注意,我沒有使用ListBoxFor,因爲我想設置集合的名稱。即進入CreateBlogEntry方法

BlogEntry車型將擁有像下面

public IEnumerable<string> SelectedTags{ get; set; } 

然後您可以利用這個​​財產,並創建一個進入你的數據庫的新模式的屬性。

如果您不想要這種行爲,您將不得不重寫默認的模型聯編程序的行爲。你可以找到關於綁定器的所有信息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; 
    } 
} 

您可以連接了這個粘合劑在全球性的。asax像如下:

public class MvcApplication : System.Web.HttpApplication 
{ 
    protected void Application_Start() 
    { 
     ModelBinders.Binders.DefaultBinder = new FancyBinder(); 
    } 
} 

我希望這是足夠清楚。如果您有任何問題,請告訴我。

+0

這是在德國很晚,所以我會在幾個小時內測試你的自定義模型粘結劑解決方案 但你的第一個想法幾乎完美 - 謝謝你 – Koopakiller 2015-04-06 02:33:15

+0

@Koopakiller歡迎你..很高興它幫助:) – Yogiraj 2015-04-06 02:40:35

+0

我testet你的FancyBinder呢,它的工作也很好。但我認爲創建第二個模型更容易。 – Koopakiller 2015-04-06 14:30:17