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

ASP.NET Core Razor Pages实现表单无刷新提交添加数据

问题根因

你当前代码中前两个添加临时数据的按钮均设置为type="submit",点击后会触发表单默认的整页POST回发,这是页面刷新的直接原因。另外你当前代码中WebSitelist、SocialMedialist如果是PageModel的普通实例属性,每次HTTP请求都会重新初始化PageModel,列表数据会在回发后丢失,需要同步修复。


推荐实现方案(改动最小,适配现有Razor Pages逻辑)

基于AJAX实现无刷新添加临时数据,用Session存储跨请求的临时列表,不需要推翻现有业务逻辑。

第一步:修改后端PageModel代码

首先修正临时列表的存储逻辑,把两个添加临时项的处理方法改为返回JSON格式结果,补充批量提交的入库逻辑:

using System.Text.Json;
using Microsoft.AspNetCore.Mvc;

// 临时列表从Session读取,避免每次请求重置
public List<WebSite> WebSitelist
{
    get
    {
        var listJson = HttpContext.Session.GetString("TempWebList");
        return string.IsNullOrEmpty(listJson) 
            ? new List<WebSite>() 
            : JsonSerializer.Deserialize<List<WebSite>>(listJson);
    }
}
public List<SocialMedia> SocialMedialist
{
    get
    {
        var listJson = HttpContext.Session.GetString("TempSocialList");
        return string.IsNullOrEmpty(listJson) 
            ? new List<SocialMedia>() 
            : JsonSerializer.Deserialize<List<SocialMedia>>(listJson);
    }
}

// 添加网站信息的处理方法
public JsonResult OnPostAddWebsiteInfo()
{
    var tempList = WebSitelist;
    tempList.Add(new WebSite { 
        WebSiteName = NewWebSiteInfo.WebsiteName, 
        websiteUrl = NewWebSiteInfo.websiteUrl
    });
    // 最新列表存回Session
    HttpContext.Session.SetString("TempWebList", JsonSerializer.Serialize(tempList));
    return new JsonResult(new { success = true, data = tempList });
}

// 添加社交媒体信息的处理方法
public JsonResult OnPostAddSocialMediaInfo()
{
    var tempList = SocialMedialist;
    tempList.Add(new SocialMedia { 
        SocialMediaName = NewSocialMediaInfo.SocialMediaName, 
        SocialMediaAccount = NewSocialMediaInfo.SocialMediaAccount
    });
    HttpContext.Session.SetString("TempSocialList", JsonSerializer.Serialize(tempList));
    return new JsonResult(new { success = true, data = tempList });
}

// 批量提交所有信息入库的处理方法
public IActionResult OnPostAddAllInfo()
{
    var allWebData = WebSitelist;
    var allSocialData = SocialMedialist;
    // 此处写你的数据库批量插入逻辑

    // 入库完成后清空Session临时数据
    HttpContext.Session.Remove("TempWebList");
    HttpContext.Session.Remove("TempSocialList");
    return RedirectToPage("/OperationSuccess"); // 替换为你的业务跳转页
}

*如果你的项目还没启用Session,需要在Program.cs中补充配置:

// 在注册Razor Pages服务的代码后添加
builder.Services.AddSession();

// 在app.UseRouting() 之后、app.MapRazorPages() 之前添加
app.UseSession();

第二步:修改前端页面代码

把前两个添加临时项的按钮改为普通按钮(阻止默认表单提交),给列表容器加唯一ID方便动态渲染,补充AJAX交互逻辑:

<!-- 网站信息添加按钮改为type="button" -->
<button type="button" id="addWebBtn" class="btn btn-primary">Add Website info</button>
<!-- 网站列表容器加ID -->
<div class="mb-3" id="webListWrap">
    @if (Model.WebSitelist.Count > 0)
    {
        <div class="col-12 border p-3">
            <table class="table table-striped table-bordered">
                <thead style="background-color:lightgray">
                    <tr>
                        <th>WebsiteName</th>
                        <th>websiteURL</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (WebSite item in Model.WebSitelist)
                    {
                        <tr>
                            <td>@item.WebSiteName</td>
                            <td>@item.websiteUrl</td>
                        </tr>
                    }
                </tbody>
            </table>
        </div>
    }
</div>

<!-- 社交媒体信息添加按钮改为type="button" -->
<button type="button" id="addSocialBtn" class="btn btn-primary">Add Social Media info</button>
<!-- 社交媒体列表容器加ID -->
<div class="mb-3" id="socialListWrap">
    @if (Model.SocialMedialist.Count > 0)
    {
        <div class="col-12 border p-3">
            <table class="table table-striped table-bordered">
                <thead style="background-color:lightgray">
                    <tr>
                        <th>SocialMediaName</th>
                        <th>SocialMediaAccount</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (SocialMedia item in Model.SocialMedialist)
                    {
                        <tr>
                            <td>@item.SocialMediaName</td>
                            <td>@item.SocialMediaAccount</td>
                        </tr>
                    }
                </tbody>
            </table>
        </div>
    }
</div>

<!-- 最后提交按钮保持submit类型,指定对应handler -->
<div class="col-4 offset-2">
    <button type="submit" asp-page-handler="AddAllInfo" class="btn btn-primary form-control">Add all info</button>
</div>

在页面底部的脚本区块添加JS交互逻辑,注意请求要携带Razor Pages的防伪令牌,否则会报400错误:

@section Scripts {
<script>
// 获取页面防伪令牌
const getToken = () => document.querySelector('input[name="__RequestVerificationToken"]').value;

// 渲染网站列表
const renderWebList = (list) => {
    const wrap = document.getElementById('webListWrap');
    if(!list.length) { wrap.innerHTML = ''; return; }
    let html = `<div class="col-12 border p-3"><table class="table table-striped table-bordered">
        <thead style="background-color:lightgray"><tr><th>WebsiteName</th><th>websiteURL</th></tr></thead><tbody>`;
    list.forEach(item => {
        html += `<tr><td>${item.webSiteName}</td><td>${item.websiteUrl}</td></tr>`;
    })
    html += `</tbody></table></div>`;
    wrap.innerHTML = html;
}

// 渲染社交媒体列表
const renderSocialList = (list) => {
    const wrap = document.getElementById('socialListWrap');
    if(!list.length) { wrap.innerHTML = ''; return; }
    let html = `<div class="col-12 border p-3"><table class="table table-striped table-bordered">
        <thead style="background-color:lightgray"><tr><th>SocialMediaName</th><th>SocialMediaAccount</th></tr></thead><tbody>`;
    list.forEach(item => {
        html += `<tr><td>${item.socialMediaName}</td><td>${item.socialMediaAccount}</td></tr>`;
    })
    html += `</tbody></table></div>`;
    wrap.innerHTML = html;
}

// 绑定添加网站按钮事件
document.getElementById('addWebBtn').addEventListener('click', async () => {
    const nameInput = document.querySelector('input[name="NewWebSiteInfo.websiteName"]');
    const urlInput = document.querySelector('input[name="NewWebSiteInfo.websiteUrl"]');
    if(!nameInput.value.trim() || !urlInput.value.trim()) {
        alert('请先填写完整网站信息');
        return;
    }
    const res = await fetch('?handler=AddWebsiteInfo', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'RequestVerificationToken': getToken()
        },
        body: new URLSearchParams({
            'NewWebSiteInfo.websiteName': nameInput.value.trim(),
            'NewWebSiteInfo.websiteUrl': urlInput.value.trim()
        })
    })
    const result = await res.json();
    if(result.success) {
        renderWebList(result.data);
        nameInput.value = '';
        urlInput.value = '';
    }
})

// 绑定添加社交媒体按钮事件
document.getElementById('addSocialBtn').addEventListener('click', async () => {
    const nameInput = document.querySelector('input[name="NewSocialMediaInfo.SocialMediaName"]');
    const accountInput = document.querySelector('input[name="NewSocialMediaInfo.SocialMediaAccount"]');
    if(!nameInput.value.trim() || !accountInput.value.trim()) {
        alert('请先填写完整社交媒体信息');
        return;
    }
    const res = await fetch('?handler=AddSocialMediaInfo', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'RequestVerificationToken': getToken()
        },
        body: new URLSearchParams({
            'NewSocialMediaInfo.SocialMediaName': nameInput.value.trim(),
            'NewSocialMediaInfo.SocialMediaAccount': accountInput.value.trim()
        })
    })
    const result = await res.json();
    if(result.success) {
        renderSocialList(result.data);
        nameInput.value = '';
        accountInput.value = '';
    }
})
</script>
}

可选替代方案

如果不想使用Session存储临时数据,也可以选择纯前端实现:

  • 前两个按钮同样改为type="button",用JS数组在前端内存中存储临时录入的数据,动态渲染列表
  • 点击最后提交按钮时,把前端数组的数据序列化为隐藏表单字段,和其他表单数据一起提交到后端
  • 该方案优点是不需要额外后端配置、响应速度更快,缺点是用户手动刷新页面时,已录入的临时数据会全部丢失

原有代码需要修正的问题:

  • 第三个提交按钮原来没有指定asp-page-handler,无法触发批量入库的处理逻辑
  • 存在拼写错误:按钮文字socil Media应为social Media,实体类属性名大小写不统一(websiteURL/websiteUrl混用)容易导致模型绑定失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:36:21