【问题标题】:Mapping of ViewModel with SelectList in MVC3MVC3中ViewModel与SelectList的映射
【发布时间】:2012-03-27 21:03:05
【问题描述】:

您好,我正在努力为我目前正在做的事情找到正确的 SO 方法,所以我想我会问。

这是我的简化代码:

实体是嵌套类型,基于将它们与 EF CodeFirst 一起使用,并且 ViewModel 正在使用 AutoMapper 进行映射。

发布表单时,ModelState 无效,因为下拉列表映射到 model.CourseId 并显示我的课程数据。即 CourseId = 2,CourseList = Null,但也具有 [Required] 属性,实际上只有 CourseId是必需的,但我还需要相关的错误消息。

然后我认为在我的 Create GET & POST 操作中,视图可能应该只有 CourseId,但我仍然需要将其显示为下拉列表并填充它,我不确定如何正确执行此操作。

我也可能不明白应该如何正确使用它,如果我什至需要 CourseName,即因为课程已经存在于数据库中,我只想要一个外键,它仍然可以让我显示所选课程。

我还计划将我的控制器操作中的所有这些映射和数据设置分解为一个单独的服务层,但目前它是一个小型原型。

// Entities
public class Recipe {
     public int Id { get; set; }
     public string Name { get; set; }
     public Course Course { get; set; }
}

public class Course {
    public int Id { get; set; }
    public string Name { get; set; }
}

// View Model
public class RecipeCreateViewModel {
    // Recipe properties
    public int Id { get; set; }
    public string Name { get; set; }

    // Course properties, as primitives via AutoMapper
    public int CourseId { get; set; }
    public string CourseName { get; set; }

    // For a drop down list of courses
    [Required(ErrorMessage = "Please select a Course.")]
    public SelectList CourseList { get; set; }
}

// Part of my View
@model EatRateShare.WebUI.ViewModels.RecipeCreateViewModel
...
<div class="editor-label">
        Course
    </div>
    <div class="editor-field">
        @* The first param for DropDownListFor will make sure the relevant property is selected *@
        @Html.DropDownListFor(model => model.CourseId, Model.CourseList, "Choose...")
        @Html.ValidationMessageFor(model => model.CourseId)
    </div>
    ...


    // Controller actions

    public ActionResult Create() {
        // map the Recipe to its View Model
        var recipeCreateViewModel = Mapper.Map<Recipe, RecipeCreateViewModel>(new Recipe());
        recipeCreateViewModel.CourseList = new SelectList(courseRepository.All, "Id", "Name");
        return View(recipeCreateViewModel);
    }

    [HttpPost]
    public ActionResult Create(RecipeCreateViewModel recipe) {
        if (ModelState.IsValid) {
            var recipeEntity = Mapper.Map<RecipeCreateViewModel, Recipe>(recipe);
            recipeRepository.InsertOrUpdate(recipeEntity);
            recipeRepository.Save();
            return RedirectToAction("Index");
        } else {
            recipe.CourseList = new SelectList(courseRepository.All, "Id", "Name");
            return View(recipe);
        }
    }

【问题讨论】:

  • 如果 CourseId 是必需属性,则将 [Required] 属性放在该属性上而不是在列表中...但是由于它不可为空,您甚至可能不需要它。将其从列表中删除。
  • 通过简化让事情变得有点混乱.. CourseId 在实体模型上有一个 [Required] 属性,用于通过 EFCodeFirst 使其成为 sql 紧凑型数据库中的必填字段。我可能错误地认为它将它转移到我的视图模型,因为以前我直接使用实体。我从 CourseList 属性中删除了 Required 属性,这绝对是一个错误。
  • 由于还没有答案,我会在此更新源并发布确切的错误消息。
  • 没有错误消息,ModelState 就像我提到的那样无效。

标签: c# asp.net-mvc-3


【解决方案1】:

我只是通过执行以下操作解决了我的特定问题。

        [Required(ErrorMessage = "Please select a Course.")]
    public int CourseId { get; set; }
    // public string CourseName { get; set; }
    public SelectList CourseList { get; set; }

视图将使用 DropDownListFor 帮助器将下拉菜单映射到我的 CourseId,这就是我真正需要的。

现在谈谈 AutoMapper 的另一个问题,以及为什么它没有在 POST Create 操作中映射回 Recipe 实体。

我可能首先需要找到一种将相关课程名称存储在“CourseName”属性中的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    相关资源
    最近更新 更多