Внедрение зависимостей для действий контроллера MVC, использующих модели представлений - PullRequest
1 голос
/ 11 марта 2012

Исходя из этого вопроса

MVC3 - Должен ли я спроектировать свою модель так, чтобы она была тесно связана с моим видом?

о том, как рекомендуется использовать видмодель для ваших представлений, и чтобы контроллер заполнил модель представления, я пробовал 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();
        }
    }

Мне трудно понять, как подойти к действиям контроллера с помощью модели представления.

* 1016Скажем, у меня есть 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?и списки выбора могут быть заполнены с использованием соответствующего репозитория, такого как kitchenRepository.All (но, похоже, это будет дублироваться в каждом действии), а затем модель представления передается в представление.

Как, хотяModelState.IsValid в действии POST Create () работает с этой моделью представления?

После этого мой контроллер ожидает объект RecipeViewModel, которому сам по себе нужен объект Recipe.

Должен ли он использоватьинтерфейсы для них тоже и есть Ninject обрабатывать все остальное?это желательно?

1 Ответ

3 голосов
/ 11 марта 2012

Прежде всего 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, чтобы заставить 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) и затем сохраняет модель домена.

...