-
-
Save arruw/d0c5f5afc600a50b7de8630aa2d11a61 to your computer and use it in GitHub Desktop.
[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(); | |
} |
Inside abstract controller's Create(), CreatedAtAction's first parameter which is the route name cannot be hard coded since all the derived class need to have a different route name. And that route name need to be constant. I am still try to figure out how to handle this myself.
@hanslai
I forked this Gist and made minor changes that might be of use to you.
https://gist.github.com/3976203a8f76ccf47e805cab834bf5bd
An alternative approach you could use would be to add the "virtual" modifier to the method signature; allowing you to override the current implementation where necessary.
This would allow you to keep the current implementation for classes that don't need any adjustments to @matjazmav 's implementation.
@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.
Wow guys :) didn't noticed that this gist is so "popular". I really must provide full code example and maybe a blog post.
Here I made a repository with working demo of the generic REST API. https://github.com/matjazmav/generic-api
Hi! I'm really interested in this as well. I'm working on something that could really benefit from Generics but I don't know how to tell ASP.NET to create a controller out of a generic type. Do you have an example you could publish?