MVC 如何枚举第二个模型的数据

MVC How to Enumerate through a Second Model's Data

在“创建”视图中,我试图枚举一些 secondary/external 模型数据。相反,页面 returns 出现 NullReferenceError,我无法弄清楚为什么模型为空。如果我在为空的枚举字段上过滤 IsNull,页面将加载。

下面是Controller中的Create函数:

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

接下来是模特。下面是 Software 模型,这是主要模型,Department 模型是次要模型。我想从其他两个模型加载数据,它们的设置与部门模型完全一样。

软件型号:

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

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

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

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

获得模型后,您可以使用 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);

或者如果从数据库动态拉取(例如通过entity framework):

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