使用 ViewModel 在数据库中保存 MVC 下拉列表项

Posted

技术标签:

【中文标题】使用 ViewModel 在数据库中保存 MVC 下拉列表项【英文标题】:Save MVC dropdownlist item in database using ViewModel 【发布时间】:2022-01-01 22:28:20 【问题描述】:

我对 MVC 架构完全陌生,需要帮助将下拉列表选择的项目保存在数据库中。基本上,对于其创建视图上的每个项目模型,我都需要一个下拉列表,我需要在其中选择一个客户端(客户端名称显示在 Dropdonwlist 中)。根据选择的客户端,ClientID 应该通过 Post 方法(作为外键)链接到数据库中的 Project 对象实例。

GET 部分显示Create 并填充Dropdownlist 工作,POST 是折磨我的东西。

这是我的项目模型:

    public class Project

    [Key]
    public int ProjectId  get; set; 
    public string Name  get; set; 
    public string Budget  get; set; 
    public string BusinessCase  get; set; 
    [DataType(DataType.Date)]
    public string StartDate  get; set; 
    [DataType(DataType.Date)]
    public string FinishDate  get; set; 
    public int ClientId  get; set; 
    public Client Client  get; set; 
    public ICollection<ProjectMember> ProjectMembers  get; set; 

    public Project()
    
    

这是我的客户端模型:

    public class Client

    [Key]
    public int ClientId  get; set; 
    public string Name  get; set; 
    public string State  get; set; 
    public string Address  get; set; 
    public int VAT  get; set; 
    public ICollection<Project> Projects  get; set; 

    public Client()
    

    

这是我的 CreateProject ViewModel(某些属性可能不需要 - 我刚刚尝试了很多方法......)

public class CreateProjectViewModel

    [Key]
    public int ProjectId  get; set; 
    public string Name  get; set; 
    public string Budget  get; set; 
    public string BusinessCase  get; set; 
    [DataType(DataType.Date)]
    public string StartDate  get; set; 
    [DataType(DataType.Date)]
    public string FinishDate  get; set; 
    public int ClientId  get; set; 
    public Client Client  get; set; 
    public ICollection<ProjectMember> ProjectMembers  get; set; 


    public IEnumerable<SelectListItem> Clients  get; set; 

这是我用于创建的控制器 GET 方法(使用从客户端表中选择值填充下拉列表):

   public IActionResult Create()
    


        var clients = _context.Client.Select(r => r.Name);
        var viewmodel = new CreateProjectViewModel
        
            Clients = new SelectList(clients)
        ;
        
        return View(viewmodel); 

    

最后,这是使用 CreateProjectViewModel 创建视图:

@model ProjectPortfolioApp.ViewModels.CreateProjectViewModel
    
    @
        ViewData["Title"] = "Create";
    



<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>

            <div class="form-group">

                @html.LabelFor(model => model.Client.Name, htmlAttributes: new  @class = "control label col-md-2" )
                **@Html.DropDownListFor(model => model.ClientId, Model.Clients, "---Select Client---", new  @class = "form-control" )**
            </div>

上面的代码可以很好地使用public IEnumerable&lt;SelectListItem&gt; Clients get; set; 按预期显示下拉元素(客户端名称)。我正在苦苦挣扎的是 POST 部分,我收到错误 Object reference not set to an instance of an object。当我发布 model =&gt; model.ClientId 时,如果我基本上通过这里其他任何内容,例如 model =&gt; model.Name,则没有错误,只有客户端 ID 没有成功发布到数据库中(显然)。

这是 HTTP Post 的 sn-p,很可能是错误的:

[ValidateAntiForgeryToken]
    public async Task<ActionResult> Create(CreateProjectViewModel model)
    
        if (ModelState.IsValid)
        
            var project = new Project()  Name = model.Name, ClientId = model.ClientId, Budget = model.Budget, BusinessCase = model.BusinessCase, StartDate = model.StartDate, FinishDate = model.FinishDate ;
            _context.Add(project);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        
       
        return View();

        
    

任何人都可以查看我的代码并帮助我识别:

我的 GET Create 构造是否可以很好地服务于 POST Create 的目的 应该在@Html.DropDownListFor 中作为有效参数传递给 避免错误? HTTP Post Create 应该是什么样的?

我查看了几十个线程,不幸的是没有任何帮助。真的任何帮助将不胜感激。谢谢。

【问题讨论】:

也许您需要使用 SelectList 的构造函数,它告诉在 SelectList 中要使用的 ValueField 是什么。 docs.microsoft.com/en-us/dotnet/api/… 如果您使用浏览器工具 (F12) 并检查显示的下拉列表,您是看到值还是只有文本字段? 你好史蒂夫,在检查页面时它看起来像这样: 它应该是这样的 在我发布的链接中尝试构造函数并使用值和字段名称以及来自客户端类的描述 非常感谢!这真的奏效了。现在检查后的 HTML 看起来像 并正确存储在 DB 中。 【参考方案1】:

你必须修正这个动作

public IActionResult Create()


 var clients = _context.Client
           .Select(r =>  new SelectListItem Value= r.ClientId.ToString(), Text= r.Name)
           .ToList();

        var viewmodel = new CreateProjectViewModel
        
            Clients = clients
             .... another properties
        ;
        
        return View(viewmodel); 

    

并查看

@Html.DropDownListFor(model => model.ClientId, @Model.Clients, "---Select Client---", new  @class = "form-control" )

【讨论】:

您好 Serge,感谢分享固定代码 sn-p,这确实有效,现在值已正确存储在 DB 中。你真的救了我,再次感谢。 不客气!由于答案很有帮助,请不要忘记接受它。其他用户应该知道它有效。您可以通过单击我的答案旁边的复选标记来接受答案。

以上是关于使用 ViewModel 在数据库中保存 MVC 下拉列表项的主要内容,如果未能解决你的问题,请参考以下文章

ViewModel 保存数据

AndroidViewModel+LiveData:更加直接地控制视图的方式

从 Javascript 在 MVC 中为 Post 方法创建 ViewModel

MVC:ViewModel 值不会使用 type="month" 在 datepicker 中显示

在哪里将 DTO 转换为 ViewModel?

ViewModel在MVC3中的应用:一个view显示多个model