使用 ViewModel 和 Entity Framework 让 DropDown SelectList 在 MVC Core 中工作

Getting a DropDown SelectList working in MVC Core using a ViewModel and Entity Framework

我一直在尝试使用 CodeFirst 方法和 MVC Core 并使用 Entity Framework 和 ViewModel 创建应用程序。

问题是分支下拉列表中没有填充任何内容。

我这辈子都不知道自己做错了什么,但我怀疑是我的控制器出了问题。

请帮忙。

我的模型

public class Intermediary
{
    public int IntermediaryID {get; set; }
    public string RegisteredName {get; set; }
    public string TradingName {get; set; }
    public DateTime CreatedDate{get; set; }
    public stringCreatedBy {get; set; }
}

public class Branch
{
    public int BranchID {get; set; }
    public string Name {get; set; }
    public DateTime CreatedDate{get; set; }
    public stringCreatedBy {get; set; }
}

我的视图模型

public class IntermediaryIndexData
{
    public IEnumerable<Intermediary> Intermediaries { get; set; }
    public IEnumerable<Branch> Branches { get; set; }
}

我的控制器

namespace BizDevHub.Controllers
{
    public class IntermediariesController : Controller
    {
        private readonly BizDevHubContext _context;

        public  IntermediariesController(BizDevHubContext context)
        {
            _context = context;
        }

        // GET: Intermediaries
        public async Task<IActionResult> Index(int? id, int? intermediaryID)
        {
            var viewModel = new IntermediaryIndexData();
            viewModel.Intermediaries = await _context.Intermediaries
                        .Include(i => i.Branch)
                  .AsNoTracking()
                  .OrderBy(i => i.RegisteredName)
                  .ToListAsync();

            //if (id != null)
            //{
            //    ViewData["IntermdiaryID"] = id.Value;
            //    Instructor instructor = viewModel.Instructors.Where(
            //        i => i.ID == id.Value).Single();
            //    viewModel.Courses = instructor.CourseAssignments.Select(s => s.Course);
            //}

            //if (courseID != null)
            //{
            //    ViewData["CourseID"] = courseID.Value;
            //    viewModel.Enrollments = viewModel.Courses.Where(
            //        x => x.CourseID == courseID).Single().Enrollments;
            //}

            return View(viewModel);
        }

        // GET: Intermediaries/Details/5
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var intermediary = await _context.Intermediaries
                .Include(c => c.Branch)
                .AsNoTracking()
                .FirstOrDefaultAsync(m => m.IntermediaryID == id);
            if (intermediary == null)
            {
                return NotFound();
            }

            return View(intermediary);
        }

        // GET: Intermediaries/Create
        public IActionResult Create()
        {
            PopulateBranchesDropDownList();
            return View();
        }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("IntermediaryID,RegisteredName,TradingName,Registration,VATNumber,FSPNumber,CreatedDate,CreatedBy,BranchID,AgreementID")] Intermediary intermediary)
    {
        if (ModelState.IsValid)
        {
            _context.Add(intermediary);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        PopulateBranchesDropDownList(intermediary.BranchID);
        return View(intermediary);
    }

        // GET: Intermediaries/Edit/5
    public async Task<IActionResult> Edit(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var intermediary = await _context.Intermediaries
            .AsNoTracking()
            .FirstOrDefaultAsync(m => m.IntermediaryID == id);
        if (intermediary == null)
        {
            return NotFound();
        }
        PopulateBranchesDropDownList(intermediary.BranchID);
        return View(intermediary);
    }

    [HttpPost, ActionName("Edit")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> EditPost(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var intermediaryToUpdate = await _context.Intermediaries
            .FirstOrDefaultAsync(c => c.IntermediaryID == id);

        if (await TryUpdateModelAsync<Intermediary>(intermediaryToUpdate,
            "",
            c => c.RegisteredName,
            c => c.TradingName,
            c => c.Registration,
            c => c.VATNumber,
            c => c.FSPNumber,
            c => c.CreatedBy,
            c => c.CreatedDate,
            c => c.BranchID,
            c => c.AgreementID
            ))
        {
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException /* ex */)
            {
                //Log the error (uncomment ex variable name and write a log.)
                ModelState.AddModelError("", "Unable to save changes. " + "Try again, and if the problem persists, " + "see your system administrator.");
            }
            return RedirectToAction(nameof(Index));
        }
        PopulateBranchesDropDownList(intermediaryToUpdate.BranchID);
        ViewData["BranchID"] = new SelectList(_context.Branches, "BranchID", "Name", intermediaryToUpdate.BranchID);
        return View(intermediaryToUpdate);
    }

        // GET: Intermediaries/Delete/5
        public async Task<IActionResult> Delete(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var intermediary = await _context.Intermediaries
                .Include(c => c.Branch)
                .AsNoTracking()
                .FirstOrDefaultAsync(m => m.IntermediaryID == id);
            if (intermediary == null)
            {
                return NotFound();
            }

            return View(intermediary);
        }

        // POST: Intermediaries/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var intermediary = await _context.Intermediaries.FindAsync(id);
            _context.Intermediaries.Remove(intermediary);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        private bool IntermediaryExists(int id)
        {
            return _context.Intermediaries.Any(e => e.IntermediaryID == id);
        }

        private void PopulateBranchesDropDownList(object selectedBranch = null)
        {
            var branchesQuery = from d in _context.Branches
                                   orderby d.Name
                                   select d;
            ViewBag.DepartmentID = new SelectList(branchesQuery.AsNoTracking(), "BranchID", "Name", selectedBranch);
        }
    }
}

我的观点

我使用脚手架添加了视图

索引

@model BizDevHub.Models.ViewModels.IntermediaryIndexData

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

<h2>Intermediary</h2>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>Registered Name</th>
            <th>Trading As</th>
            <th>Created Date</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.Intermediaries)
        {
            string selectedRow = "";
            if (item.IntermediaryID == (int?)ViewData["IntermediaryID"])
            {
                selectedRow = "success";
            }
        <tr class="@selectedRow">
            <td>
                @Html.DisplayFor(modelItem => item.RegisteredName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.TradingName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FSPNumber)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Registration)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.VATNumber)
            </td>
            <th>
                @Html.DisplayNameFor(model => item.Branch)
            </th>
            <td>
                <a asp-action="Edit" asp-route-id="@item.IntermediaryID">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.IntermediaryID">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.IntermediaryID">Delete</a>
            </td>
        </tr>
        }
    </tbody>
</table>

编辑

@model BizDevHub.Models.Intermediary

@{
    ViewData["Title"] = "Edit";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Edit</h2>

<h4>Intermediary</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="IntermediaryID" />
            <div class="form-group">
                <label asp-for="RegisteredName" class="control-label"></label>
                <input asp-for="RegisteredName" class="form-control" />
                <span asp-validation-for="RegisteredName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="TradingName" class="control-label"></label>
                <input asp-for="TradingName" class="form-control" />
                <span asp-validation-for="TradingName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Registration" class="control-label"></label>
                <input asp-for="Registration" class="form-control" />
                <span asp-validation-for="Registration" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="VATNumber" class="control-label"></label>
                <input asp-for="VATNumber" class="form-control" />
                <span asp-validation-for="VATNumber" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="FSPNumber" class="control-label"></label>
                <input asp-for="FSPNumber" class="form-control" />
                <span asp-validation-for="FSPNumber" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="CreatedDate" class="control-label"></label>
                <input asp-for="CreatedDate" class="form-control" />
                <span asp-validation-for="CreatedDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="CreatedBy" class="control-label"></label>
                <input asp-for="CreatedBy" class="form-control" />
                <span asp-validation-for="CreatedBy" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Branch" class="control-label"></label>
                <select asp-for="BranchID" class="form-control" asp-items="ViewBag.BranchID">
                    <option value=""></option>
                </select>
                <span asp-validation-for="BranchID" class="text-danger" />
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>

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

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

@model BizDevHub.Models.Intermediary

创建

@model BizDevHub.Models.Intermediary

@{
    ViewData["Title"] = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Create</h2>

<h4>Intermediary</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="RegisteredName" class="control-label"></label>
                <input asp-for="RegisteredName" class="form-control" />
                <span asp-validation-for="RegisteredName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="TradingName" class="control-label"></label>
                <input asp-for="TradingName" class="form-control" />
                <span asp-validation-for="TradingName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Registration" class="control-label"></label>
                <input asp-for="Registration" class="form-control" />
                <span asp-validation-for="Registration" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="VATNumber" class="control-label"></label>
                <input asp-for="VATNumber" class="form-control" />
                <span asp-validation-for="VATNumber" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="FSPNumber" class="control-label"></label>
                <input asp-for="FSPNumber" class="form-control" />
                <span asp-validation-for="FSPNumber" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="CreatedBy" class="control-label"></label>
                <input asp-for="CreatedBy" class="form-control" />
                <span asp-validation-for="CreatedBy" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Branches" class="control-label"></label>
                <select asp-for="BranchID" class="form-control" asp-items="ViewBag.BranchID">
                    <option value="">-- Select Branch --</option>
                </select>
                <span asp-validation-for="BranchID" class="text-danger" />
            </div>
            @*<div class="form-group">
                <label asp-for="AgreementID" class="control-label"></label>
                <input asp-for="AgreementID" class="form-control" />
                <span asp-validation-for="AgreementID" class="text-danger"></span>
            </div>*@
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>

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

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

我这辈子都不知道自己做错了什么,但我怀疑是我的控制器出了问题。

请帮忙。

BranchIntermediary 之间似乎是一对多的关系,所以你的模型设计应该是这样的:

 public class Intermediary
{
    public int IntermediaryID { get; set; }
    public string RegisteredName { get; set; }
    public string TradingName { get; set; }
    public DateTime CreatedDate { get; set; }
    public string CreatedBy {get; set; }

    public int BranchID { get; set; }
    public Branch Branch { get; set; }
}
public class Branch
{
    public int BranchID { get; set; }
    public string Name { get; set; }
    public DateTime CreatedDate { get; set; }
    public string CreatedBy {get; set; }

    public List<Intermediary> Intermediaries { get; set; }
}

->>问题是分支下拉列表中没有填充任何内容。

view中ViewBagb的key-name和controller不一致,应该改PopulateBranchesDropDownList方法

private void PopulateBranchesDropDownList(object selectedBranch = null)
    {
        var branchesQuery = from d in _context.Branches
                            orderby d.Name
                            select d;
        ViewBag.BranchID= new SelectList(branchesQuery.AsNoTracking(), "BranchID", "Name", selectedBranch);
    }

您可以参考 here 以了解有关 EF Core 中关系的更多详细信息。