UnitOfWork with Unity DI Not Persisting Context Changes - entity-framework

I am trying to set up UoW with Unity DI using .NET Framework, and everything works until I call the context.SaveChanges(), the ChangeTracker.HasChanges() in the context passed to the UoW shows false, so context changes are not persisting through to the UoW implementation. I have a feeling this is due to my registration of the UoW in the Unity container, as this is my first time setting this up. Does anything stand out as incorrect?
EDIT - I went around the UoW functionality and attempted to just call _context.SaveChanges() directly on my context and it still does not save. So it seems it's something beyond the UoW.
UnityConfig
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<IChildFamilyCareProviderLinkRepository, ChildFamilyCareProviderLinkRepository>();
container.RegisterType<IFamilyCareProviderRepository, FamilyCareProviderRepository>();
container.RegisterType<IFamilyCareProviderContactRepository, FamilyCareProviderContactRepository>();
container.RegisterType<IUnitOfWork, UnitOfWork>();
container.RegisterInstance(AutoMapperConfig.Mapper);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
UnitOfWork
public class UnitOfWork : IUnitOfWork
{
private readonly RAINContext _context;
public IFamilyCareProviderRepository FamilyCareProviders { get; private set; }
public IFamilyCareProviderContactRepository FamilyCareProviderContacts { get; private set; }
public IChildFamilyCareProviderLinkRepository ChildFamilyCareProviderLinks { get; private set; }
public UnitOfWork(RAINContext context,
IFamilyCareProviderRepository familyCareProviderRepository,
IFamilyCareProviderContactRepository familyCareProviderContactRepository,
IChildFamilyCareProviderLinkRepository childFamilyCareProviderLinkRepository)
{
this._context = context;
this.FamilyCareProviders = familyCareProviderRepository;
this.FamilyCareProviderContacts = familyCareProviderContactRepository;
this.ChildFamilyCareProviderLinks = childFamilyCareProviderLinkRepository;
}
public bool Save()
{
_context.ChangeTracker.HasChanges(); //THIS SHOWS FALSE
var success = _context.SaveChanges(); //No changes are saved to DB
return success > 0;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool dispose)
{
if (dispose)
{
_context.Dispose();
}
}
}
IUnitOfWork
public interface IUnitOfWork : IDisposable
{
IFamilyCareProviderRepository FamilyCareProviders { get; }
IFamilyCareProviderContactRepository FamilyCareProviderContacts { get; }
IChildFamilyCareProviderLinkRepository ChildFamilyCareProviderLinks { get; }
bool Save();
}
Controller
public class FamilyCareProviderController : Controller
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public FamilyCareProviderController(
IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
this._mapper = AutoMapperConfig.Mapper;
}
[HttpPost]
public ActionResult CreateFamilyCareProvider(CreateFamilyCareProvider vm)
{
try
{
var fcp = new FamilyCareProvider()
{
Id = Guid.NewGuid().ToString().ToUpper(),
FamilyCareProviderName = vm.FamilyCareProviderName,
IsActive = true,
CreatedById = UserId,
LastUpdatedById = UserId
};
_unitOfWork.FamilyCareProviders.Insert(fcp);
var fcpc = _mapper.Map<FamilyCareProviderContact>(vm.FamilyCareProviderContact);
_unitOfWork.FamilyCareProviderContacts.Insert(fcpc);
var result = _unitOfWork.Save();
return RedirectToAction(nameof(Index));
}
catch (Exception)
{
ModelState.AddModelError("", "Error saving family care provider contact.");
return View(vm);
}
}
}
Is there something that is obvious that stands out in the implementation of this?

Related

how do I change my unit of work to allow multiple dbcontexts?

How do I update this code below to allow for multiple DbContexts? I searched other posts and I tried to make my unit of work and dbfactory classes accept a generic type but I had trouble with the RepositoryBase class, the repository, the service and tying it all together; I still struggle with generics in C#. Can anyone help me out?
DbFactory.cs
public class DbFactory : Disposable, IDbFactory
{
WilMpeContext _dbContext;
public WilMpeContext Init()
{
return _dbContext ?? (_dbContext = new WilMpeContext());
}
protected override void DisposeCore()
{
_dbContext?.Dispose();
}
}
Disposable.cs
public class Disposable : IDisposable
{
private bool isDisposed;
~Disposable()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!isDisposed && disposing)
{
DisposeCore();
}
isDisposed = true;
}
// Ovveride this to dispose custom objects
protected virtual void DisposeCore()
{
}
}
iDbFactory.cs
public interface IDbFactory : IDisposable
{
WilMpeContext Init();
}
IRepository.cs
public interface IRepository<T> where T : class
{
// Marks an entity as new
void Add(T entity);
// Marks an entity as modified
void Update(T entity);
// Marks an entity to be removed
void Delete(T entity);
void Delete(Expression<Func<T, bool>> where);
// Get an entity by int id
T GetById(int id);
// Get an entity using delegate
T Get(Expression<Func<T, bool>> where);
// Gets all entities of type T
IEnumerable<T> GetAll();
// Gets entities using delegate
IEnumerable<T> GetMany(Expression<Func<T, bool>> where);
}
IUnitOfWork.cs
public interface IUnitOfWork
{
void Commit();
}
RepositoryBase.cs
public abstract class RepositoryBase<T> where T : class
{
#region Properties
private WilMpeContext _dataContext;
private readonly IDbSet<T> _dbSet;
protected IDbFactory DbFactory
{
get;
private set;
}
protected WilMpeContext DbContext
{
get { return _dataContext ?? (_dataContext = DbFactory.Init()); }
}
#endregion
protected RepositoryBase(IDbFactory dbFactory)
{
DbFactory = dbFactory;
_dbSet = DbContext.Set<T>();
}
#region Implementation
public virtual void Add(T entity)
{
_dbSet.Add(entity);
}
public virtual void Update(T entity)
{
_dbSet.Attach(entity);
_dataContext.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).AsEnumerable();
foreach (T obj in objects)
_dbSet.Remove(obj);
}
public virtual T GetById(int 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).FirstOrDefault<T>();
}
#endregion
}
UnitOfWork.cs
public class UnitOfWork : IUnitOfWork
{
private readonly IDbFactory _dbFactory;
private WilMpeContext _dbContext;
public UnitOfWork(IDbFactory dbFactory)
{
this._dbFactory = dbFactory;
}
public WilMpeContext DbContext
{
get { return _dbContext ?? (_dbContext = _dbFactory.Init()); }
}
public void Commit()
{
DbContext.Commit();
}
}
WilMpeContext.cs - this is one of my DbContexts but now I need another and I'm not sure how to implement that with my existing design
public class WilMpeContext : IdentityDbContext<ApplicationUser>
{
public WilMpeContext()
: base("name=DefaultConnection", throwIfV1Schema: false) { }
public IDbSet<AppSetting> AppSettings { get; set; }
//the rest of the tables were removed for brevity
public virtual void Commit()
{
base.SaveChanges();
}
public static WilMpeContext Create()
{
return new WilMpeContext();
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
Here is how I setup the repository to use the unit of work. AppSetting is a table in my model:
public interface IAppSettingRepository : IRepository<AppSetting>
{
void UpdateAppSetting(AppSetting appSetting);
}
public class AppSettingRepository : RepositoryBase<AppSetting>,IAppSettingRepository
{
public AppSettingRepository(IDbFactory dbFactory)
: base(dbFactory) { }
//an example of how I do something in the database. See I use DbContext from RepositoryBase
public void UpdateAppSetting(AppSetting appSetting)
{
DbContext.Entry(appSetting).State = EntityState.Modified;
}
}
And this is my service:
public class AppSettingService : IAppSettingService
{
private readonly IAppSettingRepository _appSettingRepository;
private readonly IUnitOfWork _unitOfWork;
public AppSettingService(IAppSettingRepository appSettingRepository,
IUnitOfWork unitOfWork)
{
_appSettingRepository = appSettingRepository;
_unitOfWork = unitOfWork;
}
//call repository to do database stuff and then commit changes
public void UpdateAppSetting(AppSetting appSetting)
{
_appSettingRepository.UpdateAppSetting(appSetting);
_unitOfWork.Commit();
}
}
You need to make all your interfaces and classes that is using your current WilMpeContext to generic. Also you would need to put a generic constraint on new generic.
First make your Interfaces generic for Unit of work and DBFactory:
public interface IUnitOfWork<TContext> where TContext: DbContext, new()
{
void Commit();
}
public interface IDbFactory<TContext> : IDisposable where TContext: DbContext, new()
{
TContext Init();
}
Now let's update your Classes for UnitOfWork and DBFactory:
public class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext: DbContext, new()
{
private readonly IDbFactory<TContext> _dbFactory;
private TContext _dbContext;
public UnitOfWork(IDbFactory<TContext> dbFactory)
{
this._dbFactory = dbFactory;
}
public TContext DbContext
{
get { return _dbContext ?? (_dbContext = _dbFactory.Init()); }
}
public void Commit()
{
this.DbContext.SaveChanges();
}
}
public class DbFactory<TContext> : Disposable, IDbFactory<TContext> where TContext: DbContext, new()
{
TContext _dbContext;
public TContext Init()
{
return _dbContext ?? (_dbContext = new TContext());
}
protected override void DisposeCore()
{
_dbContext?.Dispose();
}
}
Add an additional generic on Repository base class:
public abstract class RepositoryBase<T, TContext> where T : class where TContext: DbContext, new()
{
#region Properties
private TContext _dataContext;
private readonly IDbSet<T> _dbSet;
protected IDbFactory<TContext> DbFactory
{
get;
private set;
}
protected TContext DbContext
{
get { return _dataContext ?? (_dataContext = this.DbFactory.Init()); }
}
#endregion
protected RepositoryBase(IDbFactory<TContext> dbFactory)
{
DbFactory = dbFactory;
_dbSet = DbContext.Set<T>();
}
#region Implementation
public virtual void Add(T entity)
{
_dbSet.Add(entity);
}
public virtual void Update(T entity)
{
_dbSet.Attach(entity);
_dataContext.Entry(entity).State = System.Data.Entity.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).AsEnumerable();
foreach (T obj in objects)
_dbSet.Remove(obj);
}
public virtual T GetById(int 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).FirstOrDefault<T>();
}
#endregion
}
Here is your repository that will be typed with your Actual Context WilMpeContext class.
public class AppSettingRepository : RepositoryBase<AppSetting, WilMpeContext>, IAppSettingRepository
{
public AppSettingRepository(IDbFactory<WilMpeContext> dbFactory)
: base(dbFactory) { }
//an example of how I do something in the database. See I use DbContext from RepositoryBase
public void UpdateAppSetting(AppSetting appSetting)
{
DbContext.Entry(appSetting).State = System.Data.Entity.EntityState.Modified;
}
}
Finally your AppsettingService
public class AppSettingService : IAppSettingService
{
private readonly IAppSettingRepository _appSettingRepository;
private readonly IUnitOfWork<WilMpeContext> _unitOfWork;
public AppSettingService(IAppSettingRepository appSettingRepository,
IUnitOfWork<WilMpeContext> unitOfWork)
{
_appSettingRepository = appSettingRepository;
_unitOfWork = unitOfWork;
}
//call repository to do database stuff and then commit changes
public void UpdateAppSetting(AppSetting appSetting)
{
_appSettingRepository.UpdateAppSetting(appSetting);
_unitOfWork.Commit();
}
}
Now your UnitOfWork infrastructure will support any DbContext for all repositories.
Udpate
Alternative solution(May be)
May be I'm wrong but why would you need multiple dbcontext if your dbContext is not shared across the applications. I'm sure you are using Asp.net 5 MVC project that generates it's own IdenityDbContext and you might have your other DBContext as well. You can merge these two context and this way you can keep your current implementation of UOW.
Check out these SO QnA if this is the actual problem.
ASP.NET Identity DbContext confusion
Merge MyDbContext with IdentityDbContext

Unable to inject DBContext into my Web API 2 Controller with Unity

I've been at it for days, but I can't get Unity to inject anything with RegisterType<> into my Controller. I'm using Web Api 2, in Visual Studio 2015, with Unity 4. Whenever I try to inject IUnitOfWork or IRFContext, I get "message": "An error occurred when trying to create a controller of type 'ClPlayersController'. Make sure that the controller has a parameterless public constructor.".
I'm using the Unity.AspNet.WebApi to bootstrapp into WebApi. Below is my UnityWebApiActivator
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(mycompany.project.api.UnityWebApiActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(mycompany.project.api.UnityWebApiActivator), "Shutdown")]
namespace mycompany.project.api
{
public static class UnityWebApiActivator
{
public static void Start()
{
var resolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
I'm using a Start.cs due to Owin.
[assembly: OwinStartup(typeof(mycompany.project.api.Startup))]
namespace mycompany.project.api
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider(),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
}
My WebApiConfig.cs is below:
namespace mycompany.project.api
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
log4net.Config.XmlConfigurator.Configure();
config.MapHttpAttributeRoutes();
config.EnableSystemDiagnosticsTracing();
config.Services.Add(typeof(IExceptionLogger),
new SimpleExceptionLogger(new LogManagerAdapter()));
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
}
}
}
My UnityConfig.cs is below
namespace mycompany.project.api
{
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
public static void RegisterTypes(IUnityContainer container)
{
var config = new MapperConfiguration(cfg =>
{
//AutoMapper bindings
});
container.RegisterInstance<IMapper>(config.CreateMapper());
container.RegisterType<IRFContext, RFContext>(new PerThreadLifetimeManager());
container.RegisterType<IUnitOfWork, UnitOfWork>();
XmlConfigurator.Configure();
var logManager = new LogManagerAdapter();
container.RegisterInstance<ILogManager>(logManager);
}
}
}
All that I have in my Global.asax is below:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Error()
{
var exception = Server.GetLastError();
if (exception != null)
{
var log = new LogManagerAdapter().GetLog(typeof(WebApiApplication));
log.Error("Unhandled exception.", exception);
}
}
}
If my Controller is like this, it works fine:
public class ClPlayersController : ApiController
{
private readonly IMapper mapper;
public ClPlayersController(IMapper _mapper, IUnityContainer container)
{
mapper = _mapper;
}
But placing IUnitOfWork, like below, or the IRFContext, I get the error:
private readonly IMapper mapper;
private readonly IUnitOfWork unitOfWork;
public ClPlayersController(IMapper _mapper, IUnityContainer container, IUnitOfWork _unitOfWork)
{
mapper = _mapper;
unitOfWork = _unitOfWork;
}
I can't find, for the life of me, what I'm doing wrong. If I loop through the container.Registrations on the constructor, I find the mappings, but they refuse to get injected. Any hints?
EDIT
Below is the code for UnitOfWork and RFContext
namespace mycompany.project.data.configuracao
{
public class UnitOfWork : IUnitOfWork
{
private readonly IRFContext _rfContext;
private bool _disposed = false;
public UnitOfWork(IRFContext rfContext)
{
_rfContext = rfContext;
}
public void Commit()
{
if (_disposed)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
_rfContext.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing && _rfContext != null)
{
_rfContext.Dispose();
}
_disposed = true;
}
}
}
and
namespace mycompany.project.data.configuracao
{
public interface IUnitOfWork : IDisposable
{
void Commit();
}
}
and RFContext is a basic POCO generated DBContext
namespace mycompany.project.data.configuracao
{
using System.Linq;
public class RFContext : System.Data.Entity.DbContext, IRFContext
{
public System.Data.Entity.DbSet<ClGrupoEconomico> ClGrupoEconomicoes { get; set; }
//all my DbSets
public System.Data.Entity.DbSet<SpTipoLog> SpTipoLogs { get; set; }
static RFContext()
{
System.Data.Entity.Database.SetInitializer<RFContext>(null);
}
public RFContext()
: base("Name=RFContext")
{
}
public RFContext(string connectionString)
: base(connectionString)
{
}
public RFContext(string connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model)
: base(connectionString, model)
{
}
public RFContext(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{
}
public RFContext(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, bool contextOwnsConnection)
: base(existingConnection, model, contextOwnsConnection)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new ClGrupoEconomicoConfiguration());
//all my Configuration classes
modelBuilder.Configurations.Add(new SpTipoLogConfiguration());
}
public static System.Data.Entity.DbModelBuilder CreateModel(System.Data.Entity.DbModelBuilder modelBuilder, string schema)
{
modelBuilder.Configurations.Add(new ClGrupoEconomicoConfiguration(schema));
//all my configuration classes
modelBuilder.Configurations.Add(new SpTipoLogConfiguration(schema));
return modelBuilder;
}
}
}
Unfortunately the exception you are seeing can occur for several reasons. One of them is when Unity cannot resolve one or more of your injections.
An error occurred when trying to create a controller of type
'FooController'. Make sure that the controller has a parameterless
public constructor.
So, based on the information in your question your setup is apparently correct, since IMapper can be injected. Therefore I guess that UnitOfWork and RFContext have dependencies that Unity cannot resolve. Maybe a repository?
UPDATE:
The problem here is that your RFContext has several constructors.
https://msdn.microsoft.com/en-us/library/cc440940.aspx#cnstrctinj_multiple
When a target class contains more than one constructor with the same
number of parameters, you must apply the InjectionConstructor
attribute to the constructor that the Unity container will use to
indicate which constructor the container should use. As with automatic
constructor injection, you can specify the constructor parameters as a
concrete type, or you can specify an interface or base class for which
the Unity container contains a registered mapping.
In this case Unity doesn't know how to resolve your RFContext, and will try to use the constructor with the most parameters. You can solve it by using
container.RegisterType<IRFContext, RFContext>(new InjectionConstructor());

Troubles with dependency injection

I am working on an ASP.NET WebAPI using OWIN. To manage the instances of DBContext (Entity Framework), I try to use Ninject. However, when I call a controller, the programm returns an error:
The controller cannot be created, missing constructor.
Could you tell me what is going wrong here?
My Controller Class:
public class Testcontroller
{
private IApplicationDbContext _context;
public Testcontroller(IApplicationDbContext context)
{
_context = context;
}
}
This is the Ninject-File:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<IApplicationDbContext>().To<ApplicationDbContext>();
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
}
}
Ninject Dependency Scope:
public class NinjectDependencyScope : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.GetAll(serviceType);
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
// This class is the resolver, but it is also the global scope
// so we derive from NinjectScope.
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernel) : base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
The Entity Framework DbContext-Class:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public virtual DbSet<Models.Team> Teams { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
public interface IApplicationDbContext
{
DbSet<Models.Team> Teams { get; set; }
int SaveChanges();
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
I tried to follow this tutorial: http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api
What have I done wrong here?
Thanks in advance!
Unless there was a serious omission in you controller code, your controller is not inheriting from ApiController, as is expected with Web Api
public class TestController : ApiController {
private IApplicationDbContext _context;
public Testcontroller(IApplicationDbContext context) {
_context = context;
}
}
UPDATE
I tried to set up everything from scratch using this: http://www.alexzaitzev.pro/2014/11/webapi2-owin-and-ninject.html
For some reason, it now works out perfectly fine.
Thank you for your support!

How can I achieve the following using IOC?

I want to use IOC with my service and I want to instead inject a class not an interface in the constructor as below in the services layer but I do not want to create a new object from the calling layer like var service = new InvoiceService(new ChangeInvoiceDueDateCommand()) instead I want to create something like this from my controller in MVC where the IInvoiceService is injected into the controller constructor but the problem I see is that
public InvoiceController(IInvoiceService invoiceService, IMapper mapper)
{
_invoiceService = invoiceService;
_mapper = mapper;
}
and then called like this
public ActionResult ChangeInvoiceDueDate(InvoiceChangeDueDateViewModel invoiceChangeDueDateViewModel )
{
var request = _mapper.Map<InvoiceChangeDueDateViewModel, ChangeInvoiceDuedateRequest>(invoiceChangeDueDateViewModel);
InvoiceChangeDueDateResponse response = _invoiceService.ChangeDueDate(request);
return View();
}
Service Layer
public class InvoiceService : IInvoiceService
{
private readonly ChangeInvoiceDueDateCommand _changeInvoiceDueDateCommand;
public InvoiceService(ChangeInvoiceDueDateCommand changeInvoiceDueDateCommand)
{
_changeInvoiceDueDateCommand = changeInvoiceDueDateCommand;
}
public InvoiceChangeDueDateResponse ChangeDueDate(ChangeInvoiceDuedateRequest invoiceChangeDueDateRequest)
{
_changeInvoiceDueDateCommand.Execute(invoiceChangeDueDateRequest);
return new InvoiceChangeDueDateResponse {Status = new Status()};
}
}
Command
public class ChangeInvoiceDueDateCommand : ICommand<ChangeInvoiceDuedateRequest>
{
private readonly IRepository<Invoice> _invoiceRepository;
readonly InvoiceDueDateChangeValidator _validator;
public ChangeInvoiceDueDateCommand(IRepository<Invoice> invoiceRepository)
{
_invoiceRepository = invoiceRepository;
_validator = new InvoiceDueDateChangeValidator();
}
public void Execute(ChangeInvoiceDuedateRequest request)
{
if (_validator.IsDuedateValid(request.NewDuedate))
{
Invoice invoice = _invoiceRepository.GetById(request.Id);
invoice.ChangedDueDate(request.NewDuedate);
_invoiceRepository.SaveOrUpdate(invoice);
}
else
{
throw new InvalidDueDateException();
}
}
}
ICommand
public interface ICommand<T> where T : IRequest
{
void Execute(T request);
}
IRequest
public interface IRequest
{
int Id { get; set; }
}
I worked it out. It was just a Windsor syntax issue. It ended up being as simple as registering the Command using the container.Register(Component.For<ChangeInvoiceDueDateCommand>());

Instance in Caliburn Micro

We are using Caliburn Micro for the first time.
We have a AppBootstrapper inherited from ShellViewModel.
Situvation is that VieModels should have the same instance unless it is reset.
we are able to achieve shared or not shared everytime, but releasing the export whenever needed is still a mystery.
public class AppBootstrapper : Bootstrapper<ShellViewModel>
{
private static CompositionContainer _container;
protected override void Configure()
{
try
{
_container = new CompositionContainer(
new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x))));
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(_container);
StyleManager.ApplicationTheme = ThemeManager.FromName("Summer");
_container.Compose(batch);
}
catch (Exception exception)
{
}
}
public static void ReleaseAll()
{
}
protected override object GetInstance(Type serviceType, string key)
{
try
{
var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
var exports = _container.GetExportedValues<object>(contract);
if (exports.Any())
return exports.First();
throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
}
catch (ReflectionTypeLoadException ex)
{
foreach (Exception inner in ex.LoaderExceptions)
{
// write details of "inner", in particular inner.Message
}
return null;
}
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
try
{
return _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
}
catch (Exception exception)
{
return null;
}
}
protected override void BuildUp(object instance)
{
_container.SatisfyImportsOnce(instance);
}
}
ShellViewModel
[Export(typeof(ShellViewModel))]
public sealed class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public ShellViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
Items.Add(compositionContainer.GetExportedValue<AViewModel>());
Items.Add(compositionContainer.GetExportedValue<BViewModel>());
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
public void B()
{
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.B.ToString()));
}
public void A()
{
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public void RESET()
{
AppBootstrapper.ReleaseAll();
ActivateItem(Items.Single(p => p.DisplayName == AppMessageType.A.ToString()));
}
public enum AppMessageType
{
A,
B
}
}
AViewModel
[Export(typeof(AViewModel))]
public sealed class AViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public AViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
DisplayName = ShellViewModel.AppMessageType.A.ToString();
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
}
BViewModel
[Export(typeof(BViewModel))]
public sealed class BViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<object>
{
[ImportingConstructor]
public BViewModel(CompositionContainer compositionContainer, IEventAggregator eventAggregator)
{
DisplayName = ShellViewModel.AppMessageType.B.ToString();
CompositionContainer = compositionContainer;
EventAggregator = eventAggregator;
eventAggregator.Subscribe(this);
}
public IEventAggregator EventAggregator { get; set; }
public CompositionContainer CompositionContainer { get; set; }
public void Handle(object message)
{
//throw new System.NotImplementedException();
}
}
Now AViewModel and BViewModel have single instance.
Whenever Release Button is clicked i want to have new instance of AViewModel and BViewModel.
Hoping to get a reply soon.
Regards,
Vivek
When working with an IoC container, the only part of your code that should take it as a dependency should be your composition root (i.e. your AppBootstrapper in this case). You shouldn't be injecting or referencing the container anywhere else in your code (except possibly factories).
If you want your ShellViewModel to control the lifetime of your child view models (A and B), then you should consider injecting view model factories into your ShellViewModel (via constructor injection if they are required dependencies).
Your AViewModelFactory would just have a single Create method that returns a new instance of AViewModel, likewise with the BViewModelFactory. You can simply new up your view models directly in the factories. If your view models have large dependency chains themselves, then you could consider adding a reference to your container in the factories, although preferably consider looking into the MEF ExportFactory<T> type.