2016-04-22 30 views
0

我是C#的初學者,希望得到一些幫助。我正在使用ASP.NET MVC和Entity Framework 6開發一個網站項目。到目前爲止,我從不需要尋求幫助,但是我陷入了僵局。如何使用dropdrownlist(ASP.NET MVC)更新實體

我的項目的目的是列出存儲在文件夾中的文檔,將它們註冊到數據庫中,並使用可排序的表格在網頁上顯示每個文檔。每個文檔都有一個「Referentiel」(如果您願意,可以是一個部門或一個分類),並且應該是可編輯的。這是我卡住的地方。我做了一個視圖,其中包含一個表單來編輯文檔的每個字段。但是,我的模型有一個虛擬屬性「Referentiel」,它不能像字符串屬性那樣容易更新(模型適合具有這些屬性的數據庫)。

這裏是我的模型,我得到的文件擁有一個包含許多文檔的Referentiel和Referentiels:一對多關係。我使用Referentiel類中的文檔列表和Document中的Referent屬性來實現它。

public class Document 
{ 
    public int Id { get; set; } // unique identifier 
    public string Code { get; set; } // identifier of a document inside the company 
    public string Titre { get; set; } // name of the saved file (pdf, word...) 
    public string Type { get; set; } // specify the nature of the document 
    public int Ref_Id {get; set;} // foreign identifier with the linked entity in a one-to-many relation. 
    [ForeignKey("Id_Ref")] 
    public virtual Referentiel Referentiel { get; set; } // company's department where the document belongs to. 
} 

public class Referentiel 
{ 
    public int Id { get; set; } // unique identifier 
    public string Nom { get; set; } // name of a company's department 
    public virtual List<Document> Documents { get; set; } // collection of object Document (N.B. : doesn't appear in the database) 
} 

我不得不使用視圖模型在我看來訪問這兩種模式,所以我做了DocFormViewModel:

public class DocFormViewModel 
{ 
    public List<Models.Referentiel> Referentiels { get; set; } 
    public Models.Document Doc { get; set; } 

    [Display(Name = "Référentiel")] 
    public int SelectedReferentielId { get; set; } 
} 

我的控制器有兩個方法,一個GET請求和一個POST請求。

// GET: Documents/Modifier/5 
    [HttpGet] 
    public ActionResult Modifier(int? id) 
    { 
     if (id == null) 
     { 
      return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
     } 

     vm.Doc = db.Documents.Find(id); 

     if (vm.Doc == null) 
     { 
      return HttpNotFound(); 
     } 
     return View(vm); 
    } 

    // POST: Documents/Modifier/5 
    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Modifier([Bind(Include = "Id,Code,Titre,Type,Referentiel")] Document doc) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Entry(doc).State = EntityState.Modified; 
      db.SaveChanges(); 
      return RedirectToAction("Index", "Accueil"); 
     } 

     DocFormViewModel documentReferentielViewModel = new DocFormViewModel 
     { 
      Doc = db.Documents.Find(doc.Id), 
      Referentiels = db.Referentiels.ToList(), 
      SelectedReferentielId = doc.Referentiel.Id, 

     }; 
     ViewBag.referentiel_Id = new SelectList(db.Referentiels.ToList(), "Id", "Referentiels", doc.Referentiel.Id); 

     return View(documentReferentielViewModel); 
    } 

最後,我使用dropdownList來收集現有的Referentiel。所選的參考文獻將被選擇用於更新所編輯的文檔。但是,當我提出我的文檔保留其默認Referentiel形式(在數據庫和視圖)

@model BaseDoc_OI_GRC.ViewModels.DocFormViewModel 

<!--Some html--> 
@using (Html.BeginForm()) 
{ 
    <div class="form-group"> 
     @Html.LabelFor(model => model.SelectedReferentielId, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10">   
      @Html.DropDownListFor(m => m.Doc.Referentiel.Id, Model.ReferentielItems) 
       @Html.ValidationMessageFor(m => m.Doc.Referentiel, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

<div class="form-group"> 
    <div class="col-md-offset-2 col-md-10"> 
     <input type="submit" value="Enregistrer" class="btn btn-default" /> 
    </div> 
</div> 
} 

我希望你明白我的意思,我不是母語的人,但我盡力保持清晰。 (一些變量名稱是法文的,它不應該成爲一個問題,但問問我是否想要更好的翻譯)。

感謝您的閱讀,我會非常感謝任何解決方案。 ;)

+0

嘗試添加'db.Entry(doc.Referentiel).STATE = EntityState.Modified;''之前db.SaveChanges();'您可能還需要將該子實體標記爲已修改。 – Eric

+0

@Eric我也想過,但沒有嘗試。所以,我改變了我的代碼,但它引發了一個異常:「附加一個'BaseDoc.Models.Referentiel'類型的實體失敗,因爲另一個實體具有相同的主鍵值。'如果我忽略了模型的驗證,那麼只需將另一個模型Referent插入數據庫而不是更新涉及的每個模型。 –

+0

您的代碼有多個問題。首先你的'Document'甚至不具有定義關係的屬性(例如'int ReferentItyI')。接下來你有一個包含數據模型的視圖模型(永遠不要這樣做,並建議你閱讀[什麼是MVC中的ViewModel?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) )。接下來你的'Modifier()'GET方法將'Document'的一個實例返回給視圖,但是你顯示的視圖有'@model DocFormViewModel',這樣就會拋出異常。 –

回答

0

我昨天解決了我的問題。感謝您的回答。我剛剛在我的Dal類(數據訪問層)中使用了一種方法將實體Document鏈接到實體Referentiel。這種方法更容易,沒有什麼會拋出異常(即使它之前沒有拋出任何東西)。

要總結一下我的新Modifier或「編輯」的方法在DocumentsController

[HttpPost] 
public ActionResult Modifier(DocFormViewModel viewModel){ 
    dal.ModifierType(viewModel.Doc.Id, viewModel.SelectedTypeString); 
    dal.AjouterDocumentAReferentiel(viewModel.Doc.Id, viewModel.SelectedReferentielId); // English : AddDocumentToReferentiel(id_Document, id_Referentiel) 
    return RedirectToAction("Index", "Accueil"); 
} 

下面是修改後的參數視圖的一個樣本:

<!--some-html--> 
@using(Html.BeginForm()) 
{ 
    <!--some-html--> 
    <div class="form-group"> 
     @Html.LabelFor(model => model.SelectedReferentielId, htmlAttributes: new {@class = "control-label col-md-2" }) 
     @Html.DropDownListFor(model => model.SelectedReferentielId, Model.ReferentielItems) 
     @Html.ValidationMessageFor(model => model.SelectedReferentielId, "", new { @class = "text-danger" }) 
    </div> 
} 

我德爾類有方法來選擇並更新實體,如:

// Dal implements an interface IDal which extends IDisposable 
public class Dal : Idal 
{ 
    private BddContext bdd; // BddContext extends DbContext with DbSet<Document> Documents and DbSet<Referentiel> Referentiels attributes 

    // there are some attributes to fetch files from a folder but there're irrelevant to this issue so I skip them and their methods. 
    // Obviously there are a lot more of method to edit, create, remove, 
    // fetch or test existence in database/folder 

    /** 
    * This is the method I used in DocumentController instead of 
    * a direct access to the database with BddContext, now Dal does it instead 
    */ 
    public void AjouterDocumentAReferentiel(int idDoc, int idRef) 
    { 
     Document document = bdd.Documents.FirstOrDefault(doc => doc.Id == idDoc); 
     Referentiel referential = bdd.Referentiels.FirstOrDefault(r => r.Id == idRef) 
     referential.Documents.Add(document); 
     bdd.SaveChanges(); 
    } 
} 

最後,這是最終的結果是:(初級頁面的屏幕截圖)

Homepage where every documents in a folder are registered in the database Edit page for document with id = 1

相關問題