手动填充包含 collection 的模型

Manually populating a model that includes a collection

我正在尝试使用文件系统为 ASP.net Core 中的页面填充模型。我得到的大部分都有效,但是 MusicFile collection 没有正确显示 - 所有项目都显示应该与最后一个项目相关联的 MusicFiles。我不知道这是否是因为在我填充模型时以前的项目被覆盖,或者是否由于某种原因它无法在视图中访问正确的 collection。我尝试使用各种类型和各种类型的 for 循环都无济于事。这是我目前拥有的:

型号:

public class MusicItem
{

    public string Name { get; set; }
    public List<MusicFile> MusicFiles { get; set; }
}

public class MusicFile
{
    public string Url { get; set; }
    public string Display { get; set; }
}

控制器(简化):

public IActionResult Files(string folder)
    {
        List<MusicItems> MusicList = new List<MusicItems>();
        List<MusicFile> musicFiles = new List<MusicFile>();
        MusicFile musicFile;
        ..
        foreach (string folderName in folders)
        {
            if (musicFiles.Count>0) { musicFiles.Clear(); }
            for each file in files
            {
            ...
            musicFile = new MusicFile { Display = display, Url = MakeVirtualPath(fileName) };
            musicFiles.Add(musicFile);
            }
        MusicList.Add(new MusicItems { Name = folderName, MusicFiles = musicFiles });

        }

    return View(MusicList);  
    }

查看:

@model List<Web.Areas.Admin.Models.MusicItem>


@foreach (var Musicitem in Model)
{
    int id = 0;

        <h3>@Html.DisplayFor(modelItem => Musicitem.Name)</h3>


        @for (int i = 0; i < Musicitem.MusicFiles.Count; i++)
        {

            if (id != 0)
            {<span> |  </span>}
            <a href="@Musicitem.MusicFiles[i].Url">@Musicitem.MusicFiles[i].Display</a>
            id++;

        }

}

注意我已经大大简化了控制器——假设所有变量都在某处定义。标题显示正确。如果有任何帮助,我将不胜感激!

问题是由这个引起的:musicFiles.Clear(); 和这个 MusicFiles = musicFiles。您正在将 musicFiles 变量分配给每个 MusicItem,这是 c#(列表)中的引用类型。所有这些(音乐项目)都指向列表的相同引用,因此当您调用 Clear 持有引用的每个人时,都会 "see" 进行更改。同样,当循环结束并填充 musicFiles 时,所有 MusicItems 将具有相同的值,因为它们指向相同的引用。

这本质上就是 C# 变量的工作方式,因此您最好了解这一点。它并不太复杂,您只需要 reading/practice 来理解它。

我强烈建议您阅读 Jon Skeet References and Values and later Parameter passing in C# 撰写的这两篇很棒的文章。在我看来,他的解释是我在这个话题上见过的最好的解释之一。它简洁明了。但请务必了解它,因为这对于 C# 的工作方式至关重要,它会让你的生活变得更加 easier/better 作为开发人员。

解决您的问题:

您可以通过稍微更改您的代码来解决它:

public IActionResult Files(string folder)
{
    List<MusicItems> MusicList = new List<MusicItems>();

    foreach (string folderName in folders)
    {
        // creates an item with an empty list of files
        var musicItem = new MusicItems { Name = folderName, MusicFiles = new List<MusicFile>() };

        foreach(var file in files)
        {
            // create the file
            musicFile = new MusicFile { Display = display, Url = MakeVirtualPath(fileName) };

            // add the file to the item, declared in the loop.
            musicItem.MusicFiles.Add(musicFile);
        }

        MusicList.Add(musicItem);
    }

    return View(MusicList);  
}