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

.NET MVC中Bootstrap Modal无法弹出问题求助

问题分析

你遇到的核心问题是:AJAX请求的上下文与页面重载的上下文相互独立,导致TempData无法传递到重载后的页面。具体来说:

  1. 后端在AJAX请求中设置TempData["ErrorMessage"]并返回RedirectToAction,但AJAX并未处理跳转响应,而是直接执行window.location.reload()。
  2. reload()会发起全新的HTTP请求,与之前的AJAX请求完全独立,TempData默认仅存活到下一次关联请求,因此重载后的页面无法读取到之前设置的TempData,Modal自然无法触发。
解决方案

以下是三种可行的修复方案,按推荐程度排序:

方案一:后端返回JSON结果,前端直接触发Modal(推荐)

这种方式跳过TempData,直接通过AJAX接收错误信息并显示Modal,逻辑更清晰,适配AJAX场景。

后端代码修改(ManageOrderQuote)

public async Task<IActionResult> ManageOrderQuote(int orderId, string status, string statusDescription)
{
    var order = await orderQuote.GetByIdAsync(orderId);
    var orderDetails = await orderQuoteDetail.GetAllByIdAsync(orderId);
    foreach (var detail in orderDetails)
    {
        var productId = detail.ProductId;
        var productToUpdate = await product.GetByIdAsync(productId);
        productToUpdate.UnitsOnOrder += detail.Quantity;
        productToUpdate.UnitsInStock -= detail.Quantity;
        if (productToUpdate.UnitsInStock < 0)
        {
            // 返回错误信息JSON
            return Json(new { success = false, message = $"The {productToUpdate.ProductName} product doesn't have enough stock." });
        }
        await product.UpdateAsync(productToUpdate);
    }
    order.Status = status;
    order.StatusDescription = statusDescription;
    await orderQuote.UpdateAsync(order);

    // 返回成功状态与跳转地址
    return Json(new { success = true, redirectUrl = Url.Action("PendingOrders") });
}

前端AJAX代码修改

$('#statusForm').submit(function (e) {
    e.preventDefault();
    var orderId = $('#orderId').val();
    var status = $('#status').val();
    var statusDescription = $('#statusDescription').val();
    $.ajax({
        url: '/Sales/ManageOrderQuote',
        type: 'POST',
        data: {
            orderId: orderId,
            status: status,
            statusDescription: statusDescription
        },
        success: function (result) {
            if (result.success) {
                $('#statusModal').modal('hide');
                $('.modal-backdrop').remove();
                window.location.href = result.redirectUrl;
            } else {
                // 填充错误信息并显示Modal
                $('#errorModal .modal-body p').text(result.message);
                $('#errorModal').modal('show');
                // 清理状态Modal的遮罩层
                $('#statusModal').modal('hide');
                $('.modal-backdrop').not('#errorModal + .modal-backdrop').remove();
            }
        },
        error: function () {
            alert('An error occurred while changing order status.');
        }
    });
});

方案二:让AJAX处理后端跳转响应

修改AJAX逻辑,跟随后端的RedirectToAction响应,确保TempData传递到跳转后的页面。

前端AJAX代码修改

$('#statusForm').submit(function (e) {
    e.preventDefault();
    var orderId = $('#orderId').val();
    var status = $('#status').val();
    var statusDescription = $('#statusDescription').val();
    $.ajax({
        url: '/Sales/ManageOrderQuote',
        type: 'POST',
        data: {
            orderId: orderId,
            status: status,
            statusDescription: statusDescription
        },
        // 禁用AJAX自动跟随跳转
        followRedirects: false,
        success: function (response, textStatus, xhr) {
            // 获取后端返回的跳转地址
            var redirectUrl = xhr.getResponseHeader('Location');
            if (redirectUrl) {
                // 手动跳转到目标页面,保留TempData
                window.location.href = redirectUrl;
            } else {
                $('#statusModal').modal('hide');
                $('.modal-backdrop').remove();
                window.location.reload();
            }
        },
        error: function () {
            alert('An error occurred while changing order status.');
        }
    });
});

方案三:使用Session替代TempData(应急方案)

通过Session存储错误信息,手动控制生命周期,避免TempData的单次读取限制。

后端代码修改(ManageOrderQuote)

if (productToUpdate.UnitsInStock < 0)
{
    HttpContext.Session.SetString("ErrorMessage", $"The {productToUpdate.ProductName} product doesn't have enough stock.");
    return RedirectToAction("PendingOrders");
}

前端代码修改

@if (!string.IsNullOrEmpty(HttpContext.Session.GetString("ErrorMessage")))
{
    <script>
        $(document).ready(function () {
            $('#errorModal').modal('show');
        });
    </script>
}

<!-- Error Modal -->
<div class="modal fade" id="errorModal" tabindex="-1" aria-labelledby="errorModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header bg-danger text-light">
                <h5 class="modal-title" id="errorModalLabel">Error</h5>
            </div>
            <div class="modal-body">
                <p class="text-danger">@HttpContext.Session.GetString("ErrorMessage")</p>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-danger" data-bs-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

PendingOrders动作添加Session清理

public async Task<IActionResult> PendingOrders()
{
    var orders = await orderQuote.GetAllPendingOrders();

    var orderList = new List<OrderVM>();
    foreach (var order in orders)
    {
        var orderVM = new OrderVM()
        {
            OrderQuoteId = order.OrderQuoteId,
            CustomerName = order.Customer?.ContactFirstName + " " + order.Customer?.ContactLastName,
            OrderDate = order.OrderDate,
            Status = order.Status,
            StatusDescription = order.StatusDescription
        };
        orderList.Add(orderVM);
    }
    
    // 显示后清理Session,避免重复提示
    HttpContext.Session.Remove("ErrorMessage");
    return View(orderList);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:27:17