【问题标题】:Models with list of sub models how to add, remove带有子模型列表的模型如何添加、删除
【发布时间】:2019-08-25 10:03:18
【问题描述】:

我有 3 个模型(Briefing、ligne、voie),每个模型都有一个子模型列表。如何将其管理到视图中以添加/删除项目?

public class Briefing
    {
        public int Id { get; private set; }
        public Guid GuidBriefing { get; set; }
        public int Version { get; set; }
        public List<Ligne> Lignes { get; set; }
        public string Libelle { get; set; }
        public string Description { get; set; }
    }

public class Ligne
    {
        public int Id { get; set; }
        public string Libelle { get; set; }
        public List<VoieObject> Voies { get; set; }
    }

public class VoieObject
   {
        public int Id { get; set; }
        public string Libelle { get; set; }
        public int Vitesse { get; set; }
        public string PointKilometrique { get; set; }
        public string PointKilometriqueFin { get; set; }
}

我使用实体框架,我想知道如何使用 MVC 5 将这些模型管理到视图中,以便在每个模型的列表中添加或删除项目。

例如:对于Briefing,如何在带有视图的列表中添加新项目“Ligne”。

供参考,我不能用这种写法:

@Html.LabelFor(model => model.FavouriteMovies[i].Title)
    @Html.EditorFor(model => model.FavouriteMovies[i].Title)
    @Html.ValidationMessageFor(model => model.FavouriteMovies[i].Title)

我必须使用:

<label for="FavouriteMovies_0__Title">Title</label>
<input id="FavouriteMovies_0__Title" name="FavouriteMovies[0].Title" type="text" value="" />
<span class="field-validation-error">The Title field is required.</span>

我也查看了这篇文章: Add item into List from View and pass to Controller in MVC5

但我不知道我提交表单时生成的 Json 是否会正确保存我的数据。

感谢您的帮助和好意:)

【问题讨论】:

    标签: c# entity-framework view asp.net-mvc-5 model


    【解决方案1】:

    首先,为了省去很多麻烦,不要将实体对象传递给您的视图。是的,很多例子都会展示它,但它会暴露你不希望客户端用户知道的数据,它会导致从数据库加载更多的数据并通过网络传输而不是需要,它会促进惰性, 未经验证的保存。 (即接受一个实体返回,将其附加到上下文,将状态设置为已修改,并保存更改)如果不先彻底检查,绝对不要相信来自客户端的任何返回。

    您可能需要拆分您的问题,并举例说明您尝试过的内容与您期望的内容,因为根据您想要做的事情,有多种方法可供选择。例如,您可以“添加”一个子实体(创建一个新子实体并将其与实体关联),或者您可以将现有实体与另一个实体关联。例如:对于电影,我可能想要“添加”评论,这将涉及让用户输入一些字段并保存电影。或者,我可能已经创建了预订并想要“关联”一部电影。这涉及找到合适的电影实例而不是创建它。

    在高层次上,对于 Web 应用程序,编辑实体的生命周期如下所示:

    • 从上下文加载实体。
    • 映射到仅显示视图所需数据的视图模型。
    • 如果这类似于包含电影的预订,那么它将包含 MovieViewModel 的集合,其中可能包含 MovieId、名称和任何其他可能显示的详细信息。
    • 将视图模型返回到视图。

    对于关联场景,例如当我们创建一个新的预订并想要关联电影时,视图还将通过 Fetch/Ajax 等调用来搜索匹配项或列出可用记录。同样,这些调用将遵循上述步骤。客户端应用程序会将所选电影等与预订相关联,这可能包括添加或删除与电影的关联。保存时,我们会将操作分解为特定的操作,例如 UpdateReservation 与 CancelReservation。

    更新预留将接受视图模型(或另一个为更新而专门构建的视图模型),然后: - 验证视图模型适用于当前登录的用户。 - 验证传递的数据是否正确。 - 如果数据有任何问题,请记录详细信息并终止会话。 (疑似用户篡改/黑客攻击) - 通过 ID 从上下文加载实体,包括可能会更新的子引用。 (快速地) - 验证数据是否过时(检查从读取实体时视图模型中记录的时间戳/行版本,以查看它是否与当前实体时间戳匹配。如果不匹配,则表示其他人修改了此记录会话阅读它,因此您可能希望通知用户查看并重新应用更改)

    要更新子集合,您可以使用子视图模型集合或子 ID 来获取要保持关联的 ID 列表。这可能包括新的引用,并且可能表示删除现有的引用。所以我们把这些场景分开:

    var childIds = viewModel.Children.Select(x => x.ChildId).ToList(); // we only care about the IDs.
    var existingChildIds = entity.Children.Select(x => x.ChildId).ToList(); 
    var childIdsToAdd = childIds.Except(existingChildIds);
    
    var childEntitiesToAdd = context.Children.Where(x => childIdsToAdd.Contains(x.ChildId).ToList();
    var childEntitiesToRemove = entity.Children.Where(x => !childIds.Contains(x.ChildId));
    
    foreach(var child in childEntitiesToRemove)
      entity.Children.Remove(child);
    
    entity.Children.AddRange(childEntitiesToAdd);
    

    在添加和删除新的子实体时,我们可以将它们视为单独的操作。通常,创建新实体的行为涉及记录比我们通常在父级别查看的更多的数据,因此这通常在单独的视图上完成,例如弹出对话框或不同的页面。这可以在视图上使用单独的操作来创建新子项并通过 ID 将其与父项关联。操作完成后,可以从服务器更新或刷新父视图模型的原始视图。

    因此,执行诸如记录评论之类的控制器操作可能如下所示:

    [Post]
    public async Task<JsonResult> AddMovieReview(int movieId, string comment, int rating)
    {
       // validate movie exists, and rating is valid, i.e. 1-5
       // create new Review entity using comment and rating.
       // load movie from context using movie ID.
       // add review to the movie.
       // save changes.
       // return a view model with a result (success/failure) and perhaps the new avg. rating for the movie.
    }
    

    希望这会给您一些研究和尝试的想法,但除此之外,请使用一些代码创建一个问题,说明您已经尝试过什么以及您希望通过具体问题看到什么。

    【讨论】:

      猜你喜欢
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      • 2021-07-06
      相关资源
      最近更新 更多