c# – 在视图模型中使用存储库可以吗?

前端之家收集整理的这篇文章主要介绍了c# – 在视图模型中使用存储库可以吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
假设我有复杂的视图模型,有很多数据,如国家/地区,产品,类别等的列表,我每次创建viewmodel时都需要从数据库获取数据.

我想要解决的主要问题是,当我处理POST操作时,一些TestModel发布的值不正确,导致ModelState.IsValid为false,那么我必须返回与当前发布的模型相同的视图.这迫使我再次获得我的类别列表,因为我在GET操作中这样做.这在控制器中增加了很多重复的代码,我想删除它.目前我正在做以下事情:

我的模型和视图模型:

模型,实体存储在数据库中:

  1. public class Category
  2. {
  3. public int Id { get; set; }
  4. public string Name { get; set; }
  5.  
  6. public IEnumerable<Category> SubCategories { get; set; }
  7. }

查看型号:

  1. public class CategoryModel
  2. {
  3. public int Id { get; set; }
  4. public string Name { get; set; }
  5. }
  6.  
  7. public class TestModel
  8. {
  9. [required]
  10. [MaxLength(5)]
  11. public string Text { get; set; }
  12.  
  13. public int SelectedCategory { get; set; }
  14. public IEnumerable<CategoryModel> Categories { get; set; }
  15. public SelectList CategoriesList
  16. {
  17. get
  18. {
  19. var items = Categories == null || !Categories.Any()
  20. ? Enumerable.Empty<SelectListItem>()
  21. : Categories.Select(c => new SelectListItem
  22. {
  23. Value = c.Id.ToString(),Text = c.Name
  24. });
  25.  
  26. return new SelectList(items,"Value","Text");
  27. }
  28. }
  29. }

我的控制器:

  1. public class HomeController : Controller
  2. {
  3. private readonly Repository _repository = ObjectFactory.GetRepositoryInstance();
  4.  
  5. public ActionResult Index()
  6. {
  7. var model = new TestModel
  8. {
  9. Categories = _repository.Categories.Select(c => new CategoryModel
  10. {
  11. Id = c.Id,Name = c.Name
  12. })
  13. };
  14. return View(model);
  15. }
  16.  
  17. [HttpPost]
  18. public ActionResult Index(TestModel model)
  19. {
  20. if (ModelState.IsValid)
  21. {
  22. return RedirectToAction("Succes");
  23. }
  24.  
  25. model.Categories = _repository.Categories.Select(c => new CategoryModel
  26. {
  27. Id = c.Id,Name = c.Name
  28. });
  29. return View(model);
  30. }
  31.  
  32. public ActionResult Succes()
  33. {
  34. return View();
  35. }
  36. }

我想删除重复的类别抓取和映射,基本上这个代码

  1. .Categories = _repository.Categories.Select(c => new CategoryModel
  2. {
  3. Id = c.Id,Name = c.Name
  4. })

来自控制器.另外我想删除ModelState的有效性检查,只有当ModelState.IsValid保持控制器代码AS CLEAN AS POSSIBLE时,我想执行该操作.到目前为止,我有以下解决方案来删除ModelState有效性检查:

创建自定义ValidateModelAttribute

  1. public class ValidateModelAttribute : ActionFilterAttribute
  2. {
  3. public override void OnActionExecuting(ActionExecutingContext filterContext)
  4. {
  5. var viewData = filterContext.Controller.ViewData;
  6.  
  7. if(viewData.ModelState.IsValid) return;
  8.  
  9. viewData.Model = filterContext.ActionParameters["model"];
  10. filterContext.Result = new ViewResult
  11. {
  12. ViewData = viewData,};
  13. }
  14. }

现在模型在动作执行之前被验证.在验证错误的情况下,我们使用与最近发布的相同模型相同的视图.因此,控制器POST操作如下所示:

  1. [HttpPost]
  2. [ValidateModelAttribute]
  3. public ActionResult Index(TestModel model)
  4. {
  5. // Do some important stuff with posted data
  6. return RedirectToAction("Success");
  7. }

这是很好的,但现在我的TestModel的Categories属性是空的,因为我必须从数据库获取类别,并相应地映射它们.那么可以修改我的视图模型看起来像这样:

  1. public class TestModel
  2. {
  3. private readonly Repository _repository = ObjectFactory.GetRepositoryInstance();
  4.  
  5. ...
  6.  
  7. public int SelectedCategory { get; set; }
  8. public IEnumerable<CategoryModel> Categories {
  9. get
  10. {
  11. return _repository.Categories.Select(c => new CategoryModel
  12. {
  13. Id = c.Id,Name = c.Name
  14. });
  15. }
  16. }
  17.  
  18. ...
  19. }

这将使我们拥有非常干净的控制器,但不会导致某种性能或架构问题?观看模式不会违背单一责任原则吗? viewmodels应该负责获取所需的数据吗?

解决方法

没关系视图模型应主要由服务/查询甚至控制器填充的DTO.以前的版本没有问题,你的控制器只是几行代码.

但是您的存储库并不是一个存储库,它是一个ORM.一个适当的存储库(这里只是一些查询对象)将直接返回视图模型的类别列表.

关于你的自动验证属性,不要重新发明轮子,别人(在这种情况下我)做了before.

猜你在找的C#相关文章