Dependency Injection Issue with EF, ASP.NET MVC and StructureMap

211 views Asked by At

I know there are a few similar question out there regarding this issue with structure map, but my issue seems to not be resolvable with the solutions they needed. I must state I have used this same setup many times, but cannot see why this code is causing issues.

Here are all of the classes I think that are needed for help with troubleshooting my code.

ControllerConvention.cs

public class ControllerConvention : IRegistrationConvention
{
    public void ScanTypes(TypeSet types, Registry registry)
    {
        foreach (Type type in types.AllTypes())
        {
            if (type.CanBeCastTo(typeof(Controller)) && !type.IsAbstract)
            {
                registry.For(type).LifecycleIs(new UniquePerRequestLifecycle());
            }
        }
    }
}

IoC.cs

public static class IoC
{
    public static IContainer Container { get; set; }

    static IoC()
    {
        Container = new Container();
    }
}

StandardRegistry.cs

public class StandardRegistry : Registry
{
    public StandardRegistry()
    {
        Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.Assembly("PotSmart.Service");
            scan.Assembly("PotSmart.Data");
            scan.WithDefaultConventions();
        });
    }
}

StructureMapDependencyResolver.cs

 public class StructureMapDependencyResolver : IDependencyResolver
{
    private readonly Func<IContainer> _factory;

    public StructureMapDependencyResolver(Func<IContainer> factory)
    {
        _factory = factory;
    }

    public object GetService(Type serviceType)
    {
        if (serviceType == null)
        {
            return null;
        }

        var factory = _factory();



        return serviceType.IsAbstract || serviceType.IsInterface
            ? factory.TryGetInstance(serviceType)
            : factory.GetInstance(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _factory().GetAllInstances(serviceType).Cast<object>();
    }
}

Global.asax

 public IContainer Container
    {
        get
        {
            return (IContainer)HttpContext.Current.Items["_Container"];
        }
        set
        {
            HttpContext.Current.Items["_Container"] = value;
        }
    }

    protected void Application_Start()
    {


        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        DependencyResolver.SetResolver(new StructureMapDependencyResolver(() => Container ?? IoC.Container));

        IoC.Container.Configure(cfg =>
        {
            cfg.AddRegistry(new StandardRegistry());
            cfg.AddRegistry(new ControllerRegistry());

        });


    }

Here are parts of my data and entities classes:

RepositoryBase.cs

public class RepositoryBase 
{
    private readonly PotSmartEntityModel1 _dataContext;
    protected IDbFactory DbFactory { get; private set; }

    protected PotSmartEntityModel1 DbContext
    {
        get
        {
            return _dataContext ?? DbFactory.Init();
        }
    }

    protected RepositoryBase(IDbFactory dbFactory)
    {
        DbFactory = dbFactory;
        var adapter = (IObjectContextAdapter)this;
        var objectContext = adapter.ObjectContext;
        // objectContext.CommandTimeout = 120; // value in seconds
    }

}

public abstract class RepositoryBase<T> where T : class
{
    private readonly PotSmartEntityModel1 _dataContext;
    private readonly IDbSet<T> _dbSet;

    protected IDbFactory DbFactory { get; private set; }

    protected PotSmartEntityModel1 DbContext
    {
        get
        {
            return _dataContext ?? DbFactory.Init();
        }
    }

    protected RepositoryBase(IDbFactory dbFactory)
    {
        DbFactory = dbFactory;
        _dbSet = DbContext.Set<T>();
    }

    public virtual void Add(T entity)
    {
        _dbSet.Add(entity);
    }

    public virtual void Update(T entity)
    {
        _dbSet.Attach(entity);
        DbContext.Entry(entity).State = EntityState.Modified;
    }

    public virtual void Delete(T entity)
    {
        _dbSet.Remove(entity);
    }

    public virtual void Delete(Expression<Func<T, bool>> where)
    {
        IEnumerable<T> objects = _dbSet.Where<T>(where);
        foreach (T obj in objects)
        {
            _dbSet.Remove(obj);
        }
    }

    public virtual T GetById(int id)
    {
        return _dbSet.Find(id);
    }

    public virtual T GetById(string id)
    {
        return _dbSet.Find(id);
    }

    public virtual IEnumerable<T> GetAll()
    {
        return _dbSet.ToList();
    }

    public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
    {
        return _dbSet.Where(where).ToList();
    }

    public T Get(Expression<Func<T, bool>> where)
    {
        return _dbSet.Where(where).SingleOrDefault();
    }

    public virtual IQueryable<T> Query()
    {
        return _dbSet;
    }

    public virtual IQueryable<T> Query(Expression<Func<T, bool>> where)
    {
        return _dbSet.Where(where);
    }

    public virtual ObjectQuery<U> CreateQuery<U>(string query, ObjectParameter[] parameters)
    {
        return CastAsObjectContext().CreateQuery<U>(query, parameters);
    }

    public virtual ObjectQuery<U> CreateQuery<U>(string query)
    {
        return CreateQuery<U>(query, new ObjectParameter[0] { });
    }

    public virtual ObjectQuery<DbDataRecord> CreateQuery(string query, ObjectParameter[] parameters)
    {
        return CreateQuery<DbDataRecord>(query, parameters);
    }

    public virtual ObjectQuery<DbDataRecord> CreateQuery(string query)
    {
        return CreateQuery<DbDataRecord>(query);
    }

    private ObjectContext CastAsObjectContext()
    {
        var oContext = (DbContext as IObjectContextAdapter).ObjectContext;

        return oContext;
    }

}

DBFactory.cs

class DbFactory : Disposable, IDbFactory
{
    private PotSmartEntityModel1 _dbContext;

    public PotSmartEntityModel1 Init()
    {
        return _dbContext ?? (_dbContext = new PotSmartEntityModel1());
    }

    protected override void DisposeCore()
    {
        if (_dbContext != null)
        {
            _dbContext.Dispose();
        }
    }
}

IDBFactory.cs

public interface IDbFactory : IDisposable
{
    PotSmartEntityModel1 Init();
}

IRepository.cs

public interface IRepository
{
}


public interface IRepository<T> where T : class
{
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
    void Delete(Expression<Func<T, bool>> where);
    T GetById(int id);
    T GetById(string id);

    IEnumerable<T> GetAll();

    IEnumerable<T> GetMany(Expression<Func<T, bool>> where);

    IQueryable<T> Query();

    IQueryable<T> Query(Expression<Func<T, bool>> where);

    ObjectQuery<U> CreateQuery<U>(string query, ObjectParameter[] parameters);

    ObjectQuery<U> CreateQuery<U>(string query);

    ObjectQuery<DbDataRecord> CreateQuery(string query, ObjectParameter[] parameters);

    ObjectQuery<DbDataRecord> CreateQuery(string query);


}

Now, sorry for so much code but that way I get all the answer out there that some in the community may ask. The issue is on my controller, I use no default constructor and do the dependency injection like the following code show:

MarkerController.cs

public class MarkerController : Controller
{

    private readonly IMarkerService _markerService;

    public MarkerController(IMarkerService markerService)
    {
        _markerService = markerService;
    }

    // GET: Markers
    public ActionResult Index()
    {
        return View();
    }

}

When I run the code I keep getting the following error, and have tried anything I could think of.

StructureMap.StructureMapConfigurationException: 'No default Instance is registered and cannot be automatically determined for type 'PotSmart.Data.Interfaces.IDbFactory'

I know StructureMap does not always have the clearest error messages, but I feel this meant my Entity model was not being initialized at run time for some reason.It fails during "factory.GetInstance(serviceType)". Has anyone had this error, or does anyone see what I am obviously overlooking in the code sets I have above that would cause this issue? Thanks a million as always in advance.

0

There are 0 answers