【问题标题】:How to bind data from dropdown list in asp.net core如何从asp.net核心的下拉列表中绑定数据
【发布时间】:2021-07-14 03:00:22
【问题描述】:

我是asp.net core的新手,尝试用实体框架开发一个教育项目(e-shop)。 我在模型绑定方面遇到了一些问题。 我有 2 个模型:产品和类别。

public class Product
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public Category Category { get; set; }
        public decimal Price { get; set; }

    }
public class Category
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

产品控制器:

[HttpGet]
        public IActionResult Create()
        {
            ViewBag.Categories = new SelectList(categoryRepo.Categories, "Id", "Name");

            return View("Edit", new Product());
        }

        [HttpGet]
        public IActionResult Edit(int productId)
        {
            return View(repo.Products.FirstOrDefault(p => p.Id == productId));
        }

        [HttpPost]
        public IActionResult Edit(Product product)
        {
            if (ModelState.IsValid)
            {
                repo.SaveProduct(product);
                TempData["Message"] = $"{product.Title} successfully saved";
                return RedirectToAction("Index");
            }
            else
            {
                ViewBag.Categories = new SelectList(categoryRepo.Categories, "Id", "Name");
                return View(product);
            }

        }

使用 ProductController 中的 Create 方法并在 Edit.cshtml 中将类别添加到下拉列表中一切正常

@model Product
@{
    ViewData["Title"] = "Add product";
}
<h1>@ViewData["Title"]</h1>
<form asp-action="Edit" asp-controller="Product" method="post">
    <div class="form-group">
        <label asp-for="Title"></label>
        <div>
            <span class="text-danger" asp-validation-for="Title"></span>
        </div>
        <input class="form-control" type="text" asp-for="Title" />
    </div>
    <div class="form-group">
        <label asp-for="Description"></label>
        <div>
            <span class="text-danger" asp-validation-for="Description"></span>
        </div>
        <textarea class="form-control" asp-for="Description" cols="15" rows="10"></textarea>
    </div>
    <div class="form-group">
        <label asp-for="Category"></label>
        <div>
            <span class="text-danger" asp-validation-for="Category"></span>
        </div>
        <select asp-for="Category" asp-items="ViewBag.Categories">
            <option disabled>Choose the category</option>
        </select>
    </div>
    <div class="form-group">
        <label asp-for="Price"></label>
        <div>
            <span class="text-danger" asp-validation-for="Price"></span>
        </div>
        <input class="form-control" type="text" asp-for="Price" />
    </div>
    <button class="btn btn-success" type="submit">Add</button>
</form>

但是当我尝试将表单提交回 ProductController.cs 中的 Edit 方法时,Category 字段没有绑定到 Product,我只收到验证错误“Choose the category”。

请帮我解决这个问题!

附: 数据库上下文:

public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options){ }

        public DbSet<Product> Products { get; set; }
        public DbSet<Category> Categories { get; set; }
    }

IProductRepository 的实现

public class EFProductRepository : IProductRepository
    {
        private AppDbContext context;

        public EFProductRepository(AppDbContext ctx)
        {
            context = ctx;
        }
        public IQueryable<Product> Products => context.Products.Include(p => p.Category);

        public void SaveProduct(Product product)
        {
            if (product.Id == 0)
            {
                context.Products.Add(product);
            }
            else
            {
                Product entry = context.Products.FirstOrDefault(p => p.Id == product.Id);

                if (entry != null)
                {
                    entry.Title = product.Title;
                    entry.Description = product.Description;
                    entry.Category = product.Category;
                    entry.Price = product.Price;
                }
            }

            context.SaveChanges();
        }
    }

ICategoryRepository 的实现

public class EFCategoryRepository : ICategoryRepository
    {
        private AppDbContext context;

        public EFCategoryRepository(AppDbContext ctx)
        {
            context = ctx;
        }
        public IQueryable<Category> Categories => context.Categories;
    }

【问题讨论】:

    标签: c# asp.net


    【解决方案1】:

    修复 ViewBag.Categories 的操作

     ViewBag.Categories = categoryRepo.Categories
                         .Select( i=> new SelectListItem {
                          Value=i.Id.ToString(),
                          Text=i.Name 
                         }).ToList();
    
    

    将 CategoryId 添加到 Product 类,并检查您的 Product fluent API。 Product 中不应该是关于所需类别的任何内容,将所有内容更改为 CategoryId。

    public class Product
        {
           ...
            public int? CategoryId {get;set;}
            public  virtual Category Category { get; set; }
          ....
    
        }
    
        public class Category
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public virtual ICollection<Product> Products {get; set;}
        }
    
    

    并修复视图

     <select asp-for="CategoryId" asp-items="ViewBag.Categories"></select>
    

    【讨论】:

    • 谢谢,但不起作用。我调试发布方法 Edit 并在 ModelState 中看到 ValidationState 对 Category 无效。使用 CategoryId 一切正常。
    • @tiomkin 你的 dbcontext 中有 fluent Api 吗?请发布产品的所有内容
    • 我已添加到我的问题中
    • @tiomkin 谢谢,我也更新了我的答案。但是我仍然看不到您的 Product fluent Api。这是最重要的部分。
    • 哦,非常感谢!!真的,我没有从类别中删除 [必填]。感谢您的宝贵时间!
    【解决方案2】:

    您必须在 Product 中添加 CategoryId 对象,因此您的产品类应该是

    public class Product
        {
            public int Id { get; set; }
            public string Title { get; set; }
            public string Description { get; set; }
            public int CategoryId {get;set;}
            public Category Category { get; set; }
            public decimal Price { get; set; }
    
        }
    

    在您的视图页面中,类别选择元素应使用 CategoryId 而不是 asp-for 属性中的 Category 应该是这样的

     <select asp-for="CategoryId" asp-items="ViewBag.Categories"></select>
    

    【讨论】:

      猜你喜欢
      • 2021-12-29
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多