加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 18:01:44 所属栏目:百科 来源:网络整理
导读:假设我有复杂的视图模型,有很多数据,如国家/地区,产品,类别等的列表,我每次创建ViewModel时都需要从数据库中获取数据. 我想要解决的主要问题是,当我处理POST操作时,一些TestModel发布的值不正确,导致ModelState.IsValid为false,那么我必须返回与当前发布的模
假设我有复杂的视图模型,有很多数据,如国家/地区,产品,类别等的列表,我每次创建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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读