【问题标题】:MVC How to Enumerate through a Second Model's DataMVC 如何枚举第二个模型的数据
【发布时间】:2021-12-23 08:54:00
【问题描述】:

在“创建”视图中,我试图枚举一些辅助/外部模型数据。相反,该页面返回 NullReferenceError,我无法弄清楚为什么模型为空。如果我在 null 的枚举字段上过滤 IsNull,页面将加载。

以下是控制器内部的创建函数:

public IActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("SOFT_ID,SOFT_NAME,DEPT_ID,IT_CONTACT,SOFT_EXP_DATE,SOFT_SUP_PERIOD,SOFT_OUT_OF_SERVICE,VEND_ID,SUPP_ID,SOFT_IS_RENEWED")] Software software)
{
    if (ModelState.IsValid)
    {
        _context.Add(software);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View();
}

接下来是模型。下面是主要模型的软件模型和次要模型的部门模型。我想从另外两个模型加载数据,它们的设置与部门模型完全相同。

软件模型:

public class Software
{
    [Key]
    public int SOFT_ID { get; set; }
    [Required]
    [StringLength(50, ErrorMessage = "Software Name cannont be longer than 50 characters.")]
    [Display(Name = "Software Name")]
    public string SOFT_NAME { get; set; }
    [Required]
    public virtual Department DEPT_ID { get; set; }
    [Required]
    [Display(Name = "IT Contact")]
    public string IT_CONTACT { get; set; }
    [Required]
    [Display(Name = "Expiration Date")]
    [DataType(DataType.Date)]
    public DateTime SOFT_EXP_DATE { get; set; }
    [Required]
    [Range(1,5)]
    [Display(Name = "Support Period")]
    public int SOFT_SUP_PERIOD { get; set; }
    [Display(Name = "No Longer Used")]
    public bool SOFT_OUT_OF_SERVICE { get; set; }
    [Required]
    public virtual Vendor VEND_ID { get; set; }
    [Required]
    public virtual Supplier SUPP_ID { get; set; }
    [Display(Name = "Renewed?")]
    public bool SOFT_IS_RENEWED { get; set; }
    
    public IEnumerable<Department> Departments { get; set; }
    public IEnumerable<Supplier> Suppliers { get; set; }
    public IEnumerable<Vendor> Vendors { get; set; }
}

部门模型:

public class Department
{
    [Key]
    public int DEPT_ID { get; set; }
    [Required]
    [Display(Name = "Department Name")]
    public string DEPT_NAME { get; set; }
    [Required]
    [Display(Name = "Department Contact Name")]
    public string DEPT_CONTACT { get; set; }
    [Required]
    [Display(Name = "Email")]
    public string DEPT_EMAIL { get; set; }
    [Required]
    [Display(Name = "Phone")]
    public string DEPT_PHONE { get; set; }
}

最后是视图。抛出 NullReferenceError 的部分是部门、供应商和供应商的 @foreach 循环。这些应该是填充下拉菜单。

@model SoftwareManager_SSO.Models.Software

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>


<h4>Software</h4>
<hr />
<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">
                <label asp-for="SOFT_NAME" class="control-label"></label>
                <input asp-for="SOFT_NAME" class="form-control" />
                <span asp-validation-for="SOFT_NAME" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="DEPT_ID.DEPT_NAME" class="control-label"></label>
                <select class="form-control">
                    <option value="" disabled selected>Select A Dept</option>
                    @foreach (var item in Model.Departments)
                    {
                        <option value="@item.DEPT_ID">@item.DEPT_NAME</option>
                    }
                </select>
                <span asp-validation-for="DEPT_ID.DEPT_NAME"></span>
            </div>

            <div hidden="hidden" class="form-group">
                <label asp-for="DEPT_ID" class="control-label"></label>
                <input asp-for="DEPT_ID" class="form-control" disabled="disabled" />
                <span asp-validation-for="DEPT_ID" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="DEPT_ID.DEPT_CONTACT" class="control-label"></label>
                <input id="dept_contact" asp-for="DEPT_ID.DEPT_CONTACT" disabled="disabled" class="form-control" />
                <span asp-validation-for="DEPT_ID.DEPT_CONTACT" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="IT_CONTACT" class="control-label"></label>
                <select class="form-control">
                    <option value="" selected>Select IT Person</option>
                    <option value="uciltas@tohowater.com">Umit Ciltas</option>
                    <option value="sslaven@tohowater.com">Stephen Slaven</option>
                    <option value="imoreno@tohowater.com">Ismael Moreno</option>
                    <option value="dkearney@tohowater.com">David Kearney</option>
                </select>
                <span asp-validation-for="IT_CONTACT" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="SOFT_EXP_DATE" class="control-label"></label>
                <input asp-for="SOFT_EXP_DATE" class="form-control" />
                <span asp-validation-for="SOFT_EXP_DATE" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="SOFT_SUP_PERIOD" class="control-label"></label>
                <select class="form-control">
                    <option value="" selected>Select A Support Period</option>
                    <option value="1">1 Year</option>
                    <option value="2">2 Years</option>
                    <option value="3">3 Years</option>
                    <option value="4">4 Years</option>
                    <option value="5">5 Years</option>
                </select>
                <span asp-validation-for="SOFT_SUP_PERIOD" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="VEND_ID.VEND_NAME" class="control-label"></label>
                <select class="form-control">
                    <option value="" disabled selected>Select a Vendor</option>
                    @foreach (var item in Model.Vendors)
                    {
                        <option value="@item.VEND_ID">@item.VEND_NAME</option>
                    }
                </select>
                <span asp-validation-for="VEND_ID.VEND_NAME"></span>
            </div>

            <div class="form-group">
                <label asp-for="SUPP_ID.SUPP_NAME" class="control-label"></label>
                <select class="form-control">
                    <option value="" disabled selected>Select a Vendor</option>
                    @foreach (var item in Model.Suppliers)
                    {
                        <option value="@item.SUPP_ID">@item.SUPP_NAME</option>
                    }
                </select>
                <span asp-validation-for="SUPP_ID.SUPP_NAME"></span>
            </div>

            <div class="form-group form-check">
                <label class="form-check-label">
                    <input class="form-check-input" asp-for="SOFT_IS_RENEWED" /> @Html.DisplayNameFor(model => model.SOFT_IS_RENEWED)
                </label>
            </div>
            <div class="form-group form-check">
                <label class="form-check-label">
                    <input class="form-check-input" asp-for="SOFT_OUT_OF_SERVICE" /> @Html.DisplayNameFor(model => model.SOFT_OUT_OF_SERVICE)
                </label>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

老实说,我很茫然,无法弄清楚这一点。我已经阅读了该站点上的许多其他帖子,但我无法弄清楚我的代码与我看到的类似代码之间有什么不同。我将继续搜索帖子,但感谢任何帮助。

【问题讨论】:

    标签: model-view-controller razor computer-science


    【解决方案1】:

    您需要将有关这些部门的信息传递到视图中。这通常通过创建视图模型并将其传递给视图来完成。

    在您的代码中,您的视图需要一个“软件”模型,因此您可以创建一个(并确保填充“部门”)并将其传递到您的视图中。

    获得模型后,您可以使用 Html 帮助程序来生成下拉列表,而不是使用循环手动构建它。

    例如:

    @Html.DropDownListFor(model => model.departments )  
    

    或许

    @Html.DropDownListFor(model => model.departments as selectlist)
    

    抱歉,如果某些语法不太正确,在我的手机上无法很好地检查。但这应该会给你正确的想法。

    编辑

    您需要在控制器中构建视图模型并将其传递给视图。

    var viewModel = new Software();
    viewModel.Departments = new List<Department>() {
        new Department() { DEPT_NAME = "Some department name"}
    };
    return View(viewModel);
    

    或者如果从数据库中动态提取(例如通过实体框架):

    var viewModel = new Software();
    viewModel.Departments = _db.Departments.ToList()
    return View(viewModel);
    

    【讨论】:

    • 如果模型数据从数据库后端提取,这仍然有效吗?例如,我今天可能有四个部门,但将来我可能会再增加两个部门。它从中提取的部门表不是静态的,并且将来可能拥有比现在更多的数据。谢谢你的建议,我会看看我是否可以把它融入我的设置中。
    • 我尝试了以下方法,但仍然得到 NullReferenceException:对象引用未设置为对象的实例。 @Html.DropDownListFor(Model =&gt; Model.Departments, new SelectList(Model.Departments, "DEPT_ID", "DEPT_NAME"),"Select Department")) 是这样吗?
    • 如果您没有在控制器中填充视图模型,那么您将始终获得 Model.Departments 的空引用。我将用如何创建模型并传递给视图的示例来更新答案
    • 非常感谢!您编辑的关于通过 viewModel 拉入数据库表的部分起到了作用。对于将来看到这一点的任何人,我将该代码添加到初始的 Create() 函数中。之后,我的下拉列表中填充了数据库表中的行。再次感谢 Dean O'Brien!
    • 非常欢迎您。很高兴它成功了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 2022-06-22
    • 1970-01-01
    相关资源
    最近更新 更多