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

.NET Core Razor Pages单页提交保存发票表头及明细行报错

解决发票创建页面的ArgumentNullException空引用异常

问题现状

开发发票创建页面时,需求是填写发票表头(InvHeader)和动态明细行(InvRow)后单次提交保存。已解决多行添加的RowList错误,但现在触发ArgumentNullException:值不能为 null。(参数 'source'),错误触发点为视图代码@for (int i = 0; i < Model.RowList.Count(); i++),根源是RowList为null时调用Count()方法导致空引用。

问题原因

  1. 后端PageModel中RowList仅声明未初始化默认值,若OnGetAsync未执行(比如Post验证失败返回Page时),RowList会处于null状态。
  2. OnPostAsync方法中,当Model验证失败返回Page时,未重新初始化RowList,导致视图渲染时Model.RowList为null,调用Count()抛出异常。

解决方案

后端代码修改

1. 初始化RowList默认值

修改PageModel属性声明,给RowList初始化空列表,从根源避免null:

[BindProperty]
public InvHeader InvHeader { get; set; } = default!;
// 初始化空列表,防止null
public IList<InvRow> RowList { get; set; } = new List<InvRow>();

2. 完善OnPostAsync方法

当Model验证失败返回Page时,确保RowList有有效值,同时添加[BindProperty]保证表单数据正确绑定:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        // 若提交的RowList为空,保持空列表而非null
        RowList = RowList ?? new List<InvRow>();
        return Page();
    }

    _context.InvHeaders.Add(InvHeader);
    await _context.InvRows.AddRangeAsync(RowList);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

注:移除原方法的IList<InvRow> RowList参数,改用[BindProperty]绑定,避免参数传递导致的null问题。

3. 保持OnGetAsync原有逻辑(可选)

原有初始化默认行的逻辑无需修改,初始化默认值后即使不赋值,RowList也会是安全的空列表:

public IActionResult OnGetAsync()
{
    var rr = new List<InvRow>()
    {
        new InvRow() { Name = "Apple", Qty = 5, Price = 100 },
        new InvRow() { Name = "Peach", Qty = 3, Price = 500 },
        new InvRow() { Name = "Ananas", Qty = 1, Price = 1100 },
    };

    RowList = rr;

    return Page();
}

前端代码修改

统一数据源为RowList,并添加null判断避免渲染异常:

<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    <!-- 表头表格 -->
    <table class="table table-striped border-0" style="width: 100%; text-align: left;">
        <thead class="border-0">
            <tr class="border-0">
                <td class="border-0" style="min-width:100%;">
                    <div class="border border-secondary p-4">
                        <div class="row">
                            <div style="float:left;width:50%;">
                                <div class="form-group m-1">
                                    <label asp-for="InvHeader.Cli" class="control-label" style="font-size:80%;">Client</label>
                                    <input asp-for="InvHeader.Cli" class="form-control" value="clients name" />
                                </div>
                            </div>
                            <div style="float:left;width:25%;">
                                <div class="form-group m-1">
                                    <input asp-for="InvHeader.InvDate" class="form-control" type="date" value="@(DateTime.UtcNow.Date.ToString("yyyy-MM-dd"))" />
                                    <span asp-validation-for="InvHeader.InvDate" class="text-danger"></span>
                                </div>
                            </div>
                            <div style="float:left;width:25%;">
                                <div class="form-group m-1">
                                    <input asp-for="InvHeader.InvNr" class="form-control" value="33" />
                                    <span asp-validation-for="InvHeader.InvNr" class="text-danger"></span>
                                </div>
                            </div>
                        </div>
                    </div>
                </td>
            </tr>
        </thead>
    </table>

    <!-- 动态明细行表格 -->
    <table id="table1" border="0">
        <tr style="font-size:80%">                  
            <th style="width:50%">Product</th>
            <th style="width:5%">qty</th>
            <th style="width:5%">price</th>
        </tr>
        <!-- 添加null判断,安全遍历RowList -->
        @if (Model.RowList != null)
        {
            @for (int i = 0; i < Model.RowList.Count(); i++)
            {
                <tr class="border-bottom">                           
                    <td>
                        <select asp-for="RowList[i].ProdId" class="form-control" style="width:100%">
                            <!-- 替换为实际产品数据源,示例用Model.Products -->
                            @foreach (var product in Model.Products)
                            {
                                <option value="@product.ProdId" price="@product.Price">@product.Name, @product.Price</option>
                            }
                        </select>
                    </td>
                    <td><input asp-for="RowList[i].Qty" class="form-control" style="width:100%" /></td>
                    <td><input asp-for="RowList[i].Price" class="form-control" style="width:100%" /></td>
                </tr>
            }
        }
    </table>
</form>

注:原前端代码中Model.PL、Model.MR与后端RowList不匹配,需统一为RowList保证表单绑定生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 16:52:13