通用Web Api控制器,支持任何模型

Dar*_*der 21 c# generics asp.net-web-api

是否可以使用支持项目中任何模型的通用Web API?

class BaseApiController<T> :ApiController
{
    private IRepository<T> _repository;

    // inject repository

    public virtual IEnumerable<T> GetAll()
    {
       return _repository.GetAll();
    }

    public virtual T Get(int id)
    {
       return _repositry.Get(id);
    }

    public virtual void Post(T item)
    {
       _repository.Save(item);
    }
    // etc...
}

class FooApiController : BaseApiController<Foo>
{
   //..

}

class BarApiController : BaseApiController<Bar>
{
   //..
}
Run Code Online (Sandbox Code Playgroud)

这会是一个好方法吗?

毕竟,我只是重复CRUD方法?我可以使用这个基类为我做这项工作吗?

这个可以吗?你会这样做吗?任何更好的想法?

Nic*_*cht 23

我为一个小项目做了这个,以获得一些东西并运行到客户端演示.一旦我了解了业务规则,验证和其他注意事项的细节,我最终不得不从我的基类覆盖CRUD方法,因此它不会成为长期实现的平台.

我遇到了路由问题,因为不是所有东西都使用了相同类型的ID(我正在使用现有系统).有些表有int主键,有些表有,有些表stringsguids.

我最后也遇到了问题.最后,虽然当我第一次使用它时看起来很光滑,但实际上在现实世界中使用它被证明是另一回事,并没有让我更进一步.

  • 你可以用一个接口叫它`IIdentifier <T>`代表不同类型的id. (7认同)

小智 6

 public class GenericApiController<TEntity> : BaseApiController
    where TEntity : class, new()
{
    [HttpGet]
    [Route("api/{Controller}/{id}")]       
    public IHttpActionResult Get(int id)
    {
        try
        {
            var entity = db.Set<TEntity>().Find(id);
            if(entity==null)
            {
                return NotFound();
            }
            return Ok(entity);

        }
        catch(Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    [HttpGet]
    [Route("api/{Controller}")]
    public IHttpActionResult Post(TEntity entity)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        try
        {
            var primaryKeyValue = GetPrimaryKeyValue(entity);
            var primaryKeyName = GetPrimaryKeyName(entity);
            var existing = db.Set<TEntity>().Find(primaryKeyValue);
            ReflectionHelper.Copy(entity, existing, primaryKeyName);
            db.Entry<TEntity>(existing).State = EntityState.Modified;
            db.SaveChanges();
            return Ok(entity);
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    [HttpGet]
    [Route("api/{Controller}/{id}")]
    public IHttpActionResult Put(int id, TEntity entity)
    {
        try
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var existing = db.Set<TEntity>().Find(id);
            if (entity == null)
            {
                return NotFound();
            }
            ReflectionHelper.Copy(entity, existing);
            db.SaveChanges();
            return Ok(entity);
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    [HttpDelete]
    [Route("api/{Controller}/{id}")]
    public IHttpActionResult Delete(int id)
    {
        try
        {
            var entity = db.Set<TEntity>().Find(id);
            if(entity==null)
            {
                return NotFound();
            }
            db.Set<TEntity>().Remove(entity);
            db.SaveChanges();
            return Ok();
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    protected internal int GetPrimaryKeyValue(TEntity entity)
    {
        return ReflectionHelper.GetPrimaryKeyValue(entity);
    }

    protected internal string GetPrimaryKeyName(TEntity entity)
    {
        return ReflectionHelper.GetPrimaryKeyName(entity);
    }

    protected internal bool Exists(int id)
    {
        return db.Set<TEntity>().Find(id) != null;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您已将“[HttpGet]”应用于“Post”和“Put”方法。这是故意的吗? (2认同)

eou*_*3hf 5

这绝对是可能的.我以前从来没有理由这样做,但如果它适合你的情况,它应该是好的.

如果你的所有模型都可以用完全相同的方式保存和检索,那么它们应该只是在同一个控制器中呢?