ASP.NET论坛项目:提交消息无法存入数据库求助
论坛消息提交问题排查
我正在开发学校项目论坛,使用TinyMCE编辑器。点击提交按钮后页面仅刷新,消息并未存入数据库,无法在对应主题中显示。以下是相关代码,请求帮忙排查:
Message 模型
using System; using System.Collections.Generic; namespace TP1W24.Models; public partial class Message { public int MsgId { get; set; } public int SujetId { get; set; } public string? UserId { get; set; } public string MsgText { get; set; } = null!; public DateTime MsgDate { get; set; } public bool MsgActif { get; set; } public virtual Sujet Sujet { get; set; } = null!; }
Create 视图
@model TP1W24.Models.Message @{ ViewData["Title"] = "Create"; } <h1>Create</h1> <h4>Message</h4> <hr /> <div class="row"> <div class="col-md-4"> <form id="messageForm" asp-action="Create" method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <input type="hidden" asp-for="SujetId" value="@ViewContext.RouteData.Values["sujetId"]" /> <!-- Hidden field for UserId --> <input type="hidden" asp-for="UserId" /> <div class="form-group"> <label asp-for="MsgText" class="control-label"></label> <textarea asp-for="MsgText" name="MsgText" class="form-control tinymce-editor"></textarea> <span asp-validation-for="MsgText" class="text-danger"></span> </div> <!-- Hidden field for MsgDate --> <input type="hidden" asp-for="MsgDate" /> <!-- Hidden field for MsgActif --> <input type="hidden" asp-for="MsgActif" /> <div class="form-group"> <button type="submit" id="submitButton" class="btn btn-primary">Create</button> </div> </form> </div> </div> <div> <a asp-action="Index">Back to List</a> </div> @section Scripts { @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } <script src="https://cdn.tiny.cloud/1/4b6n7584wjbyriu4qezzpb9q8fb0fp8045wmik5fx83f394w/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script> <script> document.addEventListener('DOMContentLoaded', function () { tinymce.init({ selector: 'textarea.tinymce-editor', plugins: 'autolink lists link image charmap print preview', toolbar: 'undo redo | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | link image' }); document.getElementById('messageForm').addEventListener('submit', function () { var editorContent = tinymce.get('MsgText').getContent(); document.getElementById('MsgText').value = editorContent; }); }); </script> }
MessagesController 控制器
using System; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; using TP1W24.Models; namespace TP1W24.Controllers { public class MessagesController : Controller { private readonly Forum1Context _context; private readonly UserManager<IdentityUser> _userManager; private readonly ILogger<MessagesController> _logger; public MessagesController(Forum1Context context, UserManager<IdentityUser> userManager, ILogger<MessagesController> logger) { _context = context; _userManager = userManager; _logger = logger; } // GET: Messages public async Task<IActionResult> Index() { var activeMessages = await _context.Messages .Where(m => m.MsgActif) .Include(m => m.Sujet) .ToListAsync(); return View(activeMessages); } // GET: Messages/Details/5 public async Task<IActionResult> Details(int? id) { if (id == null || _context.Messages == null) { return NotFound(); } var message = await _context.Messages .Include(m => m.Sujet) .FirstOrDefaultAsync(m => m.MsgId == id); if (message == null) { return NotFound(); } return View(message); } // GET: Messages/Create public IActionResult Create(int sujetId) { // Directly create a new Message with the provided SujetId var message = new Message { SujetId = sujetId }; return View(message); } // POST: Messages/Create [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(int sujetId, [Bind("SujetId,UserId,MsgText,MsgDate,MsgActif")] Message message) { if (ModelState.IsValid) { // Set SujetId based on the provided parameter message.SujetId = sujetId; // Fetch the currently logged-in user var currentUser = await _userManager.GetUserAsync(User); if (currentUser != null) { // Set UserId using the UserName of the logged-in user message.UserId = currentUser.UserName; // Set MsgDate and MsgActif based on your logic message.MsgDate = DateTime.Now; // Set to the current date and time message.MsgActif = true; // Set based on your logic _context.Add(message); await _context.SaveChangesAsync(); // Redirect to the subject details page return RedirectToAction("Details", "Sujets", new { id = sujetId }); } else { // Handle the case where the user is not found return RedirectToAction("Login"); // Redirect to login or handle accordingly } } // Removed ViewData line, as it's not needed return View(message); } // GET: Messages/Edit/5 public async Task<IActionResult> Edit(int? id) { if (id == null || _context.Messages == null) { return NotFound(); } var message = await _context.Messages.FindAsync(id); if (message == null) { return NotFound(); } ViewData["SujetId"] = new SelectList(_context.Sujets, "SujetId", "SujetId", message.SujetId); return View(message); } // POST: Messages/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(int id, [Bind("MsgId,SujetId,UserId,MsgText,MsgDate,MsgActif")] Message message) { if (id != message.MsgId) { return NotFound(); } if (ModelState.IsValid) { try { _context.Update(message); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!MessageExists(message.MsgId)) { return NotFound(); } else { throw; } } return RedirectToAction(nameof(Index)); } ViewData["SujetId"] = new SelectList(_context.Sujets, "SujetId", "SujetId", message.SujetId); return View(message); } // GET: Messages/Delete/5 public async Task<IActionResult> Delete(int? id) { if (id == null || _context.Messages == null) { return NotFound(); } var message = await _context.Messages .Include(m => m.Sujet) .FirstOrDefaultAsync(m => m.MsgId == id); if (message == null) { return NotFound(); } return View(message); } // POST: Messages/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteConfirmed(int id) { if (_context.Messages == null) { return Problem("Entity set 'Forum1Context.Messages' is null."); } var message = await _context.Messages.FindAsync(id); if (message != null) { // Set MsgActif to false to make the message inactive message.MsgActif = false; await _context.SaveChangesAsync(); } // Redirect to the subject details page return RedirectToAction("Details", "Sujets", new { id = message.SujetId }); } private bool MessageExists(int id) { return (_context.Messages?.Any(e => e.MsgId == id)).GetValueOrDefault(); } } }
排查要点
- ModelState 验证失败:在POST方法开头添加日志代码,输出ModelState的错误信息,确认是否有字段不符合验证规则(比如MsgText为空):
_logger.LogInformation("ModelState Errors: {Errors}", string.Join("; ", ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage))); - TinyMCE 内容同步问题:修改提交事件逻辑,先阻止默认提交,确保编辑器内容同步到textarea后再提交:
document.getElementById('messageForm').addEventListener('submit', function (e) { e.preventDefault(); var editor = tinymce.get('MsgText'); if (editor) { document.getElementById('MsgText').value = editor.getContent(); } this.submit(); }); - SujetId 参数有效性:在POST方法中打印
sujetId的值,确认是否获取到了正确的路由参数,避免因参数无效导致数据无法关联主题。 - 用户登录状态:检查
currentUser是否为null,若用户未登录会跳转到Login页面,需确认登录路由配置是否正常,或是否有拦截导致跳转失效。 - 数据库保存异常:在
SaveChangesAsync()处添加try-catch块,捕获并记录异常,排查是否存在外键约束、字段长度超限等数据库层面的错误:try { _context.Add(message); await _context.SaveChangesAsync(); return RedirectToAction("Details", "Sujets", new { id = sujetId }); } catch (Exception ex) { _logger.LogError(ex, "保存消息失败"); ModelState.AddModelError("", "保存消息失败,请重试"); return View(message); } - 字段绑定问题:尝试移除
[Bind]属性,改用[FromForm]接收参数,避免因绑定字段遗漏导致数据无法正确接收。
内容的提问来源于stack exchange,提问作者le barne
相关产品推荐
相关产品推荐

