我正在尝试使用 Entity Framework Core Database First 为用户和项目之间的多对多关系做一个控制器。我使用脚手架从数据库创建模型。/ create/Add 正在运行,但 CRUD 的其余部分不起作用( Edit, details )。我怎样才能做到这一点?我做错了什么?
当我点击编辑或获取详细信息时出现此错误 错误: 找不到此页面
创建用户项目表
CREATE TABLE [user_poject] (
[user_id] INT ,
[project_id] INT ,
[user_roles] nvarchar(225)
CONSTRAINT [user_project_PK] PRIMARY KEY ([user_id], [project_id]),
CONSTRAINT fk_userProject_user
FOREIGN KEY([user_id]) REFERENCES [user]([user_id]) ON DELETE CASCADE,
CONSTRAINT fk_userProject_project
FOREIGN KEY([project_id]) REFERENCES [project]([project_id]) ON DELETE CASCADE
);
控制器:
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var userPoject = await _context.UserPojects
.Include(u => u.Project)
.Include(u => u.User)
.FirstOrDefaultAsync(m => m.UserId == id);
if (userPoject == null)
{
return NotFound();
}
return View(userPoject);
}
// GET: UserPojects1/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var userPoject = await _context.UserPojects.FindAsync(id);
if (userPoject == null)
{
return NotFound();
}
ViewData["ProjectId"] = new SelectList(_context.Projects, "ProjectId", "ProjectName", userPoject.ProjectId);
ViewData["UserId"] = new SelectList(_context.Users, "UserId", "UserName", userPoject.UserId);
return View(userPoject);
}
// POST: UserPojects1/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("UserId,ProjectId,UserRoles")] UserPoject userPoject)
{
if (id != userPoject.UserId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(userPoject);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!UserPojectExists(userPoject.UserId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["ProjectId"] = new SelectList(_context.Projects, "ProjectId", "ProjectName", userPoject.ProjectId);
ViewData["UserId"] = new SelectList(_context.Users, "UserId", "UserName", userPoject.UserId);
return View(userPoject);
}
用户项目模型:
public partial class UserPoject
{
[Key]
[Column("user_id" , Order =1)]
public int UserId { get; set; }
[Key]
[Column("project_id" , Order =2)]
public int ProjectId { get; set; }
[Column("user_roles")]
[StringLength(225)]
public string UserRoles { get; set; }
[ForeignKey(nameof(ProjectId))]
[InverseProperty("UserPojects")]
public virtual Project Project { get; set; }
[ForeignKey(nameof(UserId))]
[InverseProperty("UserPojects")]
public virtual User User { get; set; }
}
用户模型:
public partial class User
{
public User()
{
Tasks = new HashSet<Task>();
UserPojects = new HashSet<UserPoject>();
UserSprints = new HashSet<UserSprint>();
}
[Key]
[Column("user_id")]
public int UserId { get; set; }
[Required]
[Column("user_name")]
[StringLength(50)]
public string UserName { get; set; }
[Column("user_email")]
[StringLength(225)]
public string UserEmail { get; set; }
[InverseProperty(nameof(Task.User))]
public virtual ICollection<Task> Tasks { get; set; }
[InverseProperty(nameof(UserPoject.User))]
public virtual ICollection<UserPoject> UserPojects { get; set; }
[InverseProperty(nameof(UserSprint.User))]
public virtual ICollection<UserSprint> UserSprints { get; set; }
}
项目模型
public partial class Project
{
public Project()
{
Sprints = new HashSet<Sprint>();
UserPojects = new HashSet<UserPoject>();
}
[Key]
[Column("project_id")]
public int ProjectId { get; set; }
[Column("project_name")]
[StringLength(50)]
public string ProjectName { get; set; }
[Column("Project_description")]
[StringLength(225)]
public string ProjectDescription { get; set; }
[InverseProperty(nameof(Sprint.Project))]
public virtual ICollection<Sprint> Sprints { get; set; }
[InverseProperty(nameof(UserPoject.Project))]
public virtual ICollection<UserPoject> UserPojects { get; set; }
}
DBContext-Fluent API
modelBuilder.Entity<UserPoject>(entity =>
{
entity.HasKey(e => new { e.UserId, e.ProjectId })
.HasName("PK__user_poj__5279AEEECFA4D53D");
entity.HasOne(d => d.Project)
.WithMany(p => p.UserPojects)
.HasForeignKey(d => d.ProjectId)
.HasConstraintName("FK__user_poje__proje__33D4B598");
entity.HasOne(d => d.User)
.WithMany(p => p.UserPojects)
.HasForeignKey(d => d.UserId)
.HasConstraintName("FK__user_poje__user___32E0915F");
});
答案 0 :(得分:0)
我看到了一些事情,首先您需要使用“PUT”而不是“POST”来进行更新操作。缓存策略将允许折叠冗余条目。此外,在没有 POST 的情况下,还有 PUT 的排序规则。客户端以任何顺序发送 POST 操作并获得相同的结果应该是安全的。
但是对于原始问题,您将要告诉上下文您已经修改了实体。
// PUT: api/TodoItems/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
如果这仍然给您带来问题,请同时删除显式绑定,您可以使用属性适当地装饰模型类。
答案 1 :(得分:0)
当我单击编辑或获取详细信息时,此错误出现错误: 找不到此页面
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var userPoject = await _context.UserPojects
.Include(u => u.Project)
.Include(u => u.User)
.FirstOrDefaultAsync(m => m.UserId == id);
if (userPoject == null)
{
return NotFound();
}
return View(userPoject);
}
正如我们之前讨论的,通过使用上面的代码,如果id为空,它将返回NotFound页面。因此,该问题与索引页面上的编辑和详细信息超链接有关。请参考以下代码(在ActionLink方法中,使用主键添加id参数):
@model IEnumerable<netcore5.Models.UserPoject>
<table class="table">
<thead>
@*header*@
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.UserId)
</td>
<td>
@Html.DisplayFor(modelItem => item.ProjectId)
</td>
<td>
@Html.DisplayFor(modelItem => item.UserRoles)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.UserId }) |
@Html.ActionLink("Details", "Details", new { id=item.UserId }) |
@Html.ActionLink("Delete", "Delete", new { id=item.UserId })
</td>
</tr>
}
</tbody>
</table>
此外,在 Startup.Configure 方法中,如果您使用的是默认的 MVC 路由模板,如下所示:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
然后,您还可以使用以下 Anchor Tag Helper 添加带有 id 参数的链接:
<td>
<a asp-action="Edit" asp-route-id="@item.UserId">Edit</a> |
<a asp-action="Details" asp-route-id="@item.UserId">Details</a> |
<a asp-action="Delete" asp-route-id="@item.UserId">Delete</a>
</td>
结果是这样的:
参考:
Anchor Tag Helper in ASP.NET Core
Tutorial: Implement CRUD Functionality - ASP.NET MVC with EF Core