【问题标题】:How to save data from multiple selection dropdown如何从多选下拉菜单中保存数据
【发布时间】:2019-10-20 07:23:00
【问题描述】:

我开始学习实体框架和 asp.net,我想使用所有的 CRUD 操作。 我有任务和类别模型,它们是多对多的关系。在我的数据库中有 3 个表:1.Task(它包含 Id、Title、Description..)、2.Category(它包含 categoryId 和 categoryName)和 3. TaskCategory(包含 Id (taskId) 和 categoryId)。

除了使用下拉菜单向任务添加多个类别外,我设法完成了所有我想做的事情。我创建了下拉列表并加载了类别,并且我知道如何将一个类别添加到任务中(当关系为 1:N 时)(asp-for="CategoryId")。对于多项选择,我尝试使用 selectedCategories (list od integers - ids) 而不是 CategoryId 但我不知道如何处理该列表。将任务保存在控制器中时如何在TaskCategory中加入类别和任务(换句话说:如何将类别保存到任务中)?

AddTask.cshtml

<div class="form-group">
    <label class="control-label">Category</label>
    <select class="select-picker" asp-for="selectedCategories"
        asp-items="@(new SelectList(Model.Categories, "CategoryId", "CategoryName"))" multiple>
    </select>
</div>
<script>
    ...
     $('.select-picker').selectpicker('toggle');
</script>

HomeController.cs

public IActionResult AddTask()
{
    var categories = _categoryRepository.GetAllCategories().OrderBy(c => c.CategoryName);
    var taskCategories = _taskCategoryRepository.GetAllTaskCategories().OrderBy(tc => tc.Id);

    var homeViewModel = new HomeViewModel()
    {
        Task = null,
        TaskCategory = null,
        Categories = categories.ToList(),
        TaskCategories = taskCategories.ToList(),
        selectedCategories = new List<int>()
    };

    return View(homeViewModel);
}

[HttpPost]
public IActionResult AddTask(Task task, List<int> selected)
{
    // foreach (var selectedCategoryId in selected)
    // {
    //
    // }

    _taskRepository.AddTask(task);
    return RedirectToAction("Index");

    return View();
}

这样我可以在数据库中获取任务,但当然没有保存任何类别。

【问题讨论】:

    标签: c# asp.net entity-framework asp.net-core razor-pages


    【解决方案1】:

    尝试使用ViewModel来处理关系,以下是我做的工作demo,大家可以参考并根据需要进行修改

    Task 和 Category 之间的多对多关系:

    public class Task
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public List<TaskCategory> TaskCategories { get; set; }
    }
    public class Category
    {
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
        public List<TaskCategory> TaskCategories { get; set; }
    }
    public class TaskCategory
    {
        public int CategoryId { get; set; }
        public Category Category { get; set; }
    
        public int TaskId { get; set; }
        public Task Task { get; set; }
    
    }
       //DbContext
        public DbSet<Task> Task { get; set; }
        public DbSet<Category> Category { get; set; }
        public DbSet<TaskCategory> TaskCategory { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<TaskCategory>()
                .HasKey(t => new { t.CategoryId, t.TaskId });
    
            modelBuilder.Entity<TaskCategory>()
                .HasOne(pt => pt.Category)
                .WithMany(p => p.TaskCategories)
                .HasForeignKey(pt => pt.CategoryId);
    
            modelBuilder.Entity<TaskCategory>()
                .HasOne(pt => pt.Task)
                .WithMany(t => t.TaskCategories)
                .HasForeignKey(pt => pt.TaskId);
        }
    

    创建一个 TaskViewModel ,一个元素回发一个包含其选定选项值的数组(在您的情况下,它将是一个类别 Id 值的数组)。你的模型需要一个属性来绑定。添加以下属性:

    public class TaskViewModel
    { 
        public Task Task { get; set; }
        public SelectList CategoryList { get; set; }
        public List<int> selectedCategories { get; set; }
    }
    

    AddTask.cshtml:

    @model WebApplication1.Models.Tasks.TaskViewModel
    <div class="row">
      <div class="col-md-4">
        <form asp-action="AddTask">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Task.Title" class="control-label"></label>
                <input asp-for="Task.Title" class="form-control" />
                <span asp-validation-for="Task.Title" class="text-danger"></span>
            </div>
    
            <div class="form-group">
                <label asp-for="selectedCategories" class="control-label"></label>
                <select asp-for="selectedCategories" class="form-control" asp-items="Model.CategoryList" multiple></select>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
      </div>
    </div>
    

    然后在 Post 方法中,selectedCategories 的值将包含您在视图中选择的 CategoryId 值的数组。

    [HttpPost]
        public IActionResult AddTask(TaskViewModel taskVM)
        {
            Models.Tasks.Task task = taskVM.Task;
            _context.Add(task);
            _context.SaveChanges();
    
            foreach(var selectedId in taskVM.selectedCategories)
            {
                _context.TaskCategory.Add(new TaskCategory
                {
                    TaskId = task.Id,
                    CategoryId = selectedId,
                });
            }
            _context.SaveChanges();
    
            return RedirectToAction("Index");
    
        }
    

    【讨论】:

    • 非常感谢!我在 post 方法中遗漏了这个中间部分,并且不知道如何在添加新任务时在 Taskcategory 中添加新行,所以我将您的代码与我的代码结合起来,它现在可以完美运行
    猜你喜欢
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多