You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:21:22