如何从多选下拉菜单中保存数据

时间:2019-06-04 18:21:43

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

我开始学习实体框架和asp.net,我想使用所有CRUD操作。 我有任务和类别模型,它们之间存在多对多关系。在我的数据库中,有3个表:1. 任务(包含ID,标题,描述..),2. 类别(包含categoryId和categoryName)和3。 TaskCategory (包含ID(任务ID)和类别ID)。

我设法完成了我想做的所有事情,只是使用下拉菜单为任务添加了多个类别。我创建了下拉列表,并加载了类别,并且我知道如何向任务中添加一个类别(关系为1:N时)(asp-for="CategoryId"。对于多重选择,我尝试使用selectedCategories(列出od整数-id)而不是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();
}

通过这种方式,我可以在数据库中获取Task,但是当然不保存任何类别。

1 个答案:

答案 0 :(得分:0)

尝试使用ViewModel处理关系,以下是我制作的工作演示,您可以根据需要参考并进行修改

任务与类别之间的多对多关系:

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");

    }