I have a base controller that should return a List of objects (and map them from DTO to business)
If the child controller decides to apply a specification (filter or include something) it can do it by overriding the GetSpecification()
method.
But by default, in the base class I don't want to filter the objects.
[Route("api/[controller]")]
[ApiController]
public class BaseApiController<TBusinessModel, TApiModel,
TBaseRepository> : BaseController<TBaseRepository>
where TBusinessModel : BaseEntity
where TBaseRepository : IBaseRepository
{
public BaseApiController(TBaseRepository repository,
IMapper mapper) : base(repository, mapper)
{ }
// GET: api/Bars
[HttpGet]
public virtual async Task<IActionResult> List()
{
var spec = GetSpecification();
var items = await _repository.ListAsync<TBusinessModel>(spec);
var apiItems = _mapper.Map<List<TApiModel>>(items);
return Ok(apiItems);
}
protected virtual ISpecification<TBusinessModel> GetSpecification()
{
// how to get an empty specification that does not filter or do something?
return new Specification<TBusinessModel>();
}
}
I use ardalis specifications, but it could be any generic IQueryable
thing...
Actually it says:
Error CS0144 Cannot create an instance of the abstract type or interface 'Specification'
Having an empty specification is a totally valid construct. Once evaluated will return all records. In the below example, it will return all customers
But, the issue here is not the empty specification. You're trying to add another layer of abstraction, and you're trying to instantiate
Specification<T>
directly. TheSpecification
is an abstract class, thus you won't be able to create an instance. If you are eager to implement that infrastructure, then just add your own base class inherited fromSpecification<T>
, and then use that one as a base for all the other specifications in your app.Note: We made the class abstract, exactly to discourage users to do this :) But, sure you can go ahead and use it in that manner.