成为MVC4 + Entity + WebAPI的新手我为了简单地将GET,POST控制器处理程序和自定义映射到数据模型而感到沮丧。
我想我要问的是有一个生成工具,例如从数据类中创建控制器类,这样我就可以直接从数据中执行简单的GET命令了吗?
制作通用RESTful API的方法是什么,因此命令可以这样做
GET api / 1.0 / {genericdatatype} / {id}
哪里的通用数据类型可以是任何模型而没有特定的控制器?假设我不需要PUT(通过MVC应用程序处理)所以我真的不需要POST验证等。
答案 0 :(得分:3)
有一个名为MVC Scaffolding的工具/包,它将根据您的模型构建您的控制器。
http://mvcscaffolding.codeplex.com/
至于通用件,这是一个非常漫长而艰难的过程,需要花费大量时间。如果有人对此有好的答案,我也很乐意看到它。
编辑:我花了一些额外的时间来研究通用部分。看起来其他人有类似的想法,并在这里问了几乎相同的问题: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框架。