Skip to content

Commit

Permalink
Paging & Refactoring Code with Bookings CRUD Implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
rahiyansafz committed Jun 25, 2022
1 parent 0b78deb commit f63e22e
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 10 deletions.
123 changes: 123 additions & 0 deletions Hotels.API/Controllers/BookingsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Hotels.DataAccess.Data;
using Hotels.Models.Models;

namespace Hotels.API.Controllers;

[Route("api/[controller]")]
[ApiController]
public class BookingsController : ControllerBase
{
private readonly DataContext _context;

public BookingsController(DataContext context)
{
_context = context;
}

// GET: api/Bookings
[HttpGet]
public async Task<ActionResult<IEnumerable<Booking>>> GetBookings()
{
if (_context.Bookings == null)
{
return NotFound();
}
return await _context.Bookings.ToListAsync();
}

// GET: api/Bookings/5
[HttpGet("{id}")]
public async Task<ActionResult<Booking>> GetBooking(int id)
{
if (_context.Bookings == null)
{
return NotFound();
}
var booking = await _context.Bookings.FindAsync(id);

if (booking == null)
{
return NotFound();
}

return booking;
}

// PUT: api/Bookings/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPut("{id}")]
public async Task<IActionResult> PutBooking(int id, Booking booking)
{
if (id != booking.Id)
{
return BadRequest();
}

_context.Entry(booking).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!BookingExists(id))
{
return NotFound();
}
else
{
throw;
}
}

return NoContent();
}

// POST: api/Bookings
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<Booking>> PostBooking(Booking booking)
{
if (_context.Bookings == null)
{
return Problem("Entity set 'DataContext.Bookings' is null.");
}
_context.Bookings.Add(booking);
await _context.SaveChangesAsync();

return CreatedAtAction("GetBooking", new { id = booking.Id }, booking);
}

// DELETE: api/Bookings/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteBooking(int id)
{
if (_context.Bookings == null)
{
return NotFound();
}
var booking = await _context.Bookings.FindAsync(id);
if (booking == null)
{
return NotFound();
}

_context.Bookings.Remove(booking);
await _context.SaveChangesAsync();

return NoContent();
}

private bool BookingExists(int id)
{
return (_context.Bookings?.Any(e => e.Id == id)).GetValueOrDefault();
}
}
2 changes: 1 addition & 1 deletion Hotels.API/Controllers/CitiesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using AutoMapper;
using Hotels.DataAccess.Contracts;
using Microsoft.AspNetCore.Authorization;
using Hotels.API.Exceptions;
using Hotels.Models.Exceptions;

namespace Hotels.API.Controllers;

Expand Down
2 changes: 1 addition & 1 deletion Hotels.API/Middlewares/ExceptionMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Hotels.API.Exceptions;
using Hotels.Models.Exceptions;
using Newtonsoft.Json;
using System.Net;

Expand Down
5 changes: 3 additions & 2 deletions Hotels.DataAccess/Contracts/ICitiesRepository.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Hotels.Models.Models;
using Hotels.Models.Dtos.City;
using Hotels.Models.Models;

namespace Hotels.DataAccess.Contracts;

public interface ICitiesRepository : IGenericRepository<City>
{
Task<City> GetDetails(int id);
Task<CityDto> GetDetails(int id);
}
11 changes: 10 additions & 1 deletion Hotels.DataAccess/Contracts/IGenericRepository.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
namespace Hotels.DataAccess.Contracts;
using Hotels.Models;
using Hotels.Models.Models.QueryResponse;
using Hotels.Models.Models.Response;

namespace Hotels.DataAccess.Contracts;

public interface IGenericRepository<T> where T : class
{
Task<T> GetAsync(int? id);
Task<TResult> GetAsync<TResult>(int? id);
Task<IEnumerable<T>> GetAllAsync();
Task<List<TResult>> GetAllAsync<TResult>();
Task<PagedResult<TResult>> GetAllAsync<TResult>(QueryParameters queryParameters);
Task<T> AddAsync(T entity);
Task<TResult> AddAsync<TSource, TResult>(TSource source);
Task DeleteAsync(int id);
Task UpdateAsync(T entity);
Task UpdateAsync<TSource>(int id, TSource source) where TSource : IBase;
Task<bool> Exists(int id);
}
18 changes: 15 additions & 3 deletions Hotels.DataAccess/Repository/CitiesRepository.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using Hotels.DataAccess.Contracts;
using Hotels.DataAccess.Data;
using Hotels.Models.Dtos.City;
using Hotels.Models.Exceptions;
using Hotels.Models.Models;
using Microsoft.EntityFrameworkCore;

Expand All @@ -16,9 +19,18 @@ public CitiesRepository(DataContext context, IMapper mapper) : base(context, map
_mapper = mapper;
}

public async Task<City> GetDetails(int id)
public async Task<CityDto> GetDetails(int id)
{
return await _context.Cities.Include(q => q.Hotels)
.FirstOrDefaultAsync(q => q.Id == id);
//return await _context.Cities.Include(q => q.Hotels)
// .FirstOrDefaultAsync(q => q.Id == id);

var city = await _context.Cities.Include(q => q.Hotels)
.ProjectTo<CityDto>(_mapper.ConfigurationProvider)
.FirstOrDefaultAsync(q => q.Id == id);

if (city is null)
throw new NotFoundException(nameof(GetDetails), id);

return city;
}
}
70 changes: 70 additions & 0 deletions Hotels.DataAccess/Repository/GenericRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
using Hotels.DataAccess.Contracts;
using Hotels.DataAccess.Data;
using Microsoft.EntityFrameworkCore;
using Hotels.Models.Models.Response;
using Hotels.Models.Models.QueryResponse;
using AutoMapper.QueryableExtensions;
using Hotels.Models;
using Hotels.Models.Exceptions;

namespace Hotels.DataAccess.Repository;

Expand All @@ -23,9 +28,23 @@ public async Task<T> AddAsync(T entity)
return entity;
}

public async Task<TResult> AddAsync<TSource, TResult>(TSource source)
{
var entity = _mapper.Map<T>(source);

await _context.AddAsync(entity);
await _context.SaveChangesAsync();

return _mapper.Map<TResult>(entity);
}

public async Task DeleteAsync(int id)
{
var entity = await GetAsync(id);

if (entity is null)
throw new NotFoundException(typeof(T).Name, id);

_context.Set<T>().Remove(entity);
await _context.SaveChangesAsync();
}
Expand All @@ -41,6 +60,31 @@ public async Task<IEnumerable<T>> GetAllAsync()
return await _context.Set<T>().ToListAsync();
}

public async Task<PagedResult<TResult>> GetAllAsync<TResult>(QueryParameters queryParameters)
{
var totalSize = await _context.Set<T>().CountAsync();
var items = await _context.Set<T>()
.Skip(queryParameters.StartIndex)
.Take(queryParameters.PageSize)
.ProjectTo<TResult>(_mapper.ConfigurationProvider)
.ToListAsync();

return new PagedResult<TResult>
{
Items = items,
PageNumber = queryParameters.PageNumber,
RecordNumber = queryParameters.PageSize,
TotalCount = totalSize
};
}

public async Task<List<TResult>> GetAllAsync<TResult>()
{
return await _context.Set<T>()
.ProjectTo<TResult>(_mapper.ConfigurationProvider)
.ToListAsync();
}

public async Task<T> GetAsync(int? id)
{
if (id is null)
Expand All @@ -49,9 +93,35 @@ public async Task<T> GetAsync(int? id)
return await _context.Set<T>().FindAsync(id);
}

public async Task<TResult> GetAsync<TResult>(int? id)
{
var result = await _context.Set<T>().FindAsync(id);
if (result is null)
throw new NotFoundException(typeof(T).Name, id.HasValue ? id : "No Key Provided");

return _mapper.Map<TResult>(result);
}

public async Task UpdateAsync(T entity)
{
_context.Update(entity);
await _context.SaveChangesAsync();
}

public async Task UpdateAsync<TSource>(int id, TSource source) where TSource : IBase
{
if (id != source.Id)
{
throw new BadRequestException("Invalid Id used in request");
}

var entity = await GetAsync(id);

if (entity is null)
throw new NotFoundException(typeof(T).Name, id);

_mapper.Map(source, entity);
_context.Update(entity);
await _context.SaveChangesAsync();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Hotels.API.Exceptions;
namespace Hotels.Models.Exceptions;

public class BadRequestException : ApplicationException
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Hotels.API.Exceptions;
namespace Hotels.Models.Exceptions;

public class NotFoundException : ApplicationException
{
Expand Down
6 changes: 6 additions & 0 deletions Hotels.Models/IBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Hotels.Models;

public interface IBase
{
int Id { get; set; }
}

0 comments on commit f63e22e

Please sign in to comment.