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

.NET 6 ASP.NET Core自定义ModelError后asp-validation不显示

问题现象

.NET 6 ASP.NET Core项目中,POST接口校验失败后通过TempData传递错误标识,重定向到GET动作后手动添加ModelState自定义错误,无论使用asp-validation-summary标签还是@Html.ValidationMessage("CustomError")都无法渲染错误提示,同项目其他页面的自定义ModelState错误可正常生效。

相关核心代码片段:

  • 添加自定义模型错误代码:
ModelState.AddModelError("CustomError", "Sorry, it looks like the submission did not go through.");
  • 原验证错误渲染代码:
<div asp-validation-summary="All" class="text-danger border m-3"></div>
业务流程
  1. POST接口birdData校验传入的鸟类环码不存在时,通过TempData存储错误标识后重定向到ShowBirdLocations动作
  2. ShowBirdLocations GET动作读取TempData中的错误标识,匹配后添加自定义ModelState错误并返回视图
  3. 当前视图已注释asp-validation-summary代码,尝试使用@Html.ValidationMessage("CustomError")单独渲染自定义错误,仍无法显示提示
根因分析

核心问题是接口调用方式和后端返回逻辑不匹配:

  • 页面上的提交按钮是通过前端fetch发异步请求调用birdData接口,不是传统表单同步提交
  • 异步请求场景下,后端返回的RedirectToAction不会触发浏览器页面跳转:fetch内核会自动跟随重定向请求GET接口,最终拿到重定向后的完整页面HTML,但前端代码写死了return response.json(),会直接尝试把HTML解析为JSON并抛出脚本错误,既不会替换当前页面内容,也不会触发任何提示
  • 用户始终停留在首次加载的ShowBirdLocations页面,首次GET请求时TempData中没有错误标识,自然不会添加ModelState错误,提示永远无法显示
修复方案

二选一即可:

方案1:适配异步交互逻辑,接口返回JSON错误

废弃TempData+重定向的逻辑,接口直接返回结构化错误,前端负责渲染提示:

  1. 修改POST接口错误分支,直接返回400错误JSON
if (check == false)
{
    return BadRequest(new { error = "Sorry, it looks like the submission did not go through." });
}
  1. 视图中增加固定的错误提示容器
<div id="errorTip" class="text-danger border m-3 d-none"></div>
  1. 修改前端fetch逻辑,增加错误捕获分支
async function postData(url = '', data = {}) {
    const response = await fetch(url, {
        method: 'post',
        headers: {
            'Content-Type': 'application/json',
            'data': JSON.stringify(data)
        }
    });
    if (!response.ok) {
        const errRes = await response.json();
        throw new Error(errRes.error);
    }
    return response.json();
}

fetchButton.addEventListener("click", function () {
    const errorTip = document.getElementById("errorTip");
    // 每次请求前清空旧错误
    errorTip.classList.add("d-none");
    errorTip.textContent = "";

    postData(url, { ringCode: fetchInput.value })
        .then(data => {
            // 原有成功逻辑保持不变
            for (let i = 0; i < data.birdData.length; i++) {
                if (data.birdData[i].gridRef != null) {
                    data.birdData[i].latitude = getLat(data.birdData[i].gridRef);
                    data.birdData[i].longitude = getLng(data.birdData[i].gridRef);
                }
            }
            var url1 = "/results/generateSearchResult";
            var asd = url1 + "?test=" + JSON.stringify(data);
            window.location = asd;
        })
        .catch(err => {
            // 显示接口返回的错误
            errorTip.textContent = err.message;
            errorTip.classList.remove("d-none");
        })
});

方案2:改回传统表单同步提交

如果不想写前端错误处理逻辑,去掉fetch异步提交代码,将输入框、按钮包裹在form标签内,设置form的action为birdData、method为post,走传统MVC表单提交流程。
这种方案下需要给TempData加保留标记,避免跨请求读取后被自动清除:

public IActionResult ShowBirdLocations()
{
    var err = TempData["WrongRingCodeErrorMessage"] as String;
    if(err == "Error message")
    {
        TempData.Keep("WrongRingCodeErrorMessage");
        ModelState.AddModelError("CustomError", "Sorry, it looks like the submission did not go through.");
    }
    return View();
}

改完后无论是asp-validation-summary还是单独的@Html.ValidationMessage("CustomError")都能正常渲染错误。

额外优化建议

当前代码把请求参数放在自定义data请求头中传递,不符合常规接口传参规范,建议后续调整为从请求Body读取参数,避免遇到请求头长度限制、网关拦截等兼容问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 00:01:20