3

I am making a custom controller class, from which all my other controller classes will inherit in .Net Framework 4.8, Web API

public class BaseApiController<T> where T: class, ApiController
{
    protected T service;

    public BaseApiController(T service)
    {
        this.service = service;
    }
}

This gives a compile-time error

Error CS0450 'ApiController': cannot specify both a constraint class and the 'class' or 'struct' constraint

I know I am missing small detail with the right syntax.
T is a service, which is individual for every controller and I want to make sure it is always a reference type. I also want to inherit from the main ApiController class.

If I do it like this, there are no errors (This works for me):

public class BaseApiController<T> : ApiController
{
    protected T service;

    public BaseApiController(T service)
    {
        this.service = service;
    }
}

But I want the additional T logic for reference type.

I want to use it like this, e.g:
Note: This how I use it and it works.

[Authorize]
[RoutePrefix("api/[controller]")]
public class MyOtherController : BaseApiController<IMyOtherService>
{
    public MyOtherController(IMyOtherService myOtherService) : base(myOtherService)
    {

    }

    [HttpPost]
    public IHttpActionResult DoSomething(Model requestModel)
    {
        var result = this.service.SetPaymentStatusUK(model: requestModel);
        return Ok();
    }
}

I just want to know how to add the T check for reference type in the BaseApiController class.

4
  • You added ApiControler as a Generic Constraint, rather then the class to inherit/Interface to implement. Basically you put that class in the wrong spot. Commented Nov 8, 2019 at 9:59
  • Since no struct could inherit from ApiController, what do you think class is adding for you here? Commented Nov 8, 2019 at 10:00
  • 1
    The proper syntax is to inherit first, then constrain. This is from the examples class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { } learn.microsoft.com/en-us/dotnet/csharp/programming-guide/… Commented Nov 8, 2019 at 10:02
  • Thanks, accepted as well Commented Nov 8, 2019 at 10:22

1 Answer 1

3

If I understand your question right, the issue is that you applied ApiControler as a Constraint to T. When you wanted to apply it as a Ancestor of BaseApiController<T>.

As a constraint ApiControler it is not valid, because you already applied the class constraint. class include all classes, including ApiControler and every other class that has yet to be written. It is a less restrictive constraint the ApiControler. You only use a specific type or inferface as constraint, if you want all possible T's the absolutely positively have that inheritance/Interface Implementation.

According to the Syntax examples, you first inherit, then you constrain. So:

public class BaseApiController<T> : ApiController where T: class
{
  //all the code
}

Might be the droid you are looking for.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, exactly what I needed. CHeers

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.