【问题标题】:ASP.NET MVC - Provide additional data to dynamically created ViewModelASP.NET MVC - 为动态创建的 ViewModel 提供附加数据
【发布时间】:2021-10-26 07:18:09
【问题描述】:

我有一个允许用户动态添加项目(在本例中为“电影”)的视图。每部电影都有一个“评级”,应该可以从下拉列表中选择。以前,这来自一个枚举,并且效果很好(这在下面被注释掉了)。不过,“评分”列表最近已移至配置文件中。

代码如下:

创建.cshmtl

@model MyProject.Models.ViewModels.ShelfAddViewModel

        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Name)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Rating)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody id="movieContainer">
            @Html.EditorFor(model => model.Movie)
        </tbody>
        <tfoot id="item-list">
            <tr>
                <td>
                    <input type="button" id="btnAdd" class="btn" value="Add" />
                </td>
            </tr>
        </tfoot>

...

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}

<script type="text/javascript">

    $("#btnAdd").on('click', function () {
        $.ajax({
            async: true,
            data: $('#form').serialize(),
            type: "POST",
            url: '/Movies/AddMovie',
            success: function (partialView) {
                $('#movieContainer').html(partialView);
            }
        });
    });

MovieAddViewModel.cshtml

@model MyProject.Models.ViewModels.MovieAddViewModel
<tr>
    <td>
        <input asp-for="Id" class="form-control" />
    </td>   
    <td>
        <select asp-for="Rating" asp-items="Model.RatingList" class="form-control"></select>      
@*<select asp-for="Rating" asp-items="Html.GetEnumSelectList<RatingType>()" class="form-control"></select>*@
    </td>     
    <td>
        <input type="button" onclick="Remove(this)" id="removeMovie_@Model.Uid" class="btn" value="Remove" />
    </td>
</tr>

MovieController.cs

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult AddMovie([Bind("Id,Movie")] ShelfAddViewModel shelf)
    {
        shelf.Movies.Add(new MovieAddViewModel());
        return PartialView("_Movie", shelf);
    }

MovieAddViewModel.cs

public class MovieAddViewModel
{
    [Display(Name = "Movie Title")]
    public string Name { get; set; }

    [Display(Name = "Rating")]
    public string Rating { get; set; }
    // public RatingType Rating { get; set; }

    public List<SelectListItem> RatingList { get; set; }    


}

新的评分列表来自一个 JSON 文件,并按如下方式加载:

        var standards =
            _configuration.GetSection("Standards");
        var movieStandards = standards.GetSection("MovieStandards").Get<List<string>>();
        var movieStandardSelectList = movieStandards.Select(x=> new SelectListItem() { Text = x, Value = x }).ToList();

我的问题是,如何将这个 List 放到 ViewModel 上?我不能将它添加到构造函数中,因为除非构造函数没有参数,否则 ASP 不知道如何动态创建对象。我不能在创建 ViewModel 时只更新 RatingList 属性,因为当我添加另一部电影时它会消失。我也不觉得我应该直接从我的 ViewModel 访问设置。这里最好的方法是什么?

(请注意:我已经修改了我的代码,以便其他有相同问题的人更容易理解问题 - 对任何错误深表歉意。请告知我是否可以更好地表述我的问题标题)

【问题讨论】:

  • 请发布用于创建 MovieAddViewModel.cshtml 的操作
  • 我什至没有进入创建 - 当我单击“添加”时,任何前一行的下拉内容都会消失 - 仅填充新条目。

标签: c# asp.net-mvc selectlistitem


【解决方案1】:

有很多方法可以做到这一点。其中一个只需将其加载到控制器内部。

我很难从你的回答中理解你真正使用的是什么控制器或动作,所以我会给你一个提示,你可以根据你的代码进行调整

public class MyController : Controller
{
private readonly List<SelectListItem>  _movieStandardSelectList ;

  public MyController( IConfiguration configuration)
  {
      
   var movieStandards = configuration.GetSection("Standards:MovieStandards").Get<List<string>>();
   _movieStandardSelectList = movieStandards.Select(x=> new SelectListItem() { Text = x, Value = x }).ToList();       
  }
  public ActionResut MyAction()
 {
       var model = new MovieAddViewModel
       {
       RatingList=  _movieStandardSelectList;
       .... another your code  
       }
    return View(model);
}

我通常使用的另一种方法是创建一个全局静态变量

public  static List<SelectListItem>  MovieStandardSelectList {get; set;};

并将您可以在构造函数中看到的代码放入启动文件中,将列表分配给这个全局变量。不过这里就不放详细代码了,怕会遇到太多批评。

【讨论】:

  • 第一个解决方案对我不起作用。如果我创建一个 MovieAddViewModel 的新实例,并在构造函数中创建标准列表,则可以正常工作。但是,如果我在控制器中创建实例,然后设置列表的属性(根据您的示例),那么当我在前端的列表中添加另一部电影时,列表就会消失。如果我检查 CHrome 中的 ModelState,那么 RatingList 元素将从之前的条目中消失。我同意第二种解决方案有点差,但我可能不得不这样做!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
相关资源
最近更新 更多