One Web API Controller to control all models

api-design c# entity-framework-core


I am creating a MVC Core 1.0.1 project that will include both API and Web. So i have created my models and now i want to create CRUD operations within a single controller instead of scaffolding each model. I have created an ApiController that looks like this

public class ApiController : Controller
    private readonly MasterContext _context;

    public ApiController(MasterContext context)
        _context = context;

    public IActionResult Create(string resource, [FromBody] object body)
        return Ok("ok api Create");


    public IActionResult Read(string resource, int? id)
        return Ok("ok api get Read");
    public IActionResult Update(string resource, [FromBody] object body)
        return Ok("ok api Update");
    public IActionResult Delete(string resource, [FromBody] object body)
        return Ok("ok api Delete");

This way i have a method for each HTTP method that i need (Post, Get, Patch, Delete), in the resource i have the model as a string and in body i have the body of the request as an object. Before working with entity framework to do the requested operation, i have to find the model according to resource and convert the object body to that class.

Any suggestions how to do that? A colleague has done this using Python, can this be done using c# and what downside will the result have? For example, i presume model validation will be hard to accomplish.

4/24/2017 9:23:15 PM

Accepted Answer

Yes, it's possible. Let's say we have this DbContext:

public partial class FooContext : DbContext
    //has "MyAssembly.Blog" type
    public virtual DbSet<Blog> Blog { get; set; }

To save a new entity in database we should find Blog type first. Having the type, it's easy to deserialize object and save it:

//you called POST /blog
string resource = "blog";
string body = "{...}";

var context = new FooContext();

IEntityType entityType = context.Model
    .First(x => x.Name.EndsWith($".{resource}", StringComparison.OrdinalIgnoreCase));

//This type should be "MyAssembly.Blog" - exact entity CLR type.
//Another option to get this CLR type is assembly scan.
Type type = entityType.ClrType;

//having type, it is possible to create instance
object entity = JsonConvert.DeserializeObject("body", type);
//var entity = Activator.CreateInstance(type);

context.Entry(entity).State = EntityState.Added;

To read an entity by ID from database, use non-generic DbContext.Find

var entityFromDb = context.Find(type, id);

P.S. I think a generic ApiController is generally bad idea. It's bulky and it brings a huge unnecessary complexity but small benefits.

4/25/2017 7:36:13 AM

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow