Oneweb API 控制所有模型的控制器

One Web API Controller to control all models

我正在创建一个包含 API 和 Web 的 MVC Core 1.0.1 项目。所以我已经创建了我的模型,现在我想在单个控制器中创建 CRUD 操作,而不是为每个模型搭建脚手架。我创建了一个看起来像这样的 ApiController

[Consumes("application/json")]
[Produces("application/json")]
[Route("/api/{resource}")]
public class ApiController : Controller
{
    private readonly MasterContext _context;

    public ApiController(MasterContext context)
    {
        _context = context;
    }

    [HttpPost]
    public IActionResult Create(string resource, [FromBody] object body)
    {
        //_context.Add();
        return Ok("ok api Create");

    }

    [HttpGet("{id?}")]
    public IActionResult Read(string resource, int? id)
    {
        return Ok("ok api get Read");
    }
    [HttpPatch("{id}")]
    public IActionResult Update(string resource, [FromBody] object body)
    {
        //_context.Update();
        return Ok("ok api Update");
    }
    [HttpDelete("{id}")]
    public IActionResult Delete(string resource, [FromBody] object body)
    {
        return Ok("ok api Delete");
    }
}

这样我就有了我需要的每个 HTTP 方法的方法(Post、Get、Patch、Delete),在资源中我有模型作为字符串,在正文中有正文作为对象的请求。在使用 entity framework 执行请求的操作之前,我必须根据资源找到模型并将对象主体转换为 class。

有什么建议吗?一位同事使用 Python 完成了此操作,可以使用 c# 完成吗?结果会有什么缺点?例如,我认为模型验证将很难完成。

是的,这是可能的。假设我们有这个 DbContext:

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

要在数据库中保存新实体,我们应该先找到 Blog 类型。有了类型,反序列化对象并保存它就很容易了:

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

var context = new FooContext();

IEntityType entityType = context.Model
    .GetEntityTypes()
    .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;
context.SaveChanges();

要通过 ID 从数据库中读取实体,请使用非通用 DbContext.Find

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

P.S。我认为通用 ApiController 通常不是一个好主意。它体积庞大,带来了巨大的不必要的复杂性,但却带来了很小的好处。