包含[多对多关系的部分视图]的编辑视图的 MVC 问题

MVC problem with view of Edit that contain [partial view from relation many to many]

我尝试创建一个图书馆系统,其中在类别中与书籍有很多关系,我需要在我的书籍编辑视图中放入实体的部分视图,有人可以帮助我吗?

我的编辑视图:

@model MVC_Library.Models.Book


@{
    ViewData["Title"] = "Edit";
    BookCategory teste = ViewBag.testeview;
}

<h1>Edit</h1>

<h4>Book</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="BookId" />
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Author" class="control-label"></label>
                <input asp-for="Author" class="form-control" />
                <span asp-validation-for="Author" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="PublishDate" class="control-label"></label>
                <input asp-for="PublishDate" class="form-control" />
                <span asp-validation-for="PublishDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="BasePrice" class="control-label"></label>
                <input asp-for="BasePrice" class="form-control" />
                <span asp-validation-for="BasePrice" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Quantity" class="control-label"></label>
                <input asp-for="Quantity" class="form-control" />
                <span asp-validation-for="Quantity" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="PublishingCompanyId" class="control-label"></label>
                <select asp-for="PublishingCompanyId" class="form-control" asp-items="ViewBag.PublishingCompanyId"></select>
                <span asp-validation-for="PublishingCompanyId" class="text-danger"></span>
            </div>
            <div>
                @Html.Partial("_EditBookCategory", teste)
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

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

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

我的部分观点行得通(但以这种方式只是预 select 一个类别项目)

@model MVC_Library.Models.BookCategory

<div class="row">
    <div class="col-md-12">
        <label asp-for="CategoryId" class="control-label"></label>
        <select multiple asp-for="CategoryId" class="form-control" name = "BookCategory[]" asp-items="ViewBag.SelectedCategory"></select>
    </div>
</div>


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

和我的控制器编辑部分

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

            var book = await _context.Books.FindAsync(id);
            if (book == null)
            {
                return NotFound();
            }
            List<BookCategory> bookCategory = _context.BookCategories.Where(e => e.BookId == id).ToList();
            ViewData["PublishingCompanyId"] = new SelectList(_context.PublishingCompanies, "PublishingCompanyId", "PublishingCompanyName", book.PublishingCompanyId);

//this is what i try for try return mutiple category select (don't work with this viewbag)
           /* ViewBag.SelectedCategory = new MultiSelectList(_context.Categories.ToList(), "CategoryId", "CategoryName", bookCategory); */

//this viewbag return only one category selected but work
            ViewBag.testeview = bookCategory.First();

            return View(book);
        }

刚刚selected(第一个),但是想return全部。如果可能,需要帮助。

如果你想显示所有相关类别selected:

  1. 确保 asp-for="CategoryId" 这里的 CategoryId 应该是 int[]string[] 的类型。 只需删除 asp-for 标记助手,因为您在此处添加了 name="BookCategory[]",它将覆盖 asp-for 生成的名称属性。当你提交表单时,无论你是否添加asp-for,你的操作总是需要包含一个名为BookCategory[]的参数。

此外 BookCategory[] 不是正确的名称,数组中没有索引,它应该是 BookCategory 或任何其他名称,并且操作中的参数名称应该是 int[] 类型或string[]。猜测您可能希望将 selected 值与列表模型 BookCategory 的 CategoryId 相匹配。对于 multiple select.

是不可接受的
  1. 确保 MultiSelectList 中的最后一个参数应为 int[]string[]。根据您的代码,MultiSelectList 中的 dataValueField 匹配 CategoryId 属性,因此您的最后一个参数应该类似于 bookCategory.Select(a=>a.CategoryId).ToList().

    ViewBag.SelectedCategory = new MultiSelectList(_context.Categories.ToList(), "CategoryId", "CategoryName",
                                            bookCategory.Select(a=>a.CategoryId).ToList());
    
  2. 不用ViewBag.testeview,改成如下:

    @Html.Partial("_EditBookCategory", new BookCategory())       
    

整个工作演示应该是这样的:

型号:

public class Book
{
    public int BookId { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public DateTime PublishDate { get; set; }
    public int BasePrice { get; set; }
    public int Quantity { get; set; }
    public int PublishingCompanyId { get; set; }
    public List<BookCategory> BookCategory { get; set; }
}
public class Category
{
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
    public List<BookCategory> BookCategory { get; set; }

}
public class BookCategory
{
    public int CategoryId { get; set; }
    public int BookId { get; set; }
    public Category Category { get; set; }
    public Book Book { get; set; }
}

查看:

@model Book
@{
    ViewData["Title"] = "Edit";
}
<h1>Edit</h1>    
<h4>Book</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="BookId" />
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Author" class="control-label"></label>
                <input asp-for="Author" class="form-control" />
                <span asp-validation-for="Author" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="PublishDate" class="control-label"></label>
                <input asp-for="PublishDate" class="form-control" />
                <span asp-validation-for="PublishDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="BasePrice" class="control-label"></label>
                <input asp-for="BasePrice" class="form-control" />
                <span asp-validation-for="BasePrice" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Quantity" class="control-label"></label>
                <input asp-for="Quantity" class="form-control" />
                <span asp-validation-for="Quantity" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="PublishingCompanyId" class="control-label"></label>
                <select asp-for="PublishingCompanyId" class="form-control" asp-items="ViewBag.PublishingCompanyId"></select>
                <span asp-validation-for="PublishingCompanyId" class="text-danger"></span>
            </div>
            <div>
                                      //change here....
                @Html.Partial("_EditBookCategory", new BookCategory())  
            </div>
            <div class="form-group">
                <input type="submit" value="Save" 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 BookCategory

<div class="row">
    <div class="col-md-12">
        <label asp-for="CategoryId" class="control-label"></label>
        <select multiple  class="form-control" name="CategoryId" asp-items="ViewBag.SelectedCategory"></select>
    </div>
</div>

控制器:

注意:我只是hard-coded数据,因为方便测试,和你从数据库中获取数据是一样的。你只需要像我的评论所说的那样改变,其他代码不需要像我所做的那样改变。

public IActionResult Edit(int? id)
{
    var book = new Book()
    {
        BookId = 1,
        PublishDate = DateTime.Now,
        Author = "a1",
        BasePrice = 34,
        PublishingCompanyId = 1,
        Quantity = 23,
        Title = "aa"
    };
    List<BookCategory> bookCategory = new List<BookCategory>()
    {
        new BookCategory(){BookId=1,CategoryId=1},
        new BookCategory(){BookId=2,CategoryId=1},
        new BookCategory(){BookId=2,CategoryId=3}
    };
    ViewData["PublishingCompanyId"] = new List<SelectListItem>() {
        new SelectListItem() { Value = "1", Text = "Elementos1" },
        new SelectListItem() { Value = "2", Text = "Elementos2" },
        new SelectListItem() { Value = "3", Text = "Elementos3" }
        };
    var c = new List<Category>()
    {
        new Category(){CategoryId=1,Name="aa"},
        new Category(){CategoryId=2,Name="bb"},
        new Category(){CategoryId=3,Name="cc"}
    };
     //change here....
    ViewBag.SelectedCategory = new MultiSelectList(c, "CategoryId", "Name", bookCategory.Select(a=>a.CategoryId).ToList());

    //ViewBag.testeview = bookCategory.First();
    return View(book);
}
[HttpPost]
public IActionResult Edit(int? id,Book book, int[] CategoryId)
{
    //do your stuff......
    return View();
}

结果:


如何选择多个选项,你只需要按住Ctrl键的同时点击选项即可。