在 ASP.NET Core MVC 中为多对多关系表创建数据

问题描述 投票:0回答:2

我正在使用多对多关系为我的网站帖子创建标签。我按照

Microsoft 文档
,设法使用实体框架创建了 PostTags 数据库表。

我现在想在创建帖子时使用 Controller 和 ViewModel 在数据库中插入标签数据,但不知道如何继续。

GitHub 存储库

我的代码和我尝试过的-

Models

public class PostModel
{
    [Key]
    public int Id { get; set; }
    public string? Title { get; set; }

    public List<TagModel> Tags { get; set; }
    public List<PostTagModel> PostTags { get; set; }
}


public class TagModel
{
    [Key]
    public int Id { get; set; }
    public string? Title { get; set; }

    public List<PostModel> Posts { get; set; }
    public List<PostTagModel> PostTags { get; set; }
}


public class PostTagModel
{
    public int PostId { get; set; }
    public int TagId { get; set; }

    public PostModel Post { get; set; }
    public TagModel Tag { get; set; }
}

DatabaseContext.cs

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

    }

    public DbSet<PostModel> Posts { get; set; }
    public DbSet<TagModel> Tags { get; set; }


    public DbSet<PostTagModel> PostTags { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<PostModel>()
            .HasMany(e => e.Tags)
            .WithMany(e => e.Posts)
            .UsingEntity<PostTagModel>();
    }
}

ViewModel

public class CreatePostViewModel
{
    public string? Title { get; set; }
    public int? TagId { get; set; }

    public List<TagModel> TagList { get; set; }
}

Controller

CS0029: 无法隐式转换类型“int”?到'System.Collections.GenericList

[HttpGet]
public IActionResult Create()
{
    // Tags initialization for view    

    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(CreatePostViewModel postVM)
{
    if (ModelState.IsValid)
    {
        var post = new PostModel
        {
            Title = postVM.Title,
            Tags = postVM.TagId  // CS0029 : cannot implicitly convert type 'int?' to 'System.Collections.GenericList<Website.Model.TagModel>
        };

        _postInterface.Add(post);

        return RedirectToAction("Index");
    }
    else
    {
        // Error
    }
    return View(postVM);
}

View

@using SimpleWebsite.ViewModels.PostViewModel

@model CreatePostViewModel

<!-- Code above -->


<!-- Tag -->
<div class="col-md-12 mb-3">
    <label asp-for="TagId" class="control-label"></label>

    <div class="form-check-inline">
        @foreach (var item in Model.TagList)
        {
            <input type="checkbox" class="btn-check" id="@item.Id" value="@item.Id">
            <label asp-for="TagId" class="btn btn-outline-primary" for="@item.Id">@item.Title</label>
        }
    </div>

    <span asp-validation-for="TagId" class="text-danger"></span>
</div>


<!-- Code Below -->
c# asp.net-core-mvc many-to-many asp.net-mvc-viewmodel
2个回答
1
投票

我怀疑您是否可以将

TagId
值传递给控制器,因为复选框需要具有
name
属性:
name="TagId"

请注意,通过循环,用户可以检查多个复选框,并建议将

TagId
属性更改为
TagIds
类型。
int[]?

<label asp-for="TagIds" class="control-label"></label>

<div class="form-check-inline">
    @foreach (var item in Model.TagList)
    {
        <input type="checkbox" class="btn-check" id="@item.Id" value="@item.Id" name="TagIds">
        <label asp-for="TagIds" class="btn btn-outline-primary" for="@item.Id">@item.Title</label>
    }
 </div>
在控制器中,您必须从数据库中检索 
public class CreatePostViewModel { public string? Title { get; set; } public int[]? TagIds { get; set; } public List<TagModel> TagList { get; set; } }

数据并根据用户选择的

Tag
进行过滤。然后将
TagIds
post
一起插入。
selectedTags



1
投票

... using System.Linq; private readonly ITagInterface _tagInterface; public PostController(DatabaseContext context, IPostInterface postInterface, ITagInterface tagInterface) { _context = context; _postInterface = postInterface; _tagInterface = tagInterface; } [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(CreatePostViewModel postVM) { if (ModelState.IsValid) { var tags = await _tagInterface.GetAll(); List<TagModel> selectedTags = new List<TagModel>(); if (postVM.TagIds != null && postVM.TagIds.Any()) selectedTags = tags.Where(x => postVM.TagIds.Contains(x.Id)) .ToList(); var post = new PostModel { Title = postVM.Title, Tags = selectedTags }; _postInterface.Add(post); return RedirectToAction("Index"); } else { // Error } return View(postVM); }

您需要相应地更新控制器:

public class CreatePostViewModel { public string? Title { get; set; } public List<int> SelectedTagIds { get; set; } = new List<int>(); // To store multiple tag IDs public List<TagModel> TagList { get; set; } }

还有景色:

@model CreatePostViewModel <!-- Other fields --> <!-- Tag Selection --> <div class="col-md-12 mb-3"> <label asp-for="SelectedTagIds" class="control-label"></label> <div class="form-check-inline"> @foreach (var tag in Model.TagList) { <input type="checkbox" class="btn-check" name="SelectedTagIds" id="[email protected]" value="@tag.Id"> <label class="btn btn-outline-primary" for="[email protected]">@tag.Title</label> } </div> </div> <!-- Submit button and other code -->

使用Entity Framework时,更新数据库的方法如下:

打开命令行
  • 导航到您的项目所在的目录
  • 运行:
  • @model CreatePostViewModel <!-- Other fields --> <!-- Tag Selection --> <div class="col-md-12 mb-3"> <label asp-for="SelectedTagIds" class="control-label"></label> <div class="form-check-inline"> @foreach (var tag in Model.TagList) { <input type="checkbox" class="btn-check" name="SelectedTagIds" id="[email protected]" value="@tag.Id"> <label class="btn btn-outline-primary" for="[email protected]">@tag.Title</label> } </div> </div> <!-- Submit button and other code -->
完成后,运行:
  • dotnet ef migrations add UpdatePostTagRelationship //or whatever you want to call it
您可以打开笔记本电脑的命令行或在您正在使用的IDE的命令行中执行。

© www.soinside.com 2019 - 2024. All rights reserved.