Skip to content

Instantly share code, notes, and snippets.

@arruw
Last active March 24, 2021 22:05
Show Gist options
  • Save arruw/d0c5f5afc600a50b7de8630aa2d11a61 to your computer and use it in GitHub Desktop.
Save arruw/d0c5f5afc600a50b7de8630aa2d11a61 to your computer and use it in GitHub Desktop.
ASP.NET Core - Generic web API controller with generic repository pattern (created on, modified on, soft delete) ... view demo https://github.com/matjazmav/generic-api
[Authorize]
[Route("api/[controller]")]
public abstract class ApiController<T> : Controller where T : class, IEntity
{
private IApplicationRepository<T> _repository;
public ApiController(IApplicationRepository<T> repository)
{
_repository = repository;
}
[HttpGet]
[ValidateModel]
public IActionResult Query()
{
return Ok(_repository.Get());
}
[HttpGet("{id}")]
[ValidateModel]
public IActionResult Find(Guid id)
{
var record = _repository.Get(id);
if (record == null)
return NotFound();
return Ok(record);
}
[HttpPost]
[ValidateModel]
public async Task<IActionResult> Create([FromBody] T record)
{
_repository.Create(record);
if (await _repository.SaveAsync() == 0)
return BadRequest();
return CreatedAtAction("Find", new { id = record.Id }, record);
}
[HttpPut("{id}")]
[ValidateModel]
public async Task<IActionResult> Update(Guid id, [FromBody] T record)
{
if (id != record.Id)
return BadRequest();
_repository.Update(record);
if (await _repository.SaveAsync() == 0)
return BadRequest();
return Ok(record);
}
[HttpDelete("{id}")]
[ValidateModel]
public async Task<IActionResult> Delete(Guid id)
{
_repository.Delete(id);
if (await _repository.SaveAsync() == 0)
return BadRequest();
return NoContent();
}
}
public class ApplicationRepository<T> : IApplicationRepository<T> where T : class, IEntity
{
private DbContext _context;
public ApplicationRepository(ApplicationDbContext context)
{
_context = context;
}
public IQueryable<T> Get()
{
return _context.Set<T>().Where(e => !e.IsDeleted);
}
public T Get(Guid id)
{
return Get().SingleOrDefault(e => e.Id == id);
}
public void Create(T record)
{
record.CreatedOn = DateTime.Now;
record.ModifiedOn = record.CreatedOn;
_context.Add(record);
}
public void Update(T record)
{
record.ModifiedOn = DateTime.Now;
_context.Set<T>().Attach(record);
_context.Entry(record).State = EntityState.Modified;
}
public void Delete(Guid id)
{
var record = Get(id);
if (record != null) {
record.ModifiedOn = DateTime.Now;
record.IsDeleted = true;
}
}
public int Save()
{
return _context.SaveChanges();
}
public Task<int> SaveAsync()
{
return _context.SaveChangesAsync();
}
#region Dispose
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(disposing)
{
if(_context != null)
{
_context.Dispose();
_context = null;
}
}
}
#endregion
}
public interface IApplicationRepository<T> : IDisposable
{
IQueryable<T> Get();
T Get(Guid id);
void Create(T record);
void Update(T record);
void Delete(Guid id);
int Save();
Task<int> SaveAsync();
}
@hanslai
Copy link

hanslai commented Feb 10, 2018

@cathalnoonan thanks for your help. I actually tried passing in the route name to the base controller before also. But it does not work, because attribute name need to be constant. So, it will not even pass the compiler

I might need to override those functions. which I really do not want to do, because I have a lot of simple controllers need to override.

@arruw
Copy link
Author

arruw commented Sep 12, 2018

Wow guys :) didn't noticed that this gist is so "popular". I really must provide full code example and maybe a blog post.

@arruw
Copy link
Author

arruw commented Dec 8, 2019

Here I made a repository with working demo of the generic REST API. https://github.com/matjazmav/generic-api

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment