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

无法使用TempData展示删除产品时的外键约束冲突错误

问题:删除关联表产品时错误提示无法显示

我尝试删除数据库中关联多张表的产品,删除失败时要展示错误提示,但错误信息始终无法正常显示。相关代码如下:

控制器DeleteConfirmed方法代码

[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
    if (_context.Products == null)
    {
        return Problem("Entity set 'ShoeContext.Products'  is null.");
    }
    var product = await _context.Products.FindAsync(id);
    if (product != null)
    {
        _context.Products.Remove(product);
        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateException ex)
        {
            if (ex.InnerException?.InnerException is SqlException sqlEx)
            {
                TempData["ErrorMessage"] = "Cant't Delete This Product";
                return RedirectToAction("Index"); 
            }
            throw;
        }
        return RedirectToAction("Index");
    }

    return RedirectToAction(nameof(Index));
}

Index.cshtml页面代码

@if (TempData["ErrorMessage"] != null)
{
    <div class="alert alert-danger">
        @TempData["ErrorMessage"]
    </div>
}

Program.cs中Session配置代码

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;// Set the session timeout as needed
    options.Cookie.IsEssential = true;
});

可能的问题及修复方案

1. 异常捕获逻辑太局限

你只捕获了内层为SqlException的情况,但实际删除关联数据失败时,可能异常层级不符合,或者数据库抛出的异常类型不匹配,导致没进入设置TempData的分支。

修复方式:
扩大捕获范围,或者针对数据库外键约束的特定错误编号判断(比如SQL Server的外键约束错误编号是547):

catch (DbUpdateException ex)
{
    // 针对SQL Server外键约束错误精准判断
    if (ex.InnerException?.InnerException is SqlException sqlEx && sqlEx.Number == 547)
    {
        TempData["ErrorMessage"] = "无法删除该产品,它关联了其他数据";
    }
    else
    {
        TempData["ErrorMessage"] = "删除产品时发生错误";
    }
    return RedirectToAction("Index");
    // 不要抛出异常,否则会中断跳转,错误信息无法传递
}

2. Session中间件顺序错误

虽然配置了AddSession,但如果中间件管道中UseSession()的位置不对,会导致TempData无法正常工作。

修复方式:
确保app.UseSession()放在app.UseRouting()之后,app.UseAuthorization()之前,同时要确保添加了AddControllersWithViews()服务:

var builder = WebApplication.CreateBuilder(args);

// 必须添加这个服务,TempData依赖MVC/Razor Pages服务
builder.Services.AddControllersWithViews();
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

var app = builder.Build();

// 中间件顺序必须正确
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
// 关键:UseSession要在这里
app.UseSession();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

3. TempData读取后被清空

TempData默认是单次读取后就会被标记为删除,如果页面中有其他代码提前读取了TempData["ErrorMessage"],会导致页面上无法获取到值。

修复方式:
如果需要保留TempData的值,可以使用Peek()方法先判断,再读取:

@if (TempData.Peek("ErrorMessage") != null)
{
    <div class="alert alert-danger">
        @TempData["ErrorMessage"]
    </div>
}

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 13:18:18