我们有一组控制器,这些控制器返回JSON数据以通过Web API同步实体。每个数据实体都有自己的控制器和数据模型(“订单,项目,客户...”) 因此,这实际上使每个控制器都使用完全相同的代码。唯一的区别是控制器/ Web api路径的名称,以及将通过JSON返回的数据模型。 我们想要做的是拥有一个所有其他控制器都实现/扩展的基本控制器(BaseController.cs)。为此,我们希望每个子控制器类定义的基类中都有一个虚拟的“ EntityType”或“ EntityName”属性。然后,不必在每个控制器中重复执行返回数据的代码。 我们的问题是我们无法弄清楚如何存储/传递/定义“类型”或“ TEntity”变量。并且我们需要执行此命令来执行“ Get” api方法的主要部分:
示例:
var returnValue = dbContext.Set<GetEntityModelClass()>().FromSql("EXEC dbo.[AJ_P_{0}_API]", GetEntityModelName()).ToList();
我们像这样在BaseController.cs类中实现GetEntityModelName():
public virtual string GetEntityName() { return null; }
和子控制器类的示例将具有以下内容:
public override string GetEntityName() { return "Product"; }
对于可传递dbContext.Set()调用所需值的可比较GetEntityModelClass(),我们该怎么做?
如果有帮助,这里是我们的代码的更大示例:
BaseController.cs
-----------------------------------------
namespace API.Controllers
{
[Produces("application/json")]
public class BaseController : Controller
{
// Returns the name of an entity as it is used in stored procedures, class names, etc...
public virtual string GetEntityName()
{
return null;
}
// Return a type that can be utilized with the dbContext.Set<???>() call
public virtual ??? GetEntityName()
{
return ???;
}
// SiteContext is the API site's data context.
protected readonly SiteContext dbContext;
public BaseController(SiteContext context)
{
dbContext = context;
}
[HttpGet("{token}")]
public IActionResult Get([FromRoute] string token)
{
return Get(token);
}
public IActionResult Results(string token)
{
if (!ModelState.IsValid) { return BadRequest(ModelState); }
var returnValue = dbContext.Set<???GetEntityModel()???>().FromSql("EXEC dbo.[AJ_P_{0}_API] @Token={1}", GetEntityName(), token).ToList();
return Ok(returnValue);
}
}
}
ProductController.cs
-----------------------------------------
namespace API.Controllers
{
[Produces("application/json")]
[Route("/Product")]
public class ProductController : BaseController
{
public override string GetEntityName() {
return "Product";
}
public override ???? GetEntityModel() {
return ( ??? ProductModel type ??? )
}
public ProductController(SiteContext context) : base(context) { }
}
}
答案 0 :(得分:3)
我不喜欢通用基本控制器。但是,您可以使控制器通用,将所需的实体类型作为类型参数。应该可以解决您的问题。
使用样品控制器
[Produces("application/json")]
public abstract class BaseController<TEntity, TModel> : Controller
where TEntity : class
where TModel : class {
// Returns the name of an entity as it is used in stored procedures, class names, etc...
protected virtual string GetEntityName() {
return typeof(TEntity).Name;
}
// SiteContext is the API site's data context.
protected readonly SiteContext dbContext;
protected BaseController(SiteContext context) {
dbContext = context;
}
[HttpGet("{token}")]
public IActionResult Get([FromRoute] string token) {
return GetInternal(token);
}
protected abstract TModel Map(TEntity entity);
protected virtual IActionResult GetInternal(string token)
if (!ModelState.IsValid) { return BadRequest(ModelState); }
var sql = string.Format("EXEC dbo.[AJ_P_{0}_API] @Token", GetEntityName());
var entities = dbContext.Set<TEntity>().FromSql(sql, token).ToList();
var returnValue = entities.Select(Map);
return Ok(returnValue);
}
}
然后,派生的控制器将只提供type参数。
[Produces("application/json")]
[Route("[controller]")]
public class ProductController : BaseController<Product, ProductModel> {
public ProductController(SiteContext context) : base(context) { }
protected override ProductModel Map(Product entity) {
return new ProductModel {
Property1 = entity.Property1,
//...
PropertyN = entity.PropertyN,
}
}
}