ASP.NET MVC дизайн - PullRequest
       8

ASP.NET MVC дизайн

2 голосов
/ 09 февраля 2009

Как я уже говорил ранее, я работаю над клоном digg, чтобы научить себя ASP.NET MVC Внутри и снаружи, но я столкнулся с дорожным ударом, которого, похоже, не могу избежать.

Я хочу максимально оптимизировать это приложение, поэтому у меня есть DAL, представляющий собой набор классов ... Repository: Repository. Теперь, чтобы помочь оптимизировать производительность, мои базовые классы репозитория возвращают мои объекты ViewData, чтобы они могли выбирать дополнительные поля, не создавая анонимный тип.

Истории имеют пользователей, которые их создали, и пользователи имеют голоса за истории. Довольно простой макет БД. Теперь я обрабатываю свое собственное членство, потому что членство в ASP.NET по умолчанию является настолько раздутым. По моему мнению, для списка историй я должен определить, проголосовал ли текущий пользователь за воспроизводимую историю. Теперь, поскольку я полагал, что доступ к данным в представлении не должен происходить, он должен быть либо в моем контроллере, либо в моем DAL. Поскольку я уже возвращаю ViewData из моего DAL, я добавил еще одно свойство типа StoryViewData с именем «UserVotedOn», которое возвращает значение true, если пользователь проголосовал по этой истории.

Проблема в том, что я должен либо A) уведомить DAL о членстве, либо B) передать идентификатор пользователя в методы запроса DAL. Ни один из них не подходит мне, и я ищу хорошие решения. Любые отзывы приветствуются.

Ответы [ 2 ]

3 голосов
/ 10 февраля 2009

В своих приложениях MVC я использую архитектуру, которую Роб Конери показал в своей серии видеороликов MVC Storefront, и она работает для меня просто очаровательно.

Репозиторий => Сервис + Фильтры => Контроллер => Вид

Я пытался смоделировать то, чего вы хотите достичь, и сумел сделать вот так

Edit1 : изменен 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;
    }
}

И тогда вы можете передать текущий идентификатор пользователя в контроллер, а не в 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);
    }
}

Это позволяет избежать добавления пользовательского свойства UserVotedOn в модель Story

1 голос
/ 09 февраля 2009

Похоже, вам не хватает BLL.

На самом деле, правильная архитектура приложения MVC - это то, что многие люди все еще пытаются выяснить.

Лично я считаю, что UserID является концепцией трансслоя. Он появится на уровнях DAL и BLL.

По сути, ваш метод контроллера должен иметь всего несколько очень простых вызовов BLL, только чтобы определить, как реагировать на пользовательский ввод, возвращаться ли при просмотре или другом.

Ваш вид должен иметь дело только с модельными объектами. Модель, вероятно, должна быть заполнена бизнес-логикой. Вы можете вызвать методы BL в методе контроллера, чтобы инициализировать объект модели и затем передать его представлению.

Контроллер не должен связываться напрямую с базой данных. Также он не должен иметь дело с объектами низкого уровня, которые включают ваши доменные объекты и модели.

P.S. Я хотел бы попытаться избежать широкого использования ViewData. Строго типизированные классы моделей являются гораздо лучшим вариантом. Вы также можете сгруппировать их в иерархии, чтобы наследовать некоторые общие свойства. Так же, как классы модели вашего домена могут быть производными от базового класса, для которого определено свойство UserID.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...