We are aiming to reduce code noise that would be common for all Controllers such as basic CRUD.

public interface IGenericController<T, Y> where T : BaseMaster
    IEnumerable<T> Get();

    T Get(Y code);

    HttpResponseMessage Post(T entity);

    T Put(T entity);

    T Delete(Y code);

this would be use as

public class AuditController : GenericController<AuditRepository, int>

We could also use Composition over Inheritance approach here for code reuse however we there will still be code noises, so we make this as a choice.

I am a bit hesitant on wrapping existing .net base classes. One thing I could be sure is that the virtual methods are no longer expose for overriding.

Would there be any further complication on this approach?

  • BaseBean anti-pattern. IMO you are using inheritance for the wrong purpose (to reduce code). I worked with a framework made in Java that implemented excatly what you are designing. For a little while it works fine. Till uncommon change request happens... You are loosing flexibility with so typed interfaces. This loose is extended to the implementation because the inheritance. Everything that does not fit in the design ends into another class, so you basically moves the noise to another place.
    – Laiv
    Commented Dec 8, 2016 at 19:00

3 Answers 3


Its fairly common to use a custom BaseController from which your other controllers inherit rather than Controller. I dont think there is any particular danger here.

However! I have to agree that its not good practice. Your approach suggests that you will go all the way down to generic repositories.

But at some point you are going to have to deal with differing business logic, or input parameters between the different controllers.

Rather than bury that conditional in the inheritance tree, its best to have it up front in your controller or service layer. (do you have a service layer?)

Alternatively if you really are just exposing a generic repo with identical methods, then you could do that in a single controller, parsing the type out of the route

When I say a single controller I mean something like...

object Get(string resourceType, string id)
    var repo = repoFactory.GetForType(resourceType);
    return repo.Get(id)

That single controller and action is called for all your http://myapi/myresource/123

  • You actually got it right, we have generic repository pattern, and no we don't have service layer. When you mean singler controller similar to this ?
    – jbalintac
    Commented Dec 8, 2016 at 12:44
  • updated. but yeah generic repo is a bit of an anti-pattern in my view. also you lack of a service layer means you dont really have a contract to represent in the controllers. hence your duplication of controllers/code
    – Ewan
    Commented Dec 8, 2016 at 12:54

You are doing it wrong. Your approach simply violates the Interface Segregation Principle which says

No client should be forced to depend on methods it does not use

Imagine if I have a controller UsersController which does not support IGenericController<T, Y>.Delete(Y code) method (for whatever reason) but wishes to reuse most of the logic in GenericController<T, Y>, you would have to override it and throw a NotSupportedException.

Instead you should probably move all your business logic in a separate layer (think UserService) and keep your controllers thin.

  • A bit compelling theory, in the end we still need to explicitly hand write boilerplate code. I guess its not much of a trade over maintainability.
    – jbalintac
    Commented Dec 8, 2016 at 12:51

This need arises often, when a Web-Application becomes more and more client-focused, thus doesn't need much server-side handling anymore. For such cases, there is a library around, which helps you defining default-controllers without actually needing each Controller having around: https://github.com/brentj73/ControllerLess

  • This is a bit nice just using ASP.net as a webserver, however you lose control of authorisation here I am afraid.
    – jbalintac
    Commented Dec 8, 2016 at 12:49

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.