Automapper could use user defined mapping profile or built-in mapping. It mapped from the entites(source) to models(desitination).
Code
MovieDetailResponseModel has two inner class CastResponseModel and GenreResponseModel. The MDRM(MovieDetailResponseModel) has two List property Casts and Genres. We have to define the rules for mapping from Movie Entity’s MovieCast(which has the many-to-many relationship) to MDRM’ Casts. Therefore, we need a method called:
static List GetCasts(IEnumerable srcMovieCasts)```;
By using this method, we can pass Movie Entity's MovieCast list to this method, then we had a source(rule) for mapped MDRM's member casts.
MovieDetailResponseModel:
```c# public class MovieDetailResponseModel { public int Id { get; set; } public string Title { get; set; } public string Overview { get; set; } public IEnumerable<MovieCast> MovieCasts { get; set; } public IEnumerable<CastResponseModel> Casts { get; set; } public IEnumerable<GenreResponseModel> Genres { get; set; } public class CastResponseModel { public int Id { get; set; } public string Name { get; set; } public string Gender { get; set; } public string TmdbUrl { get; set; } public string ProfilePath { get; set; } public string Character { get; set; } } public class GenreResponseModel { public int Id { get; set; } public string Name { get; set; } } }
Movie Entity class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
publicclassMovie { publicint Id { get; set; } publicstring Title { get; set; } publicstring Overview { get; set; } public ICollection<Trailer> Trailers { get; set; } public ICollection<Review> Reviews { get; set; } public ICollection<MovieCast> MovieCasts { get; set; } public ICollection<MovieGenre> MovieGenres { get; set; } public ICollection<MovieCrew> MovieCrews { get; set; } public ICollection<Purchase> Purchases { get; set; } public ICollection<Favorite> Favorites { get; set; } }
GetCasts Method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
privatestatic List<MovieDetailResponseModel.CastResponseModel> GetCasts(IEnumerable<MovieCast> srcMovieCasts) { var movieCast = new List<MovieDetailsResponseModel.CastResponseModel>(); foreach (var cast in srcMovieCasts) movieCast.Add(new MovieDetailsResponseModel.CastResponseModel { Id = cast.CastId, Gender = cast.Cast.Gender, Name = cast.Cast.Name, ProfilePath = cast.Cast.ProfilePath, TmdbUrl = cast.Cast.TmdbUrl, Character = cast.Character });
return movieCast; }
In the same way, we can configure MDRM’s genres.
Since we have the same property name between MDRM and Movie Entity, we can simply use built-in method:
1 2
CreateMap<Movie, MovieDetailsResponseModel>() // only for the same simple property
Now, we put it together as a MappingProfile class:
return movieCast; } privatestatic List<MovieDetailResponseModel.GenreResponseModel> GetGenres(IEnumerable<MovieGenre> srcMovieGenres) { var movieGenres = new List<MovieDetailResponseModel.GenreResponseModel>(); foreach (var genre in srcMovieGenres) movieGenres.Add(new MovieDetailResponseModel.GenreResponseModel { Id = genre.GenreId, Name = genre.Genre.Name, });
return movieGenres; } }
Define paginated list inhered from List, having the property PageIndex (The page number) ,TotalPages (Count/pageSize), TotalCount(total item count), this one is not necessary becuase the count is accessible from List.Count Therefore, in order to get the next page, you need to send the next pageIndex to controller(PageIndex + 1). The page size is set to 30 by default. The page size is option parameter for controller. The GetPaged method is a static method to get paged list by skipping the number of page number.
publicstaticasync Task<PaginatedList<T>> GetPaged( IQueryable<T> source, int pageIndex, int pageSize, Func<IQueryable<T>, IOrderedQueryable<T>> orderedQuery = null, Expression<Func<T, bool>> filter = null, params Expression<Func<T, object>>[] includes) { // source query which implemented IQuerable var query = source; // A expression tree accepts a lambda expression if (filter != null) query = query.Where(filter); // orderedQuery is a delegate that accept a IQueryable as parameter and outputs IOrderedQueryable. // In this example, query is a parameter, executes the lambda expression function // orderQuery = rev => rev.OrderByDescending(r => r.Rating) if (orderedQuery != null) query = orderedQuery(query); //Assign Lambda expressions Includes to Expression Tree if (includes != null) foreach (Expression<Func<T, object>> navigationProperty in includes) query = query.Include(navigationProperty);
Every Repository should implement the GetPagedData method, which is simply invoke the PaginatedList’s static method with parameters, page, pageSize, orderedQuery, filter, includes.
if (!string.IsNullOrEmpty(title)) filterExpression = movie => title != null && movie.Title.Contains(title); if the title is not null or empty, assigned Expression<Func<T, bool>> filter = null with filterExpression.
For the example,_reviewRepository.GetPagedData(1, 25, rev => rev.OrderByDescending(r => r.Rating), filterExpression, review => review.Movie);review => review.Movie is a Include expression tree having delegate Func<T,object> to let DbSet\<Review\>().Include(Func<T,object>).
See C# Core I: LINQ for definition of ExpressionTree
publicasync Task<PagedResultSet<MovieResponseModel>> GetMoviesByPagination( int pageSize = 20, int pageIndex = 0, string title = "") { Expression<Func<Movie, bool>> filterExpression = null; if (!string.IsNullOrEmpty(title)) filterExpression = movie => title != null && movie.Title.Contains(title);
var pagedMovies = await _movieRepository.GetPagedData(pageIndex, pageSize, mov => mov.OrderBy(m => m.Title), filterExpression); var movies = new PagedResultSet<MovieResponseModel>(_mapper.Map<List<MovieResponseModel>>(pagedMovies), pagedMovies.PageIndex, pageSize, pagedMovies.TotalCount); return movies; }
publicasync Task<PagedResultSet<MovieResponseModel>> GetAllMoviePurchasesByPagination(int pageSize = 50, int page = 0) { var totalPurchases = await _purchaseRepository.GetCountAsync(); var purchases = await _purchaseRepository.GetAllPurchases(pageSize, page);
var data = _mapper.Map<List<MovieResponseModel>>(purchases); var purchasedMovies = new PagedResultSet<MovieResponseModel>(data, page, pageSize, totalPurchases); return purchasedMovies; }
publicasync Task<PaginatedList<MovieResponseModel>> GetMoviesByGenre(int genreId, int pageSize = 30, int page = 1) { var pagedMovies = await _movieRepository.GetMoviesByGenre(genreId, pageSize, page); var data = _mapper.Map<PaginatedList<MovieResponseModel>>(pagedMovies); var movies = new PaginatedList<MovieResponseModel>(data, pagedMovies.TotalCount, page, pageSize); return movies; }
publicasync Task<MovieDetailsResponseModel> GetMovieAsync(int id) { var movie = await _movieRepository.GetByIdAsync(id); if (movie == null) thrownew NotFoundException("Movie", id); var favoritesCount = await _favoriteRepository.GetCountAsync(f => f.MovieId == id); var response = _mapper.Map<MovieDetailsResponseModel>(movie); response.FavoritesCount = favoritesCount; return response; }