ASP.Net Core控制器中基于URL字段的编辑/删除操作实现问题
嘿,你的思路完全没问题!用唯一的标题字段做用户友好型URL确实对SEO很有帮助——搜索引擎更喜欢包含内容关键词、易读的URL,用户也更容易记住和分享,这个方向完全正确👍
下面是具体实现Edit/Delete操作的方案,一步步来:
实现Edit/Delete操作的具体步骤
1. 配置支持标题参数的路由
首先要让你的应用识别Title(或者后面提到的Slug)作为路由参数,替代默认的Id。以.NET 6+为例,在Program.cs里添加自定义路由:
// 优先匹配课程的友好URL路由 app.MapControllerRoute( name: "CourseFriendlyUrl", pattern: "courses/{title}/{action}", defaults: new { controller = "Courses", action = "Details" } ); // 保留默认路由作为 fallback app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}" );
2. 编写Controller中的Edit/Delete方法
因为你的Title是唯一键,所以可以直接通过它查询课程实体。这里给出完整的核心方法示例:
public class CoursesController : Controller { private readonly YourDbContext _context; public CoursesController(YourDbContext context) { _context = context; } // GET: Courses/Edit/your-course-title public async Task<IActionResult> Edit(string title) { if (string.IsNullOrEmpty(title) || _context.Courses == null) { return NotFound(); } var course = await _context.Courses.FirstOrDefaultAsync(m => m.Title == title); if (course == null) { return NotFound(); } return View(course); } // POST: Courses/Edit/your-course-title [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(string title, [Bind("Id,Title,Description,OtherProperties")] Course course) { // 处理标题修改的情况:如果用户改了标题,要确保新标题唯一 if (title != course.Title) { var existingCourse = await _context.Courses.FirstOrDefaultAsync(m => m.Title == course.Title); if (existingCourse != null && existingCourse.Id != course.Id) { ModelState.AddModelError("Title", "这个课程标题已经存在"); return View(course); } } if (ModelState.IsValid) { try { _context.Update(course); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!CourseExists(course.Id)) { return NotFound(); } else { throw; } } // 修改完成后重定向到新标题对应的详情页 return RedirectToAction(nameof(Details), new { title = course.Title }); } return View(course); } // GET: Courses/Delete/your-course-title public async Task<IActionResult> Delete(string title) { if (string.IsNullOrEmpty(title) || _context.Courses == null) { return NotFound(); } var course = await _context.Courses.FirstOrDefaultAsync(m => m.Title == title); if (course == null) { return NotFound(); } return View(course); } // POST: Courses/Delete/your-course-title [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteConfirmed(string title) { if (_context.Courses == null) { return Problem("实体集 'YourDbContext.Courses' 为空。"); } var course = await _context.Courses.FirstOrDefaultAsync(m => m.Title == title); if (course != null) { _context.Courses.Remove(course); } await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } private bool CourseExists(int id) { return (_context.Courses?.Any(e => e.Id == id)).GetValueOrDefault(); } }
3. 在视图中生成Edit/Delete链接
不管是课程列表页还是详情页,生成操作链接时要传递Title参数,而不是Id:
<!-- 列表页(Index.cshtml)示例 --> @foreach (var item in Model) { <tr> <td>@Html.DisplayFor(modelItem => item.Title)</td> <td> <a asp-action="Edit" asp-route-title="@item.Title">编辑</a> | <a asp-action="Details" asp-route-title="@item.Title">详情</a> | <a asp-action="Delete" asp-route-title="@item.Title">删除</a> </td> </tr> }
4. 优化建议:用Slug替代原Title做路由参数
如果课程标题包含空格、特殊字符(比如&、?、/),直接作为URL会出现解析问题。建议新增一个Slug字段(URL友好的唯一标识,比如把"ASP.NET Core入门"转成"asp-net-core-ru-men"),用它来做路由参数,SEO效果一样好,还更安全。
修改Course模型:
public partial class Course { public int Id { get; set; } public string Title { get; set; } public string Slug { get; set; } // URL友好的唯一键 // 其他字段... }
然后在保存课程时自动生成Slug(可以用EF的实体生命周期钩子,或者在Controller里处理):
private string GenerateSlug(string title) { // 转小写、替换空格为-、移除特殊字符 var slug = title.ToLowerInvariant() .Replace(" ", "-") .Replace("[^a-z0-9-]", "") .Trim('-'); // 处理重复Slug,加后缀区分 var originalSlug = slug; int counter = 1; while (_context.Courses.Any(c => c.Slug == slug)) { slug = $"{originalSlug}-{counter}"; counter++; } return slug; }
内容的提问来源于stack exchange,提问作者Praveen Rai
相关产品推荐
相关产品推荐

