Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

t4mvc : Cannot inherit a controller class which has no default constructor?

I am using T4MVC with MVC2.

I have the following building blocks:

  1. A simple entity interface which defines that every POCO entity must have a long Id property:

    public interface IEntity
    {
        public long Id;
    }
    
  2. A simple POCO class which implements the IEntity interface and has some string properties:

    public class CD : IEntity
    {
        public long Id { get; set; }
    
        public long Name { get; set; }
    }
    
  3. A base controller:

    public abstract class EntityController<T> : Controller where T : class, global::IEntity
    {
        public EntityController(IEntityManager<T> manager);
    }
    
  4. I use this base controller in my CDController (where CDManager implements the IEntityManager interface, which is a UnitOfWork pattern to add CRUD functionality):

    public partial class CDController : EntityController<CD>
    {
        public CDController() : base(new CDManager()) { }
    }
    

When I run my t4 template, this code is generated:

namespace MyApp.Web.Controllers {
    public partial class CDController {
        [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
        protected CDController(Dummy d) { }

But this gives me an error during compilation:

MyApp.EntityController<CD> does not contain a constructor that takes 0 arguments

How can I solve this?

like image 660
Stef Heyenrath Avatar asked Jul 18 '11 09:07

Stef Heyenrath


2 Answers

I wanted by controller base class to be abstract and it's constructor protected and parametrized. Got around this issue by adding a blank constructor to ControllerBase that throws a NotImplementedException.

Doesn't quite feel right but it gets the job done. Only issue is when combined with dependency injection the wrong constructor will be called - since it throws an exception the app will bum out.

Code:

public abstract class ControllerBase : Controller
{
    protected object AlwaysSupply { get; private set; }

    public ControllerBase()
    {
        throw new NotImplementedException();
    }

    public ControllerBase(object alwaysSupply)
    {
        AlwaysSupply = alwaysSupply;
    }
}

This will cause T4MVC to generate compilable code. The fault seems to be it always tries to generate a blank (no parameters) constructor for controller classes.

Hope this helps someone.

like image 184
Ales Potocnik Hahonina Avatar answered Nov 07 '22 08:11

Ales Potocnik Hahonina


I see the problem, and it comes down to T4MVC not quite doing the right thing when dealing with generic classes. Normally it would generate a default ctor for it in a partial class, but the fact that it's generic is throwing it off.

You should be able to work around simply by adding a default ctor yourself, e.g.

public abstract partial class EntityController<T> : Controller where T : class, IEntity {
    public EntityController() { }

    // etc...
}
like image 2
David Ebbo Avatar answered Nov 07 '22 09:11

David Ebbo