如何(自动)为MVC +实体生成webapi控制器或一般查询所有类型

时间:2013-01-23 21:53:32

标签: c# asp.net-mvc asp.net-web-api entity controllers

成为MVC4 + Entity + WebAPI的新手我为了简单地将GET,POST控制器处理程序和自定义映射到数据模型而感到沮丧。

我想我要问的是有一个生成工具,例如从数据类中创建控制器类,这样我就可以直接从数据中执行简单的GET命令了吗?

制作通用RESTful API的方法是什么,因此命令可以这样做

GET api / 1.0 / {genericdatatype} / {id}

哪里的通用数据类型可以是任何模型而没有特定的控制器?假设我不需要PUT(通过MVC应用程序处理)所以我真的不需要POST验证等。

3 个答案:

答案 0 :(得分:3)

有一个名为MVC Scaffolding的工具/包,它将根据您的模型构建您的控制器。

http://mvcscaffolding.codeplex.com/

http://blog.stevensanderson.com/2011/01/13/scaffold-your-aspnet-mvc-3-project-with-the-mvcscaffolding-package/

至于通用件,这是一个非常漫长而艰难的过程,需要花费大量时间。如果有人对此有好的答案,我也很乐意看到它。

编辑:我花了一些额外的时间来研究通用部分。看起来其他人有类似的想法,并在这里问了几乎相同的问题:Generic Web Api controller to support any model

在一天结束时,他们在那次谈话中表达了一些非常关注的问题。你如何处理不同类型的ID?他们总是需要成为字符串然后解析出来吗?一旦你进入更多业务规则,我怀疑你在控制器后面有一个非常复杂的业务层。也就是说,我会说你最好坚持使用直板脚手架,而不是建立一个通用的API。当然,它可能已经完成,但是花费了多少时间和疯狂解析API背后的代码?只是我的想法。

答案 1 :(得分:2)

对于原版海报来说,这个答案可能已经太迟了,但也许其他人可以使用它。

我刚刚为MVC 5代码编写了这个通用基础api控制器,首先是CRUD操作:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using My.Models;
using System.Data.Entity.Validation;

namespace My.Controllers.Api
{
  public abstract class CrudController<TEntity>
    : ApiController where TEntity : class
  {
    private readonly MyContext _db = new MyContext();
    private readonly DbSet<TEntity> _dbSet;

    protected CrudController(Func<MyContext, DbSet<TEntity>> dbSet)
    {
      _db = new EtlContext();
      _dbSet = dbSet(_db);
    }

    public IEnumerable<TEntity> Get()
    {
      return _dbSet.AsEnumerable();
    }

    public HttpResponseMessage Post(TEntity entity)
    {
      try
      {
        if (!ModelState.IsValid)
          return Request.CreateResponse(HttpStatusCode.BadRequest);

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

        _db.SaveChanges();

        return Request.CreateResponse(HttpStatusCode.Created);
      }
      catch (DbEntityValidationException)
      {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
      }
      catch (DbUpdateException)
      {
        return Request.CreateResponse(HttpStatusCode.Conflict);
      }
    }

    public HttpResponseMessage Put(TEntity entity)
    {
      try
      {
        if (!ModelState.IsValid)
          return Request.CreateResponse(HttpStatusCode.BadRequest);

        _db.Entry(entity).State = EntityState.Modified;

        _db.SaveChanges();

        return Request.CreateResponse(HttpStatusCode.OK);
      }
      catch (DbEntityValidationException)
      {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
      }
      catch (DbUpdateConcurrencyException)
      {
        return Request.CreateResponse(HttpStatusCode.NotFound);
      }
      catch (DbUpdateException)
      {
        return Request.CreateResponse(HttpStatusCode.Conflict);
      }
    }

    public HttpResponseMessage Delete(TEntity entity)
    {
      try
      {
        _db.Entry(entity).State = EntityState.Deleted;

        _db.SaveChanges();

        return Request.CreateResponse(HttpStatusCode.OK);
      }
      catch (DbUpdateConcurrencyException)
      {
        return Request.CreateResponse(HttpStatusCode.NotFound);
      }
    }

    protected override void Dispose(bool disposing)
    {
      _db.Dispose();
      base.Dispose(disposing);
    }
  }
}

我仍然必须像这样为每个DbSet创建子类:

public class CustomersController 
  : CrudController<Customer>
{
  public CustomersController()
    : base(db => db.Customers)
  {}
}

public class ProductsController 
  : CrudController<Product>
{
  public ProductsController()
    : base(db => db.Products)
  {}
}

使此路由工作:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}",
 );

答案 2 :(得分:1)

我自己提供了一个我们团队采用的替代方案。 OData。它是构建初始RESTful模板的一种快速方法,更加强调查询而不是CRUD,它使数据可用而无需自己手动构建端点。我现在正在为一个在Web API服务器上拥有OData的项目做前端,这样可以很好地解决后端开发人员在集合端点上处理更紧迫的问题。

它也适用于Entity框架。