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

ASP.NET Core MVC主从模型中ArgumentOutOfRangeException异常排查

问题分析与解决:Stock主从模型添加Article时索引越界错误

问题背景

我拥有Stock和Article主从模型,Article以StockId作为外键。我在表格中展示Stock数据,希望创建局部视图为表格每行添加Article,但运行时出现索引越界错误。

现有代码

StockController.cs

public IActionResult AddArticle(int id)
{
    Stock stock = _dbcontext.Stock.Where(e => e.StockId == id).FirstOrDefault();
    stock.Articles.Add(new Article() { ArticleId = 1 });
    return PartialView("_AddArticlePartialView", stock);
}

public IActionResult AddArticle(Article article)
{
    if (article != null)
    {
        _dbcontext.Article.Add(article);
        _dbcontext.SaveChanges();
        return RedirectToAction("Index");
    }
    return View();           
}

Index.cshtml

@model IEnumerable<Stock>

@{
    ViewData["Title"] = "Stock";
    Layout = "~/Views/Shared/_Theme.cshtml";
 }
<table class="table table-bordered table-hover" id="display">
                <thead>
                    <tr>
                        <th>
                            @Html.DisplayNameFor(model => model.CategoryId)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.Designation)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.Quantite)
                        </th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var item in Model)
                    {
                        <tr>
                            <td>
                                @Html.DisplayFor(modelItem => item.Category.CategoryName)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Designation)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Quantite)
                            </td>

                            <td>
                                <div class="btn-group-sm">
                                    <button class="btn btn-primary" data-toggle="modal" data-target="@("#AddArticle-"+item.StockId)" data-url="@Url.Action($"AddArticle/{item.StockId}")"><i class="fa fa-plus"></i>Ajouter Articles</button>
                                    @await Html.PartialAsync("_AddArticlePartialView", item)
                                </div>
                            </td>
                        </tr>
                    }
                </tbody>
            </table>

_AddArticlePartialView.cshtml

@model StockProject.Models.Stock

@{
    ViewData["Title"] = "_AddArticlePartialView";

}

<div class="modal fade" role="dialog" tabindex="-1" id="@("#AddArticle-"+Model.StockId)" aria-labelledby="addArticleLabel" aria-hidden="true" >
    <div class="modal-dialog modal-xl modal-dialog-scrollable" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">Articles</h3>
            </div>
            <div class="modal-body">
                <form asp-action="AddArticle" method="post">
                    <div class="card">
                        <div class="card-header">
                            <h3 class="card-title">Articles</h3>

                        </div>
                        
                        <div class="card-body">
                            <table class="table table-bordered" id="articleTable">
                                <thead>
                                    <tr>
                                        <th>Numero de Serie</th>
                                        <th>Marque</th>
                                        <th>Etat</th>                                        
                                    </tr>
                                </thead>
                                <tbody>
                                    @for (int i = 0; i < Model.Quantite; i++)
                                    {
                                        <tr>
                                            <td>
                                                @Html.EditorFor(x => x.Articles[i].NumeroSerie, new { htmlAttributes = new { @class = "form-control" } })
                                            </td>

                                            <td>
                                                @Html.EditorFor(x => x.Articles[i].Marque, new { htmlAttributes = new { @class = "form-control" } })
                                            </td>
                                            <td>
                                                @Html.DropDownListFor(x => x.Articles[i].Etat, new List<SelectListItem> {
                                                       new SelectListItem { Value = "En Marche" , Text = "En Marche" },
                                                       new SelectListItem { Value = "En Panne" , Text = "En Panne" },

                                                    },
                                                  new { @class = "form-control" })
                                            </td>
                                            
                                        </tr>
                                    }

                                </tbody>
                            </table>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Annuler</button>
                        <button type="submit" class="btn btn-primary">Sauvegarder</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>

错误信息

Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')

错误发生在局部视图的这一行:

@Html.EditorFor(x => x.Articles[i].NumeroSerie, new { htmlAttributes = new { @class = "form-control" } })

问题原因与解决方案

核心问题

  1. 页面加载时直接渲染局部视图导致集合为空:Index页面循环中直接调用@await Html.PartialAsync("_AddArticlePartialView", item),此时传入的Stock实例的Articles集合为空,但局部视图用Model.Quantite作为循环次数访问Articles[i],当Quantite > 0时必然索引越界。
  2. 控制器GET方法未被实际调用:按钮的data-url未通过AJAX触发请求,而是直接渲染了未初始化的局部视图。
  3. 批量添加逻辑不匹配:POST方法仅接收单个Article,但视图生成多个输入框,无法正确绑定集合数据。

修复步骤

1. 修改Index页面,改用AJAX加载模态框

移除页面中直接渲染局部视图的代码,添加JS处理按钮点击事件,通过AJAX请求控制器获取模态框内容:

<!-- 在Index页面末尾添加JS -->
<script>
    $(document).ready(function() {
        $('[data-toggle="modal"]').click(function() {
            var url = $(this).data('url');
            var targetModal = $(this).data('target');
            
            $.get(url, function(data) {
                $(targetModal).remove();
                $('body').append(data);
                $(targetModal).modal('show');
            });
        });
    });
</script>

同时修正按钮的data-target格式:

data-target="#AddArticle-@item.StockId"

2. 修改控制器GET方法,初始化对应数量的Article

根据Stock的Quantite属性,向Articles集合添加对应数量的空实例:

public IActionResult AddArticle(int id)
{
    Stock stock = _dbcontext.Stock.Where(e => e.StockId == id).FirstOrDefault();
    stock.Articles.Clear();
    // 根据库存数量生成对应数量的Article
    for (int i = 0; i < stock.Quantite; i++)
    {
        stock.Articles.Add(new Article() { StockId = id });
    }
    return PartialView("_AddArticlePartialView", stock);
}

3. 修改POST方法,支持批量添加Article

修改方法接收List<Article>集合,并确保外键正确:

public IActionResult AddArticle(List<Article> articles, int stockId)
{
    if (articles != null && articles.Any())
    {
        foreach (var article in articles)
        {
            article.StockId = stockId;
            _dbcontext.Article.Add(article);
        }
        _dbcontext.SaveChanges();
        return RedirectToAction("Index");
    }
    return View();           
}

同时在局部视图表单中添加隐藏字段传递stockId:

<form asp-action="AddArticle" method="post">
    <input type="hidden" name="stockId" value="@Model.StockId" />
    <!-- 其余表单内容不变 -->
</form>

4. 修正模态框ID格式

局部视图中模态框ID去掉多余的#符号:

<div class="modal fade" role="dialog" tabindex="-1" id="AddArticle-@Model.StockId" aria-labelledby="addArticleLabel" aria-hidden="true" >

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:03:12