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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 21:27:01