From a83e1b38a23a8f396379668ee59da3b4d701c70b Mon Sep 17 00:00:00 2001 From: Souvik Mazumder Date: Wed, 1 Dec 2021 12:02:29 -0500 Subject: [PATCH] Added CRUD APIs for Encyclopedia Controller --- .../Controllers/EncylopediaController.cs | 144 +++++++++++++++++- .../DataAccess/MainDataAccess.cs | 122 ++++++++++++--- .../Exceptions/DeleteFailedException.cs | 19 +++ .../Exceptions/UpdateFailedException.cs | 19 +++ .../Interfaces/IMainDataAccess.cs | 15 +- .../Library.Encyclopedia.Entity.csproj | 4 + .../Models/External/MainMinimizedExternal.cs | 9 +- .../Models/External/MainUpdateModel.cs | 9 ++ .../Models/External/QueryExternalModel.cs | 2 - Library.Encyclopedia.Entity/Models/Main.cs | 24 ++- 10 files changed, 332 insertions(+), 35 deletions(-) create mode 100644 Library.Encyclopedia.Entity/Exceptions/DeleteFailedException.cs create mode 100644 Library.Encyclopedia.Entity/Exceptions/UpdateFailedException.cs create mode 100644 Library.Encyclopedia.Entity/Models/External/MainUpdateModel.cs diff --git a/Library.Encyclopedia.API/Controllers/EncylopediaController.cs b/Library.Encyclopedia.API/Controllers/EncylopediaController.cs index 13da0b8..31c1445 100644 --- a/Library.Encyclopedia.API/Controllers/EncylopediaController.cs +++ b/Library.Encyclopedia.API/Controllers/EncylopediaController.cs @@ -1,6 +1,7 @@ using Library.Encyclopedia.DataAccess; using Library.Encyclopedia.DataAccess.DataAccess; using Library.Encyclopedia.Entity.Interfaces; +using Library.Encyclopedia.Entity.Models; using Library.Encyclopedia.Entity.Models.External; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; @@ -65,24 +66,119 @@ public async Task Get(string query, } } + /// + /// Get all items based on category + /// + /// + /// + /// + /// + /// + [HttpGet("category")] + public async Task GetByCategory(string category, + int offset = 0, + int size = 10, + bool asc = true) + { + try + { + var response = await mainDataAccess.GetByCategoryAsync(category, offset, size, asc); + + if (response == null) + { + return StatusCode(204); + } + else + { + return Ok(response); + } + } + catch (Exception ex) + { + _logger.LogError(ex, $"an error has occured {ex.Message}"); + throw; + } + } + + /// + /// Get all items based on starting alphabet + /// + /// + /// + /// + /// + /// + [HttpGet("alphabet")] + public async Task GetByStartingAlphabet(char alphabet, + int offset = 0, + int size = 10, + bool asc = true) + { + try + { + var response = await mainDataAccess.GetByAlphabetAsync(alphabet, offset, size, asc); + + if (response == null) + { + return StatusCode(204); + } + else + { + return Ok(response); + } + } + catch (Exception ex) + { + _logger.LogError(ex, $"an error has occured {ex.Message}"); + throw; + } + } + + /// + /// Get an entry by id + /// + /// + [HttpGet("{id}")] + public async Task Get(Guid id) + { + try + { + var response = await mainDataAccess.GetAsync(id); + + if (response == null) + { + return StatusCode(204); + } + else + { + return Ok(response); + } + } + catch (Exception ex) + { + _logger.LogError(ex, $"an error has occured {ex.Message}"); + throw; + } + } + /// /// Create new entry /// /// [HttpPost] - public async Task Create() + public async Task Create([FromBody]Main model) { try { - var response = await mainDataAccess.CreateAsync(null); + var response = await mainDataAccess.CreateAsync(model); if (response == null) { - return StatusCode(204); + return StatusCode(500); } else { - return Ok(); + return Ok(response); } } catch (Exception ex) @@ -91,5 +187,45 @@ public async Task Create() throw; } } + + /// + /// Create new entry + /// + /// + [HttpPut("{id}")] + public async Task Update(Guid id, [FromBody]MainUpdateModel model) + { + try + { + await mainDataAccess.UpdateAsync(id, model); + + return Ok(); + } + catch (Exception ex) + { + _logger.LogError(ex, $"an error has occured {ex.Message}"); + throw; + } + } + + /// + /// Create new entry + /// + /// + [HttpDelete("{id}")] + public async Task Delete(Guid id) + { + try + { + await mainDataAccess.DeleteAsync(id); + + return Ok(); + } + catch (Exception ex) + { + _logger.LogError(ex, $"an error has occured {ex.Message}"); + throw; + } + } } } \ No newline at end of file diff --git a/Library.Encyclopedia.DataAccess/DataAccess/MainDataAccess.cs b/Library.Encyclopedia.DataAccess/DataAccess/MainDataAccess.cs index 4a427ff..993de8c 100644 --- a/Library.Encyclopedia.DataAccess/DataAccess/MainDataAccess.cs +++ b/Library.Encyclopedia.DataAccess/DataAccess/MainDataAccess.cs @@ -1,4 +1,5 @@ -using Library.Encyclopedia.Entity.Interfaces; +using Library.Encyclopedia.Entity.Exceptions; +using Library.Encyclopedia.Entity.Interfaces; using Library.Encyclopedia.Entity.Models; using Library.Encyclopedia.Entity.Models.External; using Microsoft.EntityFrameworkCore; @@ -18,44 +19,125 @@ public MainDataAccess(IApplicationDbContext dbcontext) _dbcontext = dbcontext; } - - #region GET async Task IMainDataAccess.GetAsync(string query, int offset, int pagesize, bool ascending) { - var data = await _dbcontext.Main.Where(s => s.Description.Contains(query) || s.Title.Contains(query)) + var temp = _dbcontext.Main.Where(s => s.Description.Contains(query) || s.Title.Contains(query)) .Skip(offset) - .Take(pagesize) - .OrderBy(s => s.Title) - .ThenBy(s => s.Description) - .ToListAsync(); - - MainMinimizedExternalCollection result = new MainMinimizedExternalCollection(data, ) + .Take(pagesize); + + IEnumerable
data; + if (ascending) + data = await temp.OrderBy(s => s.Title) + .ThenBy(s => s.Description) + .ToListAsync(); + else + data = await temp.OrderByDescending(s => s.Title) + .ThenByDescending(s => s.Description) + .ToListAsync(); + + var total = await _dbcontext.Main.CountAsync(s => s.Description.Contains(query) || s.Title.Contains(query)); + + MainMinimizedExternalCollection result = new MainMinimizedExternalCollection(data.Minimize(), total); + + return result; } - Task
IMainDataAccess.GetAsync(string id) + async Task IMainDataAccess.GetByCategoryAsync(string category, int offset, int pagesize, bool ascending) { - throw new NotImplementedException(); + var temp = _dbcontext.Main.Where(s => s.Category.Equals(category, StringComparison.OrdinalIgnoreCase)) + .Skip(offset) + .Take(pagesize); + + IEnumerable
data; + if (ascending) + data = await temp.OrderBy(s => s.Title) + .ThenBy(s => s.Description) + .ToListAsync(); + else + data = await temp.OrderByDescending(s => s.Title) + .ThenByDescending(s => s.Description) + .ToListAsync(); + + var total = await _dbcontext.Main.CountAsync(s => s.Category.Equals(category, StringComparison.OrdinalIgnoreCase)); + + MainMinimizedExternalCollection result = new MainMinimizedExternalCollection(data.Minimize(), total); + + return result; } - Task> IMainDataAccess.GetAsync(char startingAlphabet) + async Task IMainDataAccess.GetByAlphabetAsync(char startingAlphabet, int offset, int pagesize, bool ascending) { - throw new NotImplementedException(); + var temp = _dbcontext.Main.Where(s => s.Title.StartsWith(startingAlphabet.ToString(), StringComparison.OrdinalIgnoreCase)) + .Skip(offset) + .Take(pagesize); + + IEnumerable
data; + if (ascending) + data = await temp.OrderBy(s => s.Title) + .ThenBy(s => s.Description) + .ToListAsync(); + else + data = await temp.OrderByDescending(s => s.Title) + .ThenByDescending(s => s.Description) + .ToListAsync(); + + var total = await _dbcontext.Main.CountAsync(s => s.Title.StartsWith(startingAlphabet.ToString(), StringComparison.OrdinalIgnoreCase)); + + MainMinimizedExternalCollection result = new MainMinimizedExternalCollection(data.Minimize(), total); + + return result; } - Task> IMainDataAccess.GetByCategoryAsync(string category, int offset, int pagesize, bool ascending) + async Task
IMainDataAccess.GetAsync(Guid id) { - throw new NotImplementedException(); + return await _dbcontext.Main.FirstOrDefaultAsync(s => s.Id == id); } #endregion #region CREATE - public async Task CreateAsync(Main main) + public async Task CreateAsync(Main model) { - await _dbcontext.Main.AddAsync(main); + // assign a random id + model.Id = Guid.NewGuid(); + + + await _dbcontext.Main.AddAsync(model); await _dbcontext.SaveChanges(); - return main.Id; + return model.Id; + } + #endregion + + #region UPDATE + public async Task UpdateAsync(Guid id, MainUpdateModel model) + { + // find the entry + var entry = await _dbcontext.Main.FirstOrDefaultAsync(s => s.Id == id); + + if (entry != null) + { + entry.Title = model.Title; + entry.Description = model.Description; + entry.Category = model.Category; + + _dbcontext.Main.Update(entry); + } + else + throw new UpdateFailedException(UpdateFailErrorCode.EntryNotFound); + } + #endregion + + #region DELETE + public async Task DeleteAsync(Guid id) + { + // find the entry + var entry = await _dbcontext.Main.FirstOrDefaultAsync(s => s.Id == id); + + if (entry != null) + _dbcontext.Main.Remove(entry); + else + throw new DeleteFailedException(DeleteFailErrorCode.EntryNotFound); } #endregion } -} +} \ No newline at end of file diff --git a/Library.Encyclopedia.Entity/Exceptions/DeleteFailedException.cs b/Library.Encyclopedia.Entity/Exceptions/DeleteFailedException.cs new file mode 100644 index 0000000..eac24e0 --- /dev/null +++ b/Library.Encyclopedia.Entity/Exceptions/DeleteFailedException.cs @@ -0,0 +1,19 @@ +using EnumsNET; +using System; +using System.ComponentModel; + +namespace Library.Encyclopedia.Entity.Exceptions +{ + public class DeleteFailedException : Exception + { + public DeleteFailedException(DeleteFailErrorCode code) : base(((DeleteFailErrorCode)code).AsString(EnumFormat.Description)) + { + } + } + + public enum DeleteFailErrorCode + { + [Description("Entry not found!")] + EntryNotFound + } +} diff --git a/Library.Encyclopedia.Entity/Exceptions/UpdateFailedException.cs b/Library.Encyclopedia.Entity/Exceptions/UpdateFailedException.cs new file mode 100644 index 0000000..7bd1aa6 --- /dev/null +++ b/Library.Encyclopedia.Entity/Exceptions/UpdateFailedException.cs @@ -0,0 +1,19 @@ +using EnumsNET; +using System; +using System.ComponentModel; + +namespace Library.Encyclopedia.Entity.Exceptions +{ + public class UpdateFailedException : Exception + { + public UpdateFailedException(UpdateFailErrorCode code) : base(((UpdateFailErrorCode)code).AsString(EnumFormat.Description)) + { + } + } + + public enum UpdateFailErrorCode + { + [Description("Entry not found!")] + EntryNotFound + } +} diff --git a/Library.Encyclopedia.Entity/Interfaces/IMainDataAccess.cs b/Library.Encyclopedia.Entity/Interfaces/IMainDataAccess.cs index 49a95f7..555c3e8 100644 --- a/Library.Encyclopedia.Entity/Interfaces/IMainDataAccess.cs +++ b/Library.Encyclopedia.Entity/Interfaces/IMainDataAccess.cs @@ -1,4 +1,5 @@ using Library.Encyclopedia.Entity.Models; +using Library.Encyclopedia.Entity.Models.External; using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -7,10 +8,16 @@ namespace Library.Encyclopedia.Entity.Interfaces { public interface IMainDataAccess { - public Task> GetAsync(string query, int offset, int pagesize, bool ascending); - public Task> GetByCategoryAsync(string category, int offset, int pagesize, bool ascending); - public Task
GetAsync(string id); - public Task> GetAsync(char startingAlphabet); + #region GET + public Task GetAsync(string query, int offset, int pagesize, bool ascending); + public Task GetByCategoryAsync(string category, int offset, int pagesize, bool ascending); + public Task GetByAlphabetAsync(char startingAlphabet, int offset, int pagesize, bool ascending); + public Task
GetAsync(Guid id); + #endregion + + public Task CreateAsync(Main main); + public Task UpdateAsync(Guid id, MainUpdateModel model); + public Task DeleteAsync(Guid id); } } \ No newline at end of file diff --git a/Library.Encyclopedia.Entity/Library.Encyclopedia.Entity.csproj b/Library.Encyclopedia.Entity/Library.Encyclopedia.Entity.csproj index cb63190..71cd50d 100644 --- a/Library.Encyclopedia.Entity/Library.Encyclopedia.Entity.csproj +++ b/Library.Encyclopedia.Entity/Library.Encyclopedia.Entity.csproj @@ -4,4 +4,8 @@ netcoreapp3.1 + + + + diff --git a/Library.Encyclopedia.Entity/Models/External/MainMinimizedExternal.cs b/Library.Encyclopedia.Entity/Models/External/MainMinimizedExternal.cs index e4c2ba0..7aca354 100644 --- a/Library.Encyclopedia.Entity/Models/External/MainMinimizedExternal.cs +++ b/Library.Encyclopedia.Entity/Models/External/MainMinimizedExternal.cs @@ -1,22 +1,23 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; namespace Library.Encyclopedia.Entity.Models.External { public class MainMinimizedExternal { - public string Id { get; set; } + public Guid Id { get; set; } public string Title { get; set; } public string Description { get; set; } public string Category { get; set; } } public class MainMinimizedExternalCollection : QueryExternalModel { - public MainMinimizedExternalCollection(IEnumerable collection, int total, int offset, int limit) + public MainMinimizedExternalCollection(IEnumerable collection, int total) { this.Result = collection; this.Count = collection.Count(); - this.Total + this.Total = total; } } } diff --git a/Library.Encyclopedia.Entity/Models/External/MainUpdateModel.cs b/Library.Encyclopedia.Entity/Models/External/MainUpdateModel.cs new file mode 100644 index 0000000..225404b --- /dev/null +++ b/Library.Encyclopedia.Entity/Models/External/MainUpdateModel.cs @@ -0,0 +1,9 @@ +namespace Library.Encyclopedia.Entity.Models.External +{ + public class MainUpdateModel + { + public string Title { get; set; } + public string Description { get; set; } + public string Category { get; set; } + } +} \ No newline at end of file diff --git a/Library.Encyclopedia.Entity/Models/External/QueryExternalModel.cs b/Library.Encyclopedia.Entity/Models/External/QueryExternalModel.cs index acd7099..14103a2 100644 --- a/Library.Encyclopedia.Entity/Models/External/QueryExternalModel.cs +++ b/Library.Encyclopedia.Entity/Models/External/QueryExternalModel.cs @@ -7,7 +7,5 @@ public class QueryExternalModel public IEnumerable Result { get; set; } public int Count { get; set; } public int Total { get; set; } - public int Offset { get; set; } - public int Limit { get; set; } } } \ No newline at end of file diff --git a/Library.Encyclopedia.Entity/Models/Main.cs b/Library.Encyclopedia.Entity/Models/Main.cs index 9256fc3..bc6bf11 100644 --- a/Library.Encyclopedia.Entity/Models/Main.cs +++ b/Library.Encyclopedia.Entity/Models/Main.cs @@ -1,4 +1,5 @@ -using System; +using Library.Encyclopedia.Entity.Models.External; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -18,4 +19,25 @@ public class Main public ICollection Files { get; set; } public ICollection Links { get; set; } } + + public static class MainExtensions + { + public static MainMinimizedExternal Minimize(this Main main) + { + return new MainMinimizedExternal { + Id = main.Id, + Category = main.Category, + Description = main.Description, + Title = main.Title + }; + } + public static IEnumerable Minimize(this IEnumerable
collection) + { + foreach (var item in collection) + { + yield return Minimize(item); + } + } + } + } \ No newline at end of file