2012-03-27 32 views
0

您好我正在努力找到正确的方法,因为我目前正在做的,所以我想我会问。MVC3 ViewModel与SelectList的映射

这里是我的简化代码:

的实体嵌套基于使用他们EF CodeFirst和视图模型类型被映射与AutoMapper。

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

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

我可能也不会理解这应该如何正确使用,如果我甚至需要课程名称,即因为课程已经存在于数据库中我只想要一个外键,它仍然会让我显示选定的课程。

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

// 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); 
     } 
    } 
+0

如果CourseId是必需属性,则将'[Required]'属性放在该列表上,而不是列表中......但由于它不可空,所以您可能甚至不需要该属性。从列表中删除它。 – 2012-03-27 21:22:50

+0

通过简化事情我做了一些让人困惑的事情.. CourseId在实体模型上有一个[Required]属性,用于通过EFCodeFirst在sql compact数据库中使其成为必需字段。我可能犯了一个错误,认为它会将其转移到我的视图模型中,因为以前我直接使用这些实体。我从我的CourseList属性中删除了Required属性,这肯定是一个错误。 – Pricey 2012-03-27 21:35:14

+0

由于目前还没有答案,我会在此处更新源代码并发布确切的错误消息。 – 2012-03-27 21:40:09

回答

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”属性中存储相关的课程名称。