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

假设我有复杂的视图模型,有很多数据,如国家/地区,产品,类别等的列表,我每次创建viewmodel时都需要从数据库获取数据.

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

我的模型和视图模型:

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

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }

    public IEnumerable<Category> SubCategories { get; set; }
}

查看型号:

public class CategoryModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class TestModel
{
    [required]
    [MaxLength(5)]
    public string Text { get; set; }

    public int SelectedCategory { get; set; }
    public IEnumerable<CategoryModel> Categories { get; set; }
    public SelectList CategoriesList
    {
        get
        {
            var items = Categories == null || !Categories.Any() 
                ? Enumerable.Empty<SelectListItem>()
                : Categories.Select(c => new SelectListItem
                {
                    Value = c.Id.ToString(),Text = c.Name
                });

            return new SelectList(items,"Value","Text");
        }
    }
}

我的控制器:

public class HomeController : Controller
{
    private readonly Repository _repository = ObjectFactory.GetRepositoryInstance();

    public ActionResult Index()
    {
        var model = new TestModel
        {
            Categories = _repository.Categories.Select(c => new CategoryModel
            {
                Id = c.Id,Name = c.Name
            })
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(TestModel model)
    {
        if (ModelState.IsValid)
        {
            return RedirectToAction("Succes");
        }

        model.Categories = _repository.Categories.Select(c => new CategoryModel
        {
            Id = c.Id,Name = c.Name
        });
        return View(model);
    }

    public ActionResult Succes()
    {
        return View();
    }
}

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

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

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

创建自定义Validatemodelattribute

public class Validatemodelattribute : ActionFilterattribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var viewData = filterContext.Controller.ViewData;

        if(viewData.ModelState.IsValid) return;

        viewData.Model = filterContext.ActionParameters["model"];
        filterContext.Result = new ViewResult
        {
            ViewData = viewData,};
     }
 }

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

[HttpPost]
[Validatemodelattribute]
public ActionResult Index(TestModel model)
{
    // Do some important stuff with posted data
    return RedirectToAction("Success");
}

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

public class TestModel
{
    private readonly Repository _repository = ObjectFactory.GetRepositoryInstance();

    ...

    public int SelectedCategory { get; set; }
    public IEnumerable<CategoryModel> Categories {
        get
        {
            return _repository.Categories.Select(c => new CategoryModel
            {
                Id = c.Id,Name = c.Name
            });
        }
    }

    ...
}

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

解决方法

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

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

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

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...