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

第二次POST请求后类属性ServiceIds为空的问题排查

问题原因

ASP.NET Razor Pages是无状态的,每个HTTP请求都会创建全新的页面类实例。第一次AJAX请求中赋值的私有ServiceIds属性,会在请求结束后被销毁;第二次模态框表单提交的POST请求会初始化新的页面实例,因此ServiceIds自然为空。

解决方案

以下是几种可行的解决思路,按实现复杂度排序:

方案1:在模态框表单中添加隐藏字段传递ServiceIds

前端修改

点击编辑按钮的AJAX请求成功后,将选中的ServiceIds以隐藏字段形式插入模态框表单,提交时一并传递到后端:

$(btnEdit).on('click', function () {
    var checkedList = $('[type=checkbox]:checked');
    var ids = []

    for (var item of checkedList) {
        var serviceId = $(item).closest('tr').find(".serviceId").text();
        ids.push(serviceId);
    }  

    $.ajax({
        type: "POST",
        data: JSON.stringify(ids),
        headers: { "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val() },
        contentType: "application/json",
        success: function () {
            // 清空表单中已有的ServiceIds隐藏字段
            $('#editDialog form').find('input[name="ServiceIds"]').remove();
            // 为每个ServiceId添加隐藏字段
            ids.forEach(id => {
                $('#editDialog form').append(`<input type="hidden" name="ServiceIds" value="${id}" />`);
            });
            // 打开模态框
            $('#editDialog').modal('show');
        }
    });
})

同时给模态框中的输入框添加name属性(否则后端Request.Form无法正确取值):

<div class="modal-body">
    <label for="driName">DRI Name: </label>
    <input id="driName" name="driName" type="text" />
    <label for="driEmail">DRI Email: </label>
    <input id="driEmail" name="driEmail" type="text" />
    <hr />
    <label for="delegateName">Delegate Name: </label>
    <input id="delegateName" name="delegateName" type="text" />
    <label for="delgateEmail">Delegate Email: </label>
    <input id="delegateEmail" name="delegateEmail" type="text" />
</div>

后端修改

将ServiceIds改为可绑定的公共属性(或添加[BindProperty]特性),表单提交时会自动绑定:

[BindProperty]
public List<string>? ServiceIds { get; set; }

public async Task<IActionResult> OnPostSaveAsync()
{
    var dri = Request.Form["driName"].ToString();
    var driEmail = Request.Form["driEmail"].ToString();
    var delegateName = Request.Form["delegateName"].ToString();
    var delegateEmail = Request.Form["delegateEmail"].ToString();

    if (ContactRepository != null && ServiceIds != null)
    {
        NewContacts = await ContactRepository.GetContactsAsync(ServiceIds).ConfigureAwait(false) ?? new List<Contact> { };
        foreach (var contact in NewContacts!)
        {
            contact.DRIName = dri ?? string.Empty;
            contact.DRIEmail = driEmail ?? string.Empty;
            contact.DelegateName = delegateName ?? string.Empty;
            contact.DelegateEmail = delegateEmail ?? string.Empty;
        }

        await ContactRepository.UpdateContactsAsync(NewContacts).ConfigureAwait(false);
    }

    return new RedirectToPageResult("Index");
}

方案2:使用Session存储ServiceIds

后端配置

先确保项目启用Session,在Program.cs中添加:

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(5); // 设置会话超时时间
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

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

第一次AJAX请求的后端处理

假设你有接收AJAX的OnPostSetServiceIdsAsync方法,将ServiceIds存入Session:

public async Task<IActionResult> OnPostSetServiceIdsAsync([FromBody] List<string> serviceIds)
{
    HttpContext.Session.SetString("ServiceIds", JsonSerializer.Serialize(serviceIds));
    return new JsonResult(new { success = true });
}

OnPostSaveAsync中读取Session

public async Task<IActionResult> OnPostSaveAsync()
{
    var dri = Request.Form["driName"].ToString();
    var driEmail = Request.Form["driEmail"].ToString();
    var delegateName = Request.Form["delegateName"].ToString();
    var delegateEmail = Request.Form["delegateEmail"].ToString();

    var serviceIdsJson = HttpContext.Session.GetString("ServiceIds");
    var ServiceIds = serviceIdsJson != null ? JsonSerializer.Deserialize<List<string>>(serviceIdsJson) : null;

    if (ContactRepository != null && ServiceIds != null)
    {
        NewContacts = await ContactRepository.GetContactsAsync(ServiceIds).ConfigureAwait(false) ?? new List<Contact> { };
        foreach (var contact in NewContacts!)
        {
            contact.DRIName = dri ?? string.Empty;
            contact.DRIEmail = driEmail ?? string.Empty;
            contact.DelegateName = delegateName ?? string.Empty;
            contact.DelegateEmail = delegateEmail ?? string.Empty;
        }

        await ContactRepository.UpdateContactsAsync(NewContacts).ConfigureAwait(false);
        // 用完后清除Session中的数据
        HttpContext.Session.Remove("ServiceIds");
    }

    return new RedirectToPageResult("Index");
}

方案3:合并两次请求(取消AJAX,前端暂存ServiceIds)

去掉第一次AJAX请求,点击编辑按钮时直接将ServiceIds存在前端变量,提交模态框表单时通过AJAX一并发送:

let selectedServiceIds = [];

$(btnEdit).on('click', function () {
    var checkedList = $('[type=checkbox]:checked');
    selectedServiceIds = [];

    for (var item of checkedList) {
        var serviceId = $(item).closest('tr').find(".serviceId").text();
        selectedServiceIds.push(serviceId);
    }  

    // 直接打开模态框
    $('#editDialog').modal('show');
});

// 监听模态框表单提交,改用AJAX发送
$('#editDialog form').on('submit', function(e) {
    e.preventDefault();
    
    var formData = {
        driName: $('#driName').val(),
        driEmail: $('#driEmail').val(),
        delegateName: $('#delegateName').val(),
        delegateEmail: $('#delegateEmail').val(),
        ServiceIds: selectedServiceIds
    };

    $.ajax({
        type: "POST",
        url: $(this).attr('action'),
        data: JSON.stringify(formData),
        headers: { "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val() },
        contentType: "application/json",
        success: function () {
            $('#editDialog').modal('hide');
            // 刷新页面
            window.location.reload();
        }
    });
});

后端修改OnPostSaveAsync接收JSON数据:

public async Task<IActionResult> OnPostSaveAsync([FromBody] ContactUpdateModel model)
{
    if (ContactRepository != null && model.ServiceIds != null)
    {
        NewContacts = await ContactRepository.GetContactsAsync(model.ServiceIds).ConfigureAwait(false) ?? new List<Contact> { };
        foreach (var contact in NewContacts!)
        {
            contact.DRIName = model.DriName ?? string.Empty;
            contact.DRIEmail = model.DriEmail ?? string.Empty;
            contact.DelegateName = model.DelegateName ?? string.Empty;
            contact.DelegateEmail = model.DelegateEmail ?? string.Empty;
        }

        await ContactRepository.UpdateContactsAsync(NewContacts).ConfigureAwait(false);
    }

    return new JsonResult(new { success = true });
}

// 定义接收模型
public class ContactUpdateModel
{
    public string? DriName { get; set; }
    public string? DriEmail { get; set; }
    public string? DelegateName { get; set; }
    public string? DelegateEmail { get; set; }
    public List<string>? ServiceIds { get; set; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 17:57:03