Создание сайта-блога. Часть 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 канале.