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

ASP.NET MVC中TempData无法显示提示及编辑数据问题

ASP.NET MVC项目中的两个核心问题

问题描述

  1. 分类创建成功后toastr仅显示进度动画,无提示消息:在Index.cshtml中直接使用TempData["success"]/TempData["error"]能正常显示提示,但将提示逻辑封装到_Layout.cshtml引用的_Notification局部视图后,仅显示动画,无消息内容。
  2. 编辑按钮点击后,模态框无法加载分类数据:点击编辑按钮时,TempData无法保存分类ID和名称,导致编辑模态框为空。

相关代码

CategoryController(路径:POS Software\POS Software\Areas\Admin\Controllers\CategoryController)

using Microsoft.AspNetCore.Mvc;
using POS.DataAccess.Repository.IRepository;
using POS.Models;

namespace POS_Software.Areas.Admin.Controllers
{
    [Area("Admin")]
    public class CategoryController : Controller
    {
        private readonly IUnitOfWork _unitOfWork;

        public CategoryController(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        public IActionResult Index()
        {
            List<Category> objCategoryList = _unitOfWork.Category.GetAll().ToList();
            return View(objCategoryList);
        }

        // GET: Upsert action to prepare the modal for edit or creation
        [HttpGet]
        public IActionResult Upsert(Guid? id)
        {
            Category category = new Category();

            if (id.HasValue)
            {
                category = _unitOfWork.Category.Get(c => c.Id == id.Value);
                if (category == null)
                {
                    return NotFound();
                }
            }

            // Store the retrieved category or new category in TempData
            TempData["CategoryId"] = category.Id;
            TempData["CategoryName"] = category.CategoryName;

            // Redirect to Index to open the modal with the data
            return RedirectToAction("Index");
        }

        // POST: Upsert action for creation or update
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Upsert(Category category)
        {
            if (!ModelState.IsValid)
            {
                TempData["error"] = "Invalid category data. Please check the inputs.";
                return RedirectToAction("Index");
            }

            if (category.Id == Guid.Empty)
            {
                category.Id = Guid.NewGuid();
                category.CreatedAt = DateTime.Now;
                _unitOfWork.Category.Add(category);
                TempData["success"] = "Category created successfully.";
            }
            else
            {
                var existingCategory = _unitOfWork.Category.Get(c => c.Id == category.Id);

                if (existingCategory == null)
                {
                    TempData["error"] = "Category not found.";
                    return RedirectToAction("Index");
                }

                existingCategory.CategoryName = category.CategoryName;
                _unitOfWork.Category.Update(existingCategory);
                TempData["success"] = "Category updated successfully.";
            }

            _unitOfWork.Save();

            return RedirectToAction("Index");
        }
    }
}

_Notification.cshtml(路径:POS Software\POS Software\Views\Shared_Notification.cshtml)

@if (TempData["success"] != null)
{
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
    <script type="text/javascript">
        toastr.options = {
            "progressBar": true
        };
        toastr.success('@TempData["success"]');
    </script>
}

@if (TempData["error"] != null)
{
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
    <script type="text/javascript">
        toastr.options = {
            "progressBar": true
        };
        toastr.error('@TempData["error"]');
    </script>
}

_Layout.cshtml(路径:POS Software\POS Software\Views\Shared_Layout.cshtml)

<div class="container-fluid pt-4 px-4">
    <div class="row g-4">
        <partial name="_Notification" />
        @RenderBody()
    </div>
</div>

Index.cshtml(路径:POS Software\POS Software\Areas\Admin\Views\Category\Index.cshtml)

@model IEnumerable<POS.Models.Category>

<div class="container mt-4">
    <div class="card">
        <div class="card-header d-flex justify-content-between align-items-center">
            <h5 class="mb-0">Categories Data</h5>
            <a href="@Url.Action("Upsert", "Category")" class="btn btn-primary" style="box-shadow: none" data-bs-toggle="modal" data-bs-target="#categoryModal">
                <i class="fas fa-plus-circle"></i> &nbsp;Add Category
            </a>

            <!-- Modal for Create/Update Category -->
            <div class="modal fade" id="categoryModal" tabindex="-1" aria-labelledby="categoryModalLabel" aria-hidden="true">
                <div class="modal-dialog modal-dialog-centered" role="document">
                    <div class="modal-content">
                        <form asp-controller="Category" asp-action="Upsert" method="post">
                            <div class="modal-header">
                                <h5 class="modal-title" id="categoryModalLabel">
                                    @if (TempData["CategoryId"] != null)
                                    {
                                        <span>Edit Category</span>
                                    }
                                    else
                                    {
                                        <span>Add New Category</span>
                                    }
                                </h5>
                                <button type="button" style="box-shadow: none" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                            </div>
                            <div class="modal-body">
                                <!-- Hidden Field for Id -->
                                <input type="hidden" id="Id" name="Id" value="@(TempData["CategoryId"] ?? Guid.Empty.ToString())" />


                                <div class="mb-3">
                                    <label for="CategoryName" class="form-label fw-bold ms-1">Category Name</label>
                                    <input type="text" class="form-control" id="CategoryName" name="CategoryName"
                                           value="@TempData["CategoryName"]" required placeholder="Category Name" />
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Dismiss</button>
                                <button type="submit" class="btn btn-success">Save</button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>

        <!-- Success/Error Messages -->
        @* @if (TempData["success"] != null)
        {
            <div class="alert alert-success">@TempData["success"]</div>
        }

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

        <div class="card-body">
            <table class="table table-bordered">
                <thead class="thead-light">
                    <tr>
                        <th>S/N</th>
                        <th>Category Name</th>
                        <th>Created At</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    @{
                        int index = 1;
                    }

                    @foreach (var category in Model)
                    {
                        <tr>
                            <td>@index</td>
                            <td>@category.CategoryName</td>
                            <td>@category.CreatedAt.ToString("yyyy-MM-dd")</td>
                            <td>
                                <a href="@Url.Action("Upsert", "Category", new { id = category.Id })"
                                   class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#categoryModal">Edit</a>
                            </td>
                        </tr>
                        index++;
                    }
                </tbody>
            </table>
        </div>
    </div>
</div>

问题截图

  • 创建成功后仅显示进度动画无消息:创建成功仅显示进度动画
  • 点击编辑后不显示分类名称:编辑模态框无分类名称

解决方案

问题1:toastr提示无内容修复

原因分析

  • 局部视图中重复加载jQuery和toastr脚本,导致脚本冲突,toastr初始化异常
  • TempData的值被直接渲染时存在HTML转义问题,导致消息无法正常显示

修复步骤

  1. 统一脚本引用:将jQuery和toastr的脚本移到_Layout.cshtml的<head>标签内或</body>前,确保仅加载一次:
<!-- 在_Layout.cshtml的<head>中添加 -->
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
  1. 简化_Notification.cshtml:移除重复的脚本引用,使用@Html.Raw确保消息内容正确渲染:
@if (TempData["success"] != null)
{
    <script type="text/javascript">
        toastr.options = {
            "progressBar": true
        };
        toastr.success('@Html.Raw(TempData["success"])');
    </script>
}

@if (TempData["error"] != null)
{
    <script type="text/javascript">
        toastr.options = {
            "progressBar": true
        };
        toastr.error('@Html.Raw(TempData["error"])');
    </script>
}

问题2:编辑模态框无法加载数据修复

原因分析

  • TempData默认是单次读取后即失效,重定向到Index视图时,模态框渲染读取TempData后数据被清空
  • 当前通过重定向传递数据的方式不合理,页面刷新后模态框内容无法动态更新

修复方案(推荐AJAX方式,优化用户体验)

  1. 修改Upsert GET方法,返回JSON数据:
[HttpGet]
public IActionResult Upsert(Guid? id)
{
    if (!id.HasValue)
    {
        // 返回空的分类对象用于创建
        return Json(new Category());
    }

    var category = _unitOfWork.Category.Get(c => c.Id == id.Value);
    if (category == null)
    {
        return NotFound();
    }

    return Json(category);
}
  1. 修改编辑按钮,添加点击事件获取数据:
    在Index.cshtml中,给编辑按钮添加class="edit-category-btn",并移除href和data-bs-target:
<a data-id="@category.Id" class="btn btn-secondary edit-category-btn">Edit</a>
  1. 添加AJAX脚本填充模态框:
    在Index.cshtml末尾添加脚本:
<script>
    $(document).ready(function() {
        // 编辑按钮点击事件
        $('.edit-category-btn').click(function() {
            var categoryId = $(this).data('id');
            
            $.get('/Admin/Category/Upsert?id=' + categoryId, function(data) {
                // 填充模态框数据
                $('#Id').val(data.id);
                $('#CategoryName').val(data.categoryName);
                $('#categoryModalLabel').text('Edit Category');
                // 显示模态框
                $('#categoryModal').modal('show');
            });
        });

        // 添加按钮点击事件,重置模态框
        $('.btn-primary').click(function() {
            $('#Id').val('');
            $('#CategoryName').val('');
            $('#categoryModalLabel').text('Add New Category');
        });
    });
</script>
  1. 保留原创建逻辑:将添加按钮的href移除,仅保留data-bs-toggle="modal"和data-bs-target="#categoryModal":
<a class="btn btn-primary" style="box-shadow: none" data-bs-toggle="modal" data-bs-target="#categoryModal">
    <i class="fas fa-plus-circle"></i> &nbsp;Add Category
</a>

临时修复(不推荐,保留重定向方式)

如果坚持使用重定向,需在Index视图读取TempData时保留数据:

<!-- 修改模态框标题部分 -->
<h5 class="modal-title" id="categoryModalLabel">
    @{
        var categoryId = TempData.Peek("CategoryId");
        var categoryName = TempData.Peek("CategoryName");
    }
    @if (categoryId != null)
    {
        <span>Edit Category</span>
    }
    else
    {
        <span>Add New Category</span>
    }
</h5>

<!-- 修改隐藏字段和输入框 -->
<input type="hidden" id="Id" name="Id" value="@(TempData.Peek("CategoryId") ?? Guid.Empty.ToString())" />
<input type="text" class="form-control" id="CategoryName" name="CategoryName"
       value="@TempData.Peek("CategoryName")" required placeholder="Category Name" />

TempData.Peek()会读取数据但不删除,确保数据在页面渲染后依然可用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 09:44:52