簡體   English   中英

ASP.NET Core MVC 無法綁定復選框列表

[英]ASP.NET Core MVC cannot bind checkboxlist

環境是VS2019,ASP.NET Core MVC 2.1。 我對此很陌生。 在發布時, Book對象的BookCategory列表為空。 我無法弄清楚哪個(或哪些)部分是錯誤的。

有 3 個模型, BookCategory和連接模型BookCategory BookCategory是多對多的,關系存儲在BookCategory表中。

public class Book
{
    public int BookId { get; set; }

    [Required]
    public string Title { get; set; }

    public ICollection<BookCategory> BookCategories { get; set; }
}

public class Category
{
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }

    public ICollection<BookCategory> BookCategories { get; set; }
}

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

    public bool IsSelected { get; set; }
}

BooksController如下所示。 GetBookAndBookCategoryData將獲得一個帶有關聯BookCategory列表的Book對象。 PopulateBookCategoriesList將向視圖包添加一個Category列表。

    [HttpGet]
    public async Task<IActionResult> Book(int? id)
    {
        int bookId = id.GetValueOrDefault();

        await PopulateBookCategoriesList();
        var book = await GetBookAndBookCategoryData(bookId);
        return View(book);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Book(int? id, Book book)
    {
        id = id ?? 0;
        if (id != book.BookId)      // ?? means coalesce, it takes the first non-null value.
        {
            return NotFound();
        }

        var category = _context.Categories;

        if (ModelState.IsValid)
        {
            // if create a new book
            if (id == 0)
            {
                _context.Add(book);
                await _context.SaveChangesAsync();

                foreach (var bc in book.BookCategories)
                {
                    var bcat = new BookCategory() { BookId = book.BookId, CategoryId = bc.CategoryId, IsSelected = bc.IsSelected };
                    _context.Add(bcat);
                }

                await _context.SaveChangesAsync();
            }
            else
            {
                _context.Update(book);

                foreach (var i in book.BookCategories)
                {
                    var bcat = _context.BookCategories.FirstOrDefault(bc => bc.BookId == book.BookId && bc.CategoryId == i.CategoryId);
                    bcat.IsSelected = i.IsSelected;
                    _context.Update(bcat);
                }
            }

            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        return View(book);
    }

    private async Task<Book>  GetBookAndBookCategoryData(int BookId = 0)
    {
        var book = new Book();
        var category = await _context.Categories.ToListAsync();
        if (BookId == 0)
        {
                            book.BookCategories = new List<BookCategory>();
            foreach (var c in category)     
            {
                book.BookCategories.Add(new BookCategory() { BookId = BookId, CategoryId = c.CategoryId, IsSelected = false });
            }
        }
        else
        {
            book = await _context.Books.FindAsync(BookId);

            if (book.BookCategories is null || book.BookCategories.Count == 0)
            {
                book.BookCategories = new List<BookCategory>();

                foreach (var c in _context.Categories)
                {
                    book.BookCategories.Add(new BookCategory() { BookId = book.BookId, CategoryId = c.CategoryId, IsSelected = false });
                }
            }
        }

        return book;
    }

    private async Task PopulateBookCategoriesList()
    {
        var list = await _context.Categories.ToListAsync();
        ViewBag.CategoryList = list;
    }

在 DBContext 中:

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public DbSet<MvcTest.Models.Book> Books { get; set; }
    public DbSet<MvcTest.Models.Category> Categories { get; set; }

    public DbSet<MvcTest.Models.BookCategory> BookCategories { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Category>().HasData(
            new Category { CategoryId = 1, CategoryName = "AAA" },
            new Category { CategoryId = 2, CategoryName = "BBB" },
            new Category { CategoryId = 3, CategoryName = "CCC" },
            new Category { CategoryId = 4, CategoryName = "DDD" },
            new Category { CategoryId = 5, CategoryName = "EEE" },
            new Category { CategoryId = 6, CategoryName = "FFF" },
            new Category { CategoryId = 7, CategoryName = "GGG" }
            );

        modelBuilder.Entity<BookCategory>()
            .HasKey(bc => new { bc.BookId, bc.CategoryId });
        modelBuilder.Entity<BookCategory>()
            .HasOne(bc => bc.Book)
            .WithMany(b => b.BookCategories)
            .HasForeignKey(bc => bc.BookId);
        modelBuilder.Entity<BookCategory>()
            .HasOne(bc => bc.Category)
            .WithMany(c => c.BookCategories)
            .HasForeignKey(bc => bc.CategoryId);

        base.OnModelCreating(modelBuilder);
    }
}

風景:

@model MvcTest.Models.Book

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

<h2>Create</h2>

<h4>Book</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Book">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="BookId" class="control-label"></label>
                <input asp-for="BookId" disabled="disabled" class="form-control" />
                <input asp-for="BookId" class="form-control invisible" />
                <span asp-validation-for="BookId" class="text-danger"></span>
            </div>
            <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">
                @{ var categoryList = ViewBag.CategoryList as List<Category>; }
                @foreach (var bc in Model.BookCategories)
                {
                    <div class="col-md-3 col-sm-6">
                        <div class="checkbox">
                            <label>
                                <input type="checkbox" checked="@bc.IsSelected" name="BookCategories"
                                       value="@bc.CategoryId">@categoryList.Where(c => c.CategoryId == bc.CategoryId).SingleOrDefault().CategoryName
                            </label>
                        </div>
                    </div>
                }
            </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");}
}

這是很多代碼,我感謝您的時間和耐心。

您的復選框的名稱是SelectedCategoryValues ,當您提交時,您需要一個List<int> SelectedCategoryValues on action 參數來存儲所有選定類別的 id 列表。並且您無法使用表單提交直接映射到book.BookCategories

嘗試使用以下代碼在Post操作中填充Book對象的BookCategory列表:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Book(int? id, List<int> SelectedCategoryValues, Book book)
    {
        var bookCategories = new List<BookCategory>();
        foreach (var c in _context.Categories)
        {
            bookCategories.Add(
                new BookCategory() { BookId = book.BookId, CategoryId = c.CategoryId, IsSelected = SelectedCategoryValues.Contains(c.CategoryId) ? true : false }
            );

        }
        book.BookCategories = bookCategories;
        //...
    }

你是如何從數據庫中檢索它的? 如果您希望書對象和類別對象包含在模型中,則需要添加一個

.Include(x => x.Book)
.Include(x => x.Category)

書對象也包含在從數據庫返回的對象中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM