C# MVC3中ViewModel与SelectList的映射
嗨,我正在努力找到正确的方法,所以我现在正在做的事情,所以我想我会问 以下是我的简化代码: 实体是嵌套类型,基于将它们与EF CodeFirst一起使用,ViewModel将与AutoMapper一起映射 发布表单时,由于dropdownlist映射到model.CourseId并显示我的课程数据,因此ModelState无效。。i、 e.CourseId=2,CourseList=Null,但也有[Required]属性,实际上只需要CourseId,但我还需要相关的错误消息 然后我想,在我的createget&POST操作中,视图可能应该只有CourseId,但我仍然需要将其显示为下拉列表并填充它,我不确定如何正确执行该操作 我也可能不理解如何正确使用它,如果我甚至需要CourseName,也就是说,由于数据库中已经存在课程,我只需要一个外键,它仍然可以让我显示所选的课程 我还计划将控制器操作中的所有映射和数据设置分解为一个单独的服务层,但目前它只是一个小型原型C# MVC3中ViewModel与SelectList的映射,c#,asp.net-mvc-3,C#,Asp.net Mvc 3,嗨,我正在努力找到正确的方法,所以我现在正在做的事情,所以我想我会问 以下是我的简化代码: 实体是嵌套类型,基于将它们与EF CodeFirst一起使用,ViewModel将与AutoMapper一起映射 发布表单时,由于dropdownlist映射到model.CourseId并显示我的课程数据,因此ModelState无效。。i、 e.CourseId=2,CourseList=Null,但也有[Required]属性,实际上只需要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);
}
}
//实体
公共课食谱{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共课程{get;set;}
}
公共课{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
//视图模型
公共类RecipeCreateViewModel{
//配方特性
公共int Id{get;set;}
公共字符串名称{get;set;}
//课程属性,通过AutoMapper作为原语
public int CourseId{get;set;}
公共字符串CourseName{get;set;}
//查看课程的下拉列表
[必选(ErrorMessage=“请选择课程。”)]
公共选择列表课程列表{get;set;}
}
//我的部分观点
@模型EatRateShare.WebUI.ViewModels.RecipeCreateViewModel
...
课程
@*DropDownListFor的第一个参数将确保选择了相关属性*@
@DropDownListFor(model=>model.CourseId,model.CourseList,“选择…”)
@Html.ValidationMessageFor(model=>model.CourseId)
...
//控制器动作
公共操作结果创建(){
//将配方映射到其视图模型
var recipeCreateViewModel=Mapper.Map(new Recipe());
recipeCreateViewModel.CourseList=新的选择列表(courseRepository.All,“Id”,“Name”);
返回视图(recipeCreateViewModel);
}
[HttpPost]
公共操作结果创建(RecipeCreateViewModel配方){
if(ModelState.IsValid){
var recipeEntity=Mapper.Map(配方);
交互存储。插入更新(交互);
recipereposition.Save();
返回操作(“索引”);
}否则{
recipe.CourseList=新选择列表(courseRepository.All,“Id”,“Name”);
返回视图(配方);
}
}
我通过执行以下操作修复了我的特定问题
[Required(ErrorMessage = "Please select a Course.")]
public int CourseId { get; set; }
// public string CourseName { get; set; }
public SelectList CourseList { get; set; }
视图将使用DropDownListFor帮助器将下拉列表映射到我的CourseId,这就是我真正需要的
现在转到AutoMapper的另一个问题,以及为什么它没有在创建后操作中映射回配方实体
我可能首先需要找到一种将相关课程名称存储在“CourseName”属性中的方法。如果CourseId是必需的属性,那么将
[必需]
属性放在该属性上,而不是列表上。。。但既然它不是空的,你甚至不需要它。把它从列表中删除。通过简化事情,我使它有点混乱。。CourseId在实体模型上有一个[Required]属性,用于通过EFCodeFirst使其成为sql compact数据库中的必填字段。我可能错误地认为它会将其传输到我的视图模型,因为以前我直接使用实体。我已经从我的CourseList属性中删除了必需的属性,这肯定是一个错误。因为还没有答案,我会在这里更新源代码,并发布准确的错误消息。没有错误消息,ModelState只是像我提到的那样无效。