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

ASP.NET Core MVC C# POST时如何保留下拉列表值避免重复查询数据库

解决方案

针对你遇到的POST提交后视图模型下拉集合丢失、需要重复查库的问题,有以下几种成熟的实现方案:

方案1:基础数据全局缓存(推荐)

你用到的联邦银行列表、州列表、状态列表、清算实体列表都属于变更频率极低的公共基础数据,完全可以通过服务端缓存存储,避免重复查询数据库。
你可以直接使用ASP.NET Core自带的IMemoryCache实现,示例修改如下:

// 先在Program.cs注册缓存服务
builder.Services.AddMemoryCache();

// 封装获取下拉数据的公共方法,自动走缓存
private async Task<(IEnumerable<C21FederalReserveBank> C21FedBanks, IEnumerable<FedBank> ACHFedBanks, IEnumerable<State> States, IEnumerable<ClearingEntity> ClearingEntities, IEnumerable<Status> Statuses)> GetDropDownDataAsync()
{
    const string cacheKey = "BankDropDownDatas";
    if (!_memoryCache.TryGetValue(cacheKey, out var dropDownData))
    {
        var fedBanks = await _bankLookupService.GetFedBanksAsync();
        dropDownData = new 
        {
            C21FedBanks = fedBanks.Select(b => new C21FederalReserveBank { C21FederalReserveBankID = b.Id, Name = b.ValueName }),
            ACHFedBanks = fedBanks,
            States = await _bankLookupService.GetStatesAsync(),
            ClearingEntities = await _bankLookupService.GetClearingEntitiesAsync(),
            Statuses = await _bankLookupService.GetStatusesAsync()
        };
        // 缓存12小时,可根据数据更新频率调整
        _memoryCache.Set(cacheKey, dropDownData, TimeSpan.FromHours(12));
    }
    return (dropDownData.C21FedBanks, dropDownData.ACHFedBanks, dropDownData.States, dropDownData.ClearingEntities, dropDownData.Statuses);
}

之后不管是GET的页面加载还是POST校验失败返回视图,直接调用这个方法即可,只会在缓存失效时才查询一次数据库,所有用户共享缓存数据,性能最优。

方案2:TempData临时存储

如果这些下拉数据是和当前用户请求关联的专属数据,可以用TempData存储:

// GET请求加载页面时存入TempData
var dropDownData = await GetDropDownDataAsync();
BankDetailViewModel vm = new BankDetailViewModel
{
    BankDetails = await _bankService.GetBankAsync(id),
    C21FedBanks = dropDownData.C21FedBanks,
    ACHFedBanks = dropDownData.ACHFedBanks,
    States = dropDownData.States,
    ClearingEntities = dropDownData.ClearingEntities,
    Statuses = dropDownData.Statuses
};
TempData["BankDropDownData"] = System.Text.Json.JsonSerializer.Serialize(dropDownData);
TempData.Keep("BankDropDownData"); // 保留数据防止读取后被自动清除

// POST校验失败时直接从TempData读取,不用查库
if (!ModelState.IsValid)
{
    var dropDownData = System.Text.Json.JsonSerializer.Deserialize<DropDownDataDto>(TempData["BankDropDownData"].ToString());
    model.C21FedBanks = dropDownData.C21FedBanks;
    model.ACHFedBanks = dropDownData.ACHFedBanks;
    model.States = dropDownData.States;
    model.Statuses = dropDownData.Statuses;
    model.ClearingEntities = dropDownData.ClearingEntities;
    TempData.Keep("BankDropDownData");
    return View("BankDetails", model);
}

TempData默认是单次请求有效,调用Keep方法可以延长数据有效期到下一次请求。

方案3:前端隐藏域序列化

如果不想占用服务端存储资源,可以把下拉集合序列化为JSON存在视图的隐藏域中,表单提交时自动带回服务端:

<!-- 在cshtml视图中添加隐藏域 -->
<input type="hidden" name="C21FedBanksJson" value="@System.Text.Json.JsonSerializer.Serialize(Model.C21FedBanks)" />
<input type="hidden" name="ACHFedBanksJson" value="@System.Text.Json.JsonSerializer.Serialize(Model.ACHFedBanks)" />
<!-- 其他集合同理 -->

POST方法中直接从表单参数读取反序列化即可:

if (!ModelState.IsValid)
{
    model.C21FedBanks = System.Text.Json.JsonSerializer.Deserialize<List<C21FederalReserveBank>>(Request.Form["C21FedBanksJson"]);
    model.ACHFedBanks = System.Text.Json.JsonSerializer.Deserialize<List<FedBank>>(Request.Form["ACHFedBanksJson"]);
    // 其他集合同理
    return View("BankDetails", model);
}

注意该方案适合集合数据量较小的场景,数据量过大会增加表单提交的体积和耗时,另外建议添加哈希校验防止数据被篡改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 08:36:04