代码之家  ›  专栏  ›  技术社区  ›  Chad Moran

ASP.NET MVC设计

  •  2
  • Chad Moran  · 技术社区  · 15 年前

    正如我之前所说的,我正在研究一个digg克隆来自学ASP.NET MVC的内部和外部,但我遇到了一个我似乎无法避免的路障。

    我希望能够尽可能地优化这个应用程序,这样我就有了DAL,它是一组……知识库:知识库类。现在,为了帮助优化性能,我让我的基本存储库类返回我的ViewData对象,以便它们可以选择所需的额外字段,而不必创建匿名类型。

    故事有创建故事的用户,用户对故事有投票权。非常简单的数据库布局。现在,我处理自己的成员身份,因为默认的ASP.NET成员身份过于膨胀。在我的视图中,对于故事列表,我必须确定当前用户是否对正在呈现的故事投票。既然我认为视图中的数据访问不应该发生,那么它应该在我的控制器或DAL中。因为我已经从DAL中返回了viewdata,所以我在story viewdata类型中添加了另一个名为“user voted on”的属性,如果用户对该故事进行了投票,它将返回true。

    问题是,我必须要么a)让DAL知道成员身份,要么b)将用户ID传递到DAL上的查询方法中。这些对我来说都不合适,我正在寻找一些好的解决方案。欢迎任何反馈。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Paul G.    15 年前

    在我的MVC应用程序中,我使用的是Rob Conery在其MVC店面视频系列中展示的架构,它对我来说就像魅力一样。

    存储库=>服务+筛选器=>控制器=>视图

    我试着模拟你想要达到的目标,然后像这样做

    编辑1 :在存储库和筛选器中将ilist更改为iqueryable

    知识库

    public interface IRepository
    {
        IQueryable<Vote> GetVotes();
        IQueryable<Story> GetStories();
    }
    

    获取您想要的服务

    public class Service : IService
    {
        private IRepository _repository;
    
        public Service(IRepository repository)
        {
            _repository = repository;
            if (_repository == null) throw new InvalidOperationException("Repository cannot be null");
        }
        public IList<Vote> GetUserVotes(int userID)
        {
            return _repository.GetVotes().WithUserID(userID).ToList();
        }
        public IList<Story> GetNotVotedStories(IList<Vote> votes)
        {
            return _repository.GetStories().WithoutVotes(votes).ToList();
        }
    }
    

    过滤您的故事和用户投票的过滤器(这些基本上是扩展方法)。不是最好的实现,但是您可以稍后重写

    public static class Filters
    {
        public static IQueryable<Vote> WithUserID(this IQueryable <Vote> qry, int userID)
        {
            return from c in qry
                   where c.UserID == userID
                   select c;
        }
        public static IQueryable<Story> WithoutVotes(this IQueryable <Story> qry, IList <Vote> votes)
        {
            return  from c in qry
                    where votes.Where(x => x.StoryID == c.StoryID).ToList().Count > 0
                    select c;
        }
    }
    

    然后你可以在控制器中传递当前的用户ID,而不是像以前那样在DAL或视图中传递。

    public class HomeController : Controller
    {
        private readonly IRepository _repository;
        private readonly IService _service;
    
        public HomeController()
        {
            _repository = new Repository();
            _service = new Service.Service(_repository);
        }
    
        public ActionResult Index()
        {
            var userVotes = _service.GetUserVotes(CurrentUserID);
            var unvotedStories = _service.GetNotVotedStories(userVotes);
    
            return View(unvotedStories);
        }
    }
    

    这允许您远离将与用户相关的uservotedon属性添加到您的故事模型中。

        2
  •  1
  •   User    15 年前

    你好像错过了BLL。

    事实上,MVC应用程序的正确体系结构正是许多人仍在努力解决的问题。

    我个人认为userid有点像是一个跨层的概念。它将同时出现在DAL和BLL级别。

    基本上,您的控制器方法应该只对BLL进行一些非常基本的调用,只是为了确定如何对用户输入做出反应,是返回视图还是其他视图。

    您的视图应该只处理模型对象。模型应该由业务逻辑填充。可以在控制器方法中调用bl方法,以便初始化模型对象,然后将其传递给视图。

    控制器不应直接与数据库通信。它也不应该处理包含域对象和模型的低级对象。

    另外,我会尽量避免大量使用viewdata。强类型模型类是更好的选择。您还可以将它们分组在层次结构中以继承一些公共属性。就像域模型类可以从定义了userid属性的基类派生一样。