ASP.NET MVC中TempData无法显示提示及编辑数据问题
ASP.NET MVC项目中的两个核心问题
问题描述
- 分类创建成功后toastr仅显示进度动画,无提示消息:在Index.cshtml中直接使用
TempData["success"]/TempData["error"]能正常显示提示,但将提示逻辑封装到_Layout.cshtml引用的_Notification局部视图后,仅显示动画,无消息内容。 - 编辑按钮点击后,模态框无法加载分类数据:点击编辑按钮时,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> 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转义问题,导致消息无法正常显示
修复步骤
- 统一脚本引用:将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>
- 简化_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方式,优化用户体验)
- 修改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); }
- 修改编辑按钮,添加点击事件获取数据:
在Index.cshtml中,给编辑按钮添加class="edit-category-btn",并移除href和data-bs-target:
<a data-id="@category.Id" class="btn btn-secondary edit-category-btn">Edit</a>
- 添加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>
- 保留原创建逻辑:将添加按钮的
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> 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
相关产品推荐
相关产品推荐

