Создание сайта-блога. Часть 2.
!!НАШ БЛОГ ПЕРЕЕХАЛ!!
Мы создали свой сайт! Все материалы, опубликованные в этом блоге, переехали туда.
Наш новый сайт maddevelop.ru
Контроллер отображения постов
Контроллер BlogController выбирает из базы данных посты и передаёт их представлению для визуализации. На уровне класса у него есть переменные:
private IPostRepository postRepository; private PostsListViewModel model = new PostsListViewModel(); private int pageSize = 3;
В переменную postRepository будет записываться экземпляр класса нашего хранилища. Как было сказано в первой части, из-за использования Ninject при этом будет создаваться класс EFBlogRepository.
В представление мы будем передавать не только список постов, но и множество другой информации. Для этого необходимо отсылать вспомогательный класс:
public class PostsListViewModel { public IEnumerable<Post> Posts { get; set; } public IEnumerable<string> CategoryNames { get; set; } public IEnumerable<string> TagNames { get; set; } public PagingInfo PagingInfo { get; set; } public string CurrentCategory { get; set; } public string CurrentTag { get; set; } public string CurrentAuthor { get; set; } public Post FullPost { get; set; } }
Он содержит кроме списка постов (IEnumerable<Post> Posts) список названий категорий (IEnumerable<string> CategoryNames), список названий тегов (IEnumerable<string> TagNames), информацию о разбиении на страницы (PagingInfo PagingInfo), название текущей категории (string CurrentCategory), название выбранного тега (string CurrentTag), имя выбранного автора (string CurrentAuthor) и класс выбранного для чтения поста (Post FullPost).
Класс для пагинации (разбиения на страницы) содержит свойства:
public class PagingInfo { public int TotalItems { get; set; } // Общее количество постов public int ItemsPerPage { get; set; } // Количество товаров на одной странице public int CurrentPage { get; set; } // Номер текущей страницы public int TotalPages // Количество страниц { get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); } } }
Для удобства проверки работы пагинации отображаем на одной странице три поста: pageSize = 3.
В конструкторе контроллера сразу определяем из базы данных списки названий тегов и категорий:
public BlogController(IPostRepository repoPost) { postRepository = repoPost; model.CategoryNames = postRepository.Categories.Select(cat => cat.Name); model.TagNames = postRepository.Tags.Select(tag => tag.Name); }
После этого приступаем к созданию метода действия, который возвращает класс ViewResult. Этот класс производит рендеринг представления в веб-страницу и возвращает ее в виде ответа клиенту.
public ViewResult List(string category, int page = 1) { model = new PostsListViewModel { Posts = postRepository.Posts .Where(p => category == null || p.Category.Name == category) .OrderByDescending(v => v.Date) .Skip((page - 1) * pageSize) .Take(pageSize), PagingInfo = new PagingInfo { CurrentPage = page, ItemsPerPage = pageSize, TotalItems = category == null ? postRepository.Posts.Count() : postRepository.Posts.Where(q => q.Category.Name == category).Count() }, CurrentCategory = category }; return View(model); }
Класс возвращается с параметром, моделью представления. Для отображения списка постов нет надобности определять все его свойства, достаточно лишь задать свойства Posts и PagingInfo.
Метод List имеет два параметра: string category и int page = 1. Второй, как видим, является параметром со значением по умолчанию. Метод List используется не только для предоставления информации при первой загрузке сайта, но и при выборе какой-либо категории. Для второго случая в методе определяется свойство CurrentCategory.
Для выборки постов по тегам и авторам используются два метода действия:
public ViewResult TagList(string tag, int page = 1) { model = new PostsListViewModel { Posts = postRepository.Posts .Where(p => tag == null || p.Tags.Select(v => v.Name).Contains(quot;#{tag}")) .OrderByDescending(v => v.Date) .Skip((page - 1) * pageSize) .Take(pageSize), PagingInfo = new PagingInfo { CurrentPage = page, ItemsPerPage = pageSize, TotalItems = tag == null ? postRepository.Posts.Count() : postRepository.Posts.Count(p => p.Tags.Select(v => v.Name).Contains(quot;#{tag}")) }, CurrentTag = tag }; return View("List",model); } public ViewResult AuthorList(string author, int page = 1) { model = new PostsListViewModel { Posts = postRepository.Posts .Where(p => p.Author == author) .OrderByDescending(v => v.Date) .Skip((page - 1) * pageSize) .Take(pageSize), PagingInfo = new PagingInfo { CurrentPage = page, ItemsPerPage = pageSize, TotalItems = postRepository.Posts.Count(p => p.Author == author) }, CurrentAuthor = author }; return View("List", model); }
Они не сильно отличаются от метода действия List(): есть соответствующие изменения в фильтрации, появляются определения свойств CurrentAuthor и CurrentTag. Так как названия этих методов отличаются от названия страницы представления List, то оно явно указывается в возвращаемом методе View("List", model).
Последний метод подготавливает данные для показа полного текста поста:
public ViewResult FullPost(int id) { model = new PostsListViewModel { Posts = new List<Post> {postRepository.Posts.SingleOrDefault(x => x.Id == id)}, PagingInfo = new PagingInfo {CurrentPage = 1, ItemsPerPage = 1, TotalItems = 1}, FullPost = postRepository.Posts.SingleOrDefault(x => x.Id == id) }; return View("List", model); }
Его параметром является идентификатор поста, на основании которого происходит его поиск в базе данных.
Ещё больше интересной информации на нашем Telegram канале.