0

I am trying to use an abstract base class with generics on an ASP Net Core controller. While the code builds, the endpoints return 404 and do not appear in the swagger docs.

When I remove the generic base class, I am able to see the controller in the docs, but I would then have to copy and paste multiple versions of the controller, which I am trying to avoid.

Any suggestions on what I am missing?

THIS CONTROLLER WORKS

[Route("/testconcrete/employees")]
public class TestController : ControllerBase
{
    private readonly IUserService<TechDevsEmployee> _userService;

    public TestController(IUserService<TechDevsEmployee> userService)
    {
        _userService = userService;
    }

    [HttpGet("{userId}")]
    public async Task<ActionResult<User>> GetUserById([FromRoute] Guid userId)
    {
        var result = await _userService.FindById(userId);
        return new OkObjectResult(result);
    }
}

THIS CONTROLLER DOES NOT WORK (404)

[Route("/testgeneric/employees")]
public class TechDevsEmployeeController<TechDevsEmployee> : UserController<TechDevsEmployee> where TechDevsEmployee : IUser, IClientEntity
{
    public TechDevsEmployeeController(IUserService<TechDevsEmployee> userService) : base(userService)
    {
    }
}

BASE CLASS

public abstract class UserController<T> : ControllerBase where T : IUser, IClientEntity
{
    private readonly IUserService<T> _userService;

    public UserController(IUserService<T> userService)
    {
        _userService = userService;
    }

    [HttpGet("{userId}")]
    public async Task<ActionResult<User>> GetUserById([FromRoute] Guid userId)
    {
        var result = await _userService.FindById(userId);
        return new OkObjectResult(result);
    }
}
1

2 Answers 2

2

I believe in your subclass definition you have declared a generic type TechDevsEmployee in the class signature. The subclass does not need to specify this, you can specify the type you want the BaseClass to use directly like so:

[Route("/testgeneric/employees")]
public class TechDevsEmployeeController : UserController<TechDevsEmployee>
{
    public TechDevsEmployeeController(IUserService<TechDevsEmployee> userService) 
        : base(userService)
    {
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

As kyleJ mentions in his answer, you cannot have a generic parameter on the concrete class itself. MVC has no way of guessing what type you want to use for TechDevsEmployee. If you have many subclasses of TechDevsEmployee, you need to create a separate sub controller for each subclass, and remove the generic parameter from the subclass, as mentioned in the other answer https://stackoverflow.com/a/60920600/25338

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.