如何使用dropdrownlist更新实体(ASP.NET MVC)

时间:2016-04-22 13:55:30

标签: c# asp.net asp.net-mvc entity-framework asp.net-mvc-4

我是C#的初学者,我想要一些帮助。我正在使用ASP.NET MVC和Entity Framework 6开展一个网站项目。到目前为止,我从来没有寻求过帮助,但我遇到了僵局。

我的项目的目的是列出存储在文件夹中的文档,将它们注册到数据库中,并使用可排序的表格显示网页上的每个文档。每个文档都有一个' Referentiel' (如果您愿意,可以是部门或类别)并且应该是可编辑的。这就是我被困的地方。我创建了一个视图,其中包含一个用于编辑文档每个字段的表单。但是,我的模型有一个虚拟属性" Referentiel"它不像字符串属性那样容易更新(模型使数据库符合这些属性)。

这是我的模特,我拥有拥有Referentiel和Referentiels的文件,这些文件拥有许多文件:一对多的关系。我使用Referentiel类中的Documents列表和Document中的Referentiel属性实现了它。

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)
}

我必须使用ViewModel来访问我视图中的两个模型,所以我创建了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来更新已编辑的文档。但是当我提交表单时,我的文档保留其默认的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>
}

我希望你理解我,我不是母语人士,但我尽力保持清醒。 (一些变量名用法语,不应该是一个问题,但问我是否想要更好的翻译)。

感谢阅读,我将非常感谢任何解决方案。 ;)

1 个答案:

答案 0 :(得分:0)

我昨天解决了我的问题。谢谢你的回答。我刚在Dal类(数据访问层)中使用了一种方法,用于将实体Document链接到实体Referentiel。这种方式更容易,没有任何东西会抛出异常(即使它之前没有抛出任何东西)。

总结我的新Modifier或&#34;编辑&#34; 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类有选择和更新实体的方法,例如:

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