使用视图模型的MVC控制器操作的依赖注入

时间:2012-03-10 22:33:49

标签: asp.net-mvc asp.net-mvc-3 c#-4.0 dependency-injection ninject

继续这个问题

MVC3 - Should I design my Model to be tightly coupled to my View?

关于如何建议为视图使用视图模型并让Controller填充视图模型,我一直在尝试使用Ninject.MVC并使用一些示例来为存储库模式注入控制器所需的存储库。

喜欢这个

    public RecipesController(IRepository<Member> memberRepository, IRepository<Course> courseRepository, IRepository<Cuisine> cuisineRepository, IRepository<Recipe> recipeRepository) {
        this.memberRepository = memberRepository;
        this.courseRepository = courseRepository;
        this.cuisineRepository = cuisineRepository;
        this.recipeRepository = recipeRepository;
    }

然后我使用MVC Scaffolding来查看行为是什么样的

    public ActionResult Create() {
        ViewBag.PossibleCuisines = cuisineRepository.All;
        ViewBag.PossibleMembers = memberRepository.All;
        ViewBag.PossibleCourses = courseRepository.All;
        return View();
    }

    [HttpPost]
    public ActionResult Create(Recipe recipe) {
        if (ModelState.IsValid) {
            recipeRepository.InsertOrUpdate(recipe);
            recipeRepository.Save();
            return RedirectToAction("Index");
        } else {
            ViewBag.PossibleMembers = memberRepository.All;
            ViewBag.PossibleCourses = courseRepository.All;
            ViewBag.PossibleCuisines = cuisineRepository.All;
            return View();
        }
    }

我很难理解如何使用视图模型来处理控制器操作。

说我有这样的RecipeViewModel:

    public class RecipeViewModel {
    public Recipe Recipe { get; set; }
    public SelectList AuthorList { get; set; }
    public SelectList CourseList { get; set; }
    public SelectList CuisineList { get; set; }

    public RecipeViewModel(Recipe recipe) {
        Recipe = recipe;
    }
}

这是我的视图将使用的模型。我假设Create()GET操作将首先创建此视图模型,并且必须创建一个新的Recipe对象以传递给ViewModel的构造函数?并且可以使用相关的存储库(例如cuisineRepository.All)填充选择列表(但这似乎在每个操作中都会重复),然后将视图模型传递给视图。

如果Create()POST操作中的ModelState.IsValid如何处理此视图模型?

通过这样做,我的控制器现在需要一个RecipeViewModel对象,它本身需要一个Recipe对象。

它是否应该使用这些接口并让Ninject处理剩下的?这是可取的吗?

1 个答案:

答案 0 :(得分:3)

首先,RecipeViewModel不应包含Recipe对象,但应包含以下成员:

public class RecipeViewModel {
   public RecipeViewModel(IRepository<Course> courseRepository, IRepository<Cuisine> cuisineRepository, IRepository<Recipe> recipeRepository){
       this.courseRepository = courseRepository;
       this.cuisineRepository = cuisineRepository;
       this.recipeRepository = recipeRepository;
   }
   public string RecipeName { get; set; }
   public IList<IngredientsViewModel> Ingredients { get; set;}
   public SelectList AuthorList { get; set; }
   public SelectList CourseList { get; set; }
   public SelectList CuisineList { get; set; }

   public static RecipeViewModel Build()
   {
        //Build up Select Lists here and return View model.
   }

}

然后在ViewModel上使用Validation属性来使ModelState.IsValid工作:

public class RecipeViewModel {
   [Required]
   public string RecipeName { get; set; }
   public IList<IngredientsViewModel> Ingredients { get; set;}
   public SelectList AuthorList { get; set; }
   public SelectList CourseList { get; set; }
   public SelectList CuisineList { get; set; }
}

我个人然后会重构您的控制器以将数据层与视图分离。

public RecipesController(IRecipeService recipeService) {
    this.recipeService  = recipeService;
}

然后控制器的其余部分如下:

public ActionResult Create() {
    var recipeViewModel = new RecipeViewModel();
    recipeViewModel.Build():
    ViewBag.PossibleCuisines = recipeViewModel.CuisineList;
    ViewBag.PossibleMembers = recipeViewModel.AuthorsList;
    ViewBag.PossibleCourses = recipeViewModel.CourceList;
    return View();
}

[HttpPost]
public ActionResult Create(RecipeViewModel recipe) {
    if (ModelState.IsValid) {
        _recipeService.Save(recipe)
        return RedirectToAction("Index");
    } else {
        return View();
    }
}

然后,IRecipeService执行从视图模型到域模型的映射(在本例中为RecipeViewModel到Recipe),然后保留域模型。