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

ASP.NET Web应用表单提交验证失败时跳转空白页问题排查

ASP.NET Web应用表单验证问题排查

我的ASP.NET Web应用中,提交表单时输入信息正确的话,TimeCard可以正常更新;取消表单能正常返回且无变更。系统已设置验证规则确保时间和Comment字段不为空,但当Comment字段留空时,页面会跳转到空白页。该功能此前正常,近期整理代码后出现此问题,排查Git提交记录未发现相关代码变更。

TimeCard实体

public class TimeCard
{
    // 由数据库设置
    public int Id { get; set; }

    public DateTime ClockIn { get; set; } = DateTime.Today;

    public DateTime ClockOut { get; set; } = DateTime.MinValue;

    public bool IsIn { get; set; }
    public bool Sickness { get; set; }
    public bool Holiday { get; set; }

   // 用于批量添加多天假期
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [DataType(DataType.Date)]
    public DateTime HolidayStartDate { get; set; }

    
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [DataType(DataType.Date)]
    public DateTime HolidayEndDate { get; set; }

    // 并非始终必填,仅在创建和编辑工时卡时需要
    [StringLength(100, MinimumLength = 5)]
    public string Comment { get; set; }

    // 工时卡属于用户(员工)
    public int UserId { get; set; } // 外键
    public User User { get; set; } // 导航属性
}

编辑视图页面

@model TimeCard

<h3 class="Form-heading">编辑工时卡</h3>

<form asp-action="EditTimeCard" method="post" onsubmit="combineDateTime()">
    <input type="hidden" asp-for="Id" />

    <!-- 用于存储合并后DateTime值的隐藏字段 -->
    <input type="hidden" id="ClockIn" asp-for="ClockIn" />
    <input type="hidden" id="ClockOut" asp-for="ClockOut" />

    <div class="row">
        <div class="col-md-6">
            <div class="form-group edit-form">
                <label class="form-label"><i class="bi bi-calendar-plus-fill"></i>日期</label>
                <input type="date" id="ClockInDate" class="form-control" />
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group edit-form">
                <label class="form-label"><i class="bi bi-alarm-fill"></i>上班时间</label>
                <input type="time" id="ClockInTime" class="form-control" />
            </div>
            <div class="form-group edit-form">
                <label class="form-label"><i class="bi bi-alarm-fill"></i>下班时间</label>
                <input type="time" id="ClockOutTime" class="form-control" />
            </div>
        </div>
    </div>

    <div class="form-group edit-form">
        <label asp-for="Comment" class="form-label">备注</label>
        <input type="text" asp-for="Comment" class="form-control" />
        <span asp-validation-for="Comment" class="text-danger"></span>
    </div>

    <button type="submit" class="btn1">编辑工时卡</button>
    <a class="cancel-btn" asp-controller="User" asp-action="TimeCardLog" asp-route-id="@Model.User.Id">取消</a>
</form>

<script>
    document.addEventListener("DOMContentLoaded", function () {
        var clockIn = new Date('@Model.ClockIn.ToString("o")');
        var clockOut = new Date('@Model.ClockOut.ToString("o")');

        document.getElementById('ClockInDate').value = clockIn.toISOString().split('T')[0];
        document.getElementById('ClockInTime').value = clockIn.toTimeString().split(' ')[0].substring(0, 5);
        document.getElementById('ClockOutTime').value = clockOut.toTimeString().split(' ')[0].substring(0, 5);
    });

    function combineDateTime() {
        var clockInDate = document.getElementById('ClockInDate').value;
        var clockInTime = document.getElementById('ClockInTime').value;
        var clockOutTime = document.getElementById('ClockOutTime').value;

        var clockInDateTime = clockInDate + 'T' + clockInTime;
        document.getElementById('ClockIn').value = clockInDateTime;

        var clockOutDateTime = clockInDate + 'T' + clockOutTime;
        document.getElementById('ClockOut').value = clockOutDateTime;
    }
</script>

编辑功能控制器

// GET: /User/EditTimeCard/{id}
[Authorize(Roles = "manager, admin")]
public IActionResult EditTimeCard(int id)
{
    var timeCard = _tcSvc.GetTimeCard(id);

    if (timeCard == null)
    {
        Alert($"未找到工时卡", AlertType.warning);
        return RedirectToAction("TimeCardLog", new { id = timeCard.UserId });
    }

    return View(timeCard);
}

// POST: /User/EditTimeCard/{id}
[HttpPost]
public IActionResult EditTimeCard(int id, TimeCard model)
{
    if (string.IsNullOrWhiteSpace(model.Comment))
    {
        ModelState.AddModelError("Comment", "备注不能为空,请输入编辑原因");
    }

    if (ModelState.IsValid)
    {
        var updatedTimeCard = _tcSvc.UpdateTimeCard(id, model.ClockIn, model.ClockOut, model.Comment);

        if (updatedTimeCard != null)
        {
            Alert("工时卡更新成功", AlertType.success);
            return RedirectToAction("TimeCardLog", new { id = updatedTimeCard.UserId });
        }
        else
        {
            Alert("工时卡无法更新", AlertType.warning);
        }
    }

    return View(model);
}

已尝试的操作

已添加以下验证脚本,但问题仍未解决。添加TimeCard的表单验证功能正常。

@section Scripts {
    @{
        await Html.RenderPartialAsync("_ValidationScriptsPartial");
    }
}

排查思路

  • 检查视图数据完整性:当Comment为空导致ModelState无效时,返回View(model)需确认model.User是否为null。视图中使用了@Model.User.Id,若User导航属性未被正确填充,会抛出空引用异常导致页面空白。可在POST方法返回视图前,手动从服务获取包含User信息的完整TimeCard数据再传递给视图。
  • 前端提交流程验证:检查combineDateTime函数是否拦截了表单默认验证。可修改为onsubmit="return combineDateTime();"并在函数末尾添加return true;,确保前端验证能正常触发。
  • 客户端验证有效性:打开浏览器开发者工具,确认Comment为空时是否触发前端验证拦截提交。若未触发,检查_ValidationScriptsPartial是否包含正确的jQuery Validation和Unobtrusive Validation脚本,且页面是否正确加载这些脚本。
  • 后端异常捕获:在POST方法中添加try-catch块,排查是否有未处理的异常。例如model.User为空时,渲染@Model.User.Id会抛出异常,可在返回视图前设置model.User = _userSvc.GetUser(model.UserId);确保User属性不为空。
  • 布局页脚本渲染检查:确认布局页中是否正确包含@RenderSection("Scripts", required: false),若Scripts区块未被正确渲染,验证脚本无法加载会导致前端验证失效,进而引发后端返回视图时的空白问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:08:08