Как сохранить данные из выпадающего списка - PullRequest
0 голосов
/ 04 июня 2019

Я начал изучать структуру сущностей и asp.net и хотел использовать все операции CRUD.У меня есть модели задач и категорий, и они находятся во многих отношениях.В моей базе данных есть 3 таблицы: 1. Task (содержит Id, Title, Description ..), 2. Category (содержит categoryId и categoryName) и 3. TaskCategory (содержит Id (taskId) и categoryId).

Мне удалось сделать все, что я хотел, кроме добавления нескольких категорий в задачу, используя выпадающий список.Я создал выпадающий список и загрузил категории, и я знаю, как добавить одну категорию в задачу (когда отношение равно 1: N) (asp-for="CategoryId").Для множественного выбора я попытался использовать selectedCategories (список целых чисел - идентификаторов) вместо 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();
}

Таким образом я получаю Задачу в базе данных, но, конечно, без какой-либо сохраненной категории.

1 Ответ

0 голосов
/ 05 июня 2019

Попробуйте использовать 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");

    }
...