简体   繁体   English

ASP.NET MVC设计

[英]ASP.NET MVC design

As I've stated before I'm working on a digg clone to teach myself ASP.NET MVC Inside and out but I've hit a road bump that I can't seem to avoid. 正如我之前所说的那样,我正在研究一个Digg克隆以自学ASP.NET MVC,但是我遇到了我似乎无法避免的障碍。

I want to be able to optimize this application as much as possible so I have my DAL which is a bunch of classes of ...Repository : Repository. 我希望能够尽可能地优化此应用程序,因此我有了DAL,它是... Repository:Repository的一类。 Now to help optimize for performance I have my base repository classes return my ViewData objects so that they can select extra fields needed without having to create an anonymous type. 现在,为了帮助优化性能,我让基本存储库类返回了ViewData对象,以便它们可以选择所需的其他字段,而不必创建匿名类型。

Stories have Users who have created them and Users have Votes for Stories. 故事包含创建故事的用户,而用户具有故事投票权。 Pretty easy DB layout. 非常简单的数据库布局。 Now I handle my own membership because the default ASP.NET membership is so bloated. 现在,我处理我自己的成员资格,因为默认的ASP.NET成员资格so肿。 In my view for the list of stories I have to determine if the current user has voted on the story being rendered. 在我的故事列表中,我必须确定当前用户是否对正在呈现的故事进行了投票。 Now since I figured data access in the View shouldn't be happening it should be in either my controller or my DAL. 现在,由于我认为不应进行View中的数据访问,因此应该在我的控制器或DAL中。 Since I'm already returning ViewData from my DAL i added another property on the StoryViewData type named "UserVotedOn" that returns true if the user has voted on that story. 由于我已经从DAL返回了ViewData,因此我在StoryViewData类型上添加了另一个名为“ UserVotedOn”的属性,如果用户对该故事进行了投票,该属性将返回true。

Problem with this is I have to either A) make the DAL aware of membership or B) pass in the User ID into the query methods on the DAL. 问题是我必须要么A)使DAL了解成员身份,要么B)将用户ID传递到DAL的查询方法中。 Neither of these feel right to me and I'm looking for some good solutions. 这些都不适合我,我正在寻找一些好的解决方案。 Any feedback is welcome. 欢迎任何反馈。

In my MVC apps I'm using architecture that Rob Conery showed on his MVC Storefront video series and it works like charm for me. 在我的MVC应用程序中,我使用的是Rob Conery在其MVC Storefront视频系列中展示的体系结构,它对我来说就像是魅​​力。

Repository => Service + Filters => Controller => View 仓库=>服务+筛选器=>控制器=>视图

I've tried to simulate what you want to achieve and managed todo like this 我试图模拟您想要实现的目标并设法做到这一点

Edit1 : Changed IList to IQueryable in repository and filters Edit1 :在存储库和过滤器中将 IList更改为IQueryable

Repository 知识库

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

Service for getting what you want 获得您想要的服务

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();
    }
}

Filters to filter your stories and user votes (These are basically extension methods). 用于过滤您的故事和用户投票的过滤器(这些基本上是扩展方法)。 Not the nicest implementation out there, but you can rewrite later 这不是最好的实现,但是您以后可以重写

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;
    }
}

And then you can pass current UserID in controller, not in DAL or View like you had to do before 然后您可以在控制器中传递当前的UserID,而不是像以前一样在DAL或View中传递

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);
    }
}

This allows you to stay away from adding user related UserVotedOn property to your Story model 这使您可以避免将与用户相关的UserVotedOn属性添加到您的Story模型中

It looks like you're missing the BLL. 看来您缺少BLL。

Actually, the right architecture of an MVC application is what many people still trying to figure out. 实际上,许多人仍在试图找出MVC应用程序的正确架构。

I personally consider UserID to be somewhat a translayer concept. 我个人认为UserID有点跨层概念。 It will appear on both DAL and BLL levels. 它会同时出现在DAL和BLL级别上。

Basically, your controller method should have just a few very basic calls to the BLL, only to determine how to react to user input, whether to return on view or another. 基本上,您的控制器方法应该只对BLL进行一些非常基本的调用,仅用于确定如何对用户输入做出反应,返回视图还是其他。

Your view should only deal with model objects. 您的视图应仅处理模型对象。 A model should probably be filled by the business logic. 模型可能应该由业务逻辑填充。 You could call BL methods in a controller method in order to initialize you model object and then pass it to the view. 您可以在控制器方法中调用BL方法,以初始化模型对象,然后将其传递给视图。

Controller should not communicate directly with the database. 控制器不应直接与数据库通信。 Neither should it probably deal with low level objects which comprise your domain objects and models. 它也不应该处理组成您的域对象和模型的低级对象。

PS i would try to avoid extensive use of ViewData. PS我会尽量避免大量使用ViewData。 Strongly-typed model classes are a much better option. 强类型模型类是更好的选择。 You can also group them in hierarchies to inherit some common properties. 您还可以将它们分组在层次结构中以继承一些公共属性。 Just like your domain model classes could derive from a base class that has a UserID property defined. 就像您的域模型类可以从定义了UserID属性的基类派生一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM