I just upgraded my MVC2 project to MVC3 and used the NuGet library package reference to install ninject. This created an appstart class and i used the following code to inject my IMembershipService class.
public static void RegisterServices(IKernel kernel) {
kernel.Bind<IMembershipService>().To<AccountMembershipService>();
}
This works great with my HomeController, for example.
public class HomeController : Controller
{
public IMembershipService MembershipService { get; set; }
public HomeController() : this(null) { }
public HomeController(IMembershipService service)
{
MembershipService = service;
}
HOWEVER, I am using a BaseController. Nearly the same code in the base class no longer works.
public class BaseController : Controller
{
public IMembershipService MembershipService { get; set; }
public UserService UserService { get; set; }
public BaseController() : this(null, null) { }
public BaseController(IMembershipService service, UserService userService)
{
MembershipService = service;
UserService = userService ?? new UserService();
}
If I break in the constructor of the base controller, service is just NULL. I have never used Ninject for IOC so perhaps the answer is obvious, but why will it not inject my AccountMembershipController in the base class like I want it to? I don't see what is different, although i realize the extra level of inheritance may be messing with Ninject somehow.
Your HomeController dervices from Controller, not BaseController? Also, you have a default constructor for BaseController that sets things as null. Why do you have that at all? I'd start by getting rid of those default constructors. You shouldn't need any default constructors.
I ran into this same problem myself. Assuming your code looks like this:
public HomeController : BaseController
{
}
public BaseController : Controller
{
public IMembershipService MembershipService { get; set; }
public MembershipService() { }
public MembershipService(IMembershipService service)
{
MembershipService = service;
}
}
For some reason, Ninject thinks that HomeController only has one constructor, the default parameterless one. When you put everything in HomeController, it can find the injectable constructor, but factor it out into a base class and for some reason it won't look in the base class to see if there are any overloaded constructors. There are two fixes for this:
Remove the default constructor. This is my preferred solution because it forces the constructor to be injected (like when you create the controller manually when unit testing), but the downside is that you have to implement the constructor in all your subclasses.
Keep the default constructor, but add the [Inject] attribute to all your injectable properties:
public BaseController : Controller
{
[Inject] public IMembershipService MembershipService { get;set; }
// rest is the same
}
Ninject will inject the properties correctly this way, but be aware that Ninject will call the parameterless constructor.
Related
I am working with a database where I have more than 75 tables and I am using the repository and unit of work patterns with Entity Framework in an ASP.NET MVC project. I am little bit confused and some query in my mind about object creation. When UnitOfWork initializes, it creates object for all table's entity which is present in UnitOfWork. So it can be heavy for application load.
Here is the interface of unit of work:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Application.Repository;
using Application.Repository.General;
namespace Application.UnitOfWorks
{
public interface IUnitOfWork : IDisposable
{
IGeneralRegionMasterRepository GeneralRegionMasters { get; }
IGeneralSubRegionMasterRepository GeneralSubRegionMasters { get; }
IGeneralCountryMasterRepository GeneralCountryMasters { get; }
IGeneralStateMasterRepository GeneralStateMasters { get; }
IGeneralCityMasterRepository GeneralCityMasters { get; }
int Complete();
}
}
Implementation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Application.EntityFramework;
using Application.Repository;
using Application.Repository.General;
namespace Application.UnitOfWorks
{
public class UnitOfWork : IUnitOfWork
{
public readonly InventoryDbContext _context;
public UnitOfWork(InventoryDbContext context)
{
_context = context;
GeneralRegionMasters = new GeneralRegionMasterRepository(_context);
GeneralSubRegionMasters = new GeneralSubRegionMasterRepository(_context);
GeneralCountryMasters = new GeneralCountryMasterRepository(_context);
GeneralStateMasters = new GeneralStateMasterRepository(_context);
GeneralCityMasters = new GeneralCityMasterRepository(_context);
}
public IGeneralRegionMasterRepository GeneralRegionMasters { get; private set; }
public IGeneralSubRegionMasterRepository GeneralSubRegionMasters { get; private set; }
public IGeneralCountryMasterRepository GeneralCountryMasters { get; private set; }
public IGeneralStateMasterRepository GeneralStateMasters { get; private set; }
public IGeneralCityMasterRepository GeneralCityMasters { get; private set; }
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
}
I want to know about performance effect of it on application. Thank you in advance for help.
I've run into the same problem that you are describing in the past. The structure of the code just feels really heavy since you are creating new instances of 70 repositories even though you may only need one of them. This is why I've just started to avoid adding my own UoW and Repositories when using EF directly because EF already has Repositories and UoW built in (DbSets = Repos, Save Changes does UoW save at the end of all DbSet changes). If you don't want to code directly against a DbContext, just have your DbContext implement the IUnitOfWork interface directly and go off of that. Also have all your DbSets exposed on that UnitOfWork. Then you could have it also implement IMyDbContext and have that expose the DbSets and have this interface also implement IUnitOfWork (or have DbContext -> IMyDbContext -> IUnitOfWork) or break them up if you don't want repo code having access to Save at the bottom. This just ends up making it easier in the long run. No weird code to maintain, no classes to create. If you switch to not use EF, you can still use those same interfaces behind the scenes and the only thing that would have to change would be the DbSet implementation (maybe you can even get that to be generic - create your on DbSets that implement another interface, too). Personally, I'm going down the CQS path so I don't have to worry about repos or UoW anymore. :)
Edit
Example the best I can here! :)
public interface IUnitOfWork
{
int Complete();
Task<int> CompleteAsync();
}
public interface IInventoryDbContext : IUnitOfWork
{
DbSet<GeneralRegionMaster> GeneralRegionMasters { get; }
DbSet<GeneralSubRegionMaster> GeneralSubRegionMasters { get; }
... etc
}
public class MyDbContext : DbContext, IInventoryDbContext
{
public DbSet<GeneralRegionMaster> GeneralRegionMasters { get; set; }
public DbSet<GeneralSubRegionMaster> GeneralSubRegionMasters { get; set;
}
public int Complete() => this.SaveChanges();
public Task<int> CompleteAsync() => this.SaveChangesAsync();
}
If you did a controller level only:
public class MyController : Controller
{
private readonly IInventoryDbContext _context;
public MyController(IInventoryDbContext context)
{
_context = context;
}
public JsonResult CreateGeneralRegionMaster(GeneralRegionMaster entity)
{
_context.GeneralRegionMaster.Add(entity);
var result = _context.Complete();
return Json(result == 1);
}
}
Again, you could do something different for the DbSets and do this instead:
public interface IRepo<T> where T: class
{
// Expose whatever methods you want here
}
public class MyDbSet<T> : DbSet<T>, IRepo<T> where T: class
{
}
Then this changes:
public interface IInventoryDbContext : IUnitOfWork
{
IRepo<GeneralRegionMaster> GeneralRegionMasters { get; }
IRepo<GeneralSubRegionMaster> GeneralSubRegionMasters { get; }
... etc
}
public class MyDbContext : DbContext, IInventoryDbContext
{
public MyDbSet<GeneralRegionMaster> GeneralRegionMasters { get; set; }
public MyDbSet<GeneralSubRegionMaster> GeneralSubRegionMasters { get; set; }
public IRepo<GeneralRegionMaster> GeneralRegionMastersRepo => GeneralRegionMasters;
public IRepo<GeneralSubRegionMaster> GeneralSubRegionMastersRepo => GeneralSubRegionMasters;
public int Complete() => this.SaveChanges();
public Task<int> CompleteAsync() => this.SaveChangesAsync();
}
Re:
When UnitOfWork initializes, it creates object for all table's entity which is present in UnitOfWork. So it can be heavy for application load.
You don't need to initialize all the repo instances in the UoW constructor.
You can create them when they are required in the corresponding getters (lazy initialization):
private IGeneralRegionMasterRepository _generalRegionMasters;
public IGeneralRegionMasterRepository GeneralRegionMasters {
get {
if (_generalRegionMasters == null) {
_generalRegionMasters = new GeneralRegionMasterRepository(_context);
}
return _generalRegionMasters;
}
}
You need to have a context class that derives from DbContext when you're using Entity Framework.
Asp.net Identity uses EF and the default template creates the below class:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
This class does not derive directly from DbContext. For my own data (my classes that I want to persist to the db) should I create my own db context class?
If I want to do an operation that will update both the identity user and one of my own classes, I need to use both contexts. So this does not feel very natural.
Should I keep using the ApplicationDbContext class as context for my own classes as well? Would that work?
What is the best method to use EF for my own classes while using identity?
Use a single Context class inheriting from IdentityDbContext. See this answer for more info.
You need to add DbSets for all your classes into the ApplicationDbContext.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", false)
{
}
//Public DBSets
public DbSet<LeaveApplication> LeaveApplications { get; set; }
public DbSet<LeaveStatus> LeaveStatus { get; set; }
public DbSet<Department> Departments { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
I was trying to set a property in the constructor af a controller like this:
public ApplicationUserManager UserManager { get; private set; }
public AccountController()
{
UserManager = HttpContext.GetOwinContext().Get<ApplicationUserManager>("");
}
But as explained here:
https://stackoverflow.com/a/3432733/1204249
The HttpContext is not available in the constructor.
So how can I set the property so that I can access it in every Actions of the Controller?
You can move the code into a read-only property on your controller (or a base controller if you need it available across your entire application):
public class AccountController : Controller {
private ApplicationUserManager userManager;
public ApplicationUserManager UserManager {
if (userManager == null) {
//Only instantiate the object once per request
userManager = HttpContext.GetOwinContext().Get<ApplicationUserManager>("");
}
return userManager;
}
}
I'm starting to working on ASP.NET using MVC. I writing to action results, one of them is a HTTP GET and the another HTTP POST
[HttpGet]
public ActionResult DoTest()
{
Worksheet worksheets = new worksheets(..);
return View(w);
}
[HttpPost]
public ActionResult DoTest(Worksheet worksheet)
{
return PartialView("_Problems", worksheet);
}
Now, Worksheet class has a property called Problems and this is a collection, but uses as an abstract class item.
public class Worksheet
{
public List<Problem> Problems { get; set; }
}
Here's my abstract class and one implementation
public abstract class Problem
{
public Problem() { }
public int Id { get; set; }
public abstract bool IsComplete { get; }
protected abstract bool CheckResponse();
}
public class Problem1 : Problem
{
...
public decimal CorrectResult { get; set; }
// this is the only property of my implementation class which I need
public decimal? Result { get; set;}
public override bool IsComplete
{
get { return Result.HasValue; }
}
protected override bool CheckResponse()
{
return this.CorrectResult.Equals(this.Result.Value);
}
}
I have right now, many implementations of Problem class, but I really need to get just one value of my implementation class. But it thrown the above image error.
What can I do to allow model binder recover that part of my abstracts classes
The following code would not compile:
var problem = new Problem();
... because the Problem class is abstract. The MVC engine cannot just create a Problem directly. Unless you give it some way to know which type of Problem to instantiate, there's nothing it can do.
It is possible to create your own ModelBinder implementation, and tell MVC to use it. Your implementation could be tied to a Dependency Injection framework, for example, so that it knows to create a Problem1 whenever a Problem class is requested.
Or you could simply change your action method to take a concrete type:
public ActionResult DoTest(IEnumerable<Problem1> problems)
{
return PartialView("_Problems",
new Worksheet {
Problems = problems.Cast<Problem>().ToList()
});
}
I am implementing Ninject dependency injection in an existing MVC 2 application that uses a base controller that all controllers inherit to set navigation and other information needed by the master page. When I set a controller to inherit from the base controller, I get the following error: "...BaseController' does not contain a constructor that takes 0 arguments. How do I get around this error? I am new to Ninject and can't figure this out.
public class BaseController : Controller
{
private INavigationRepository navigationRepository;
private ISessionService sessionService;
public BaseController(INavigationRepository navigationRepository, IMembershipService membershipService, ISessionService sessionService)
{
this.navigationRepository = navigationRepository;
this.sessionService = sessionService;
}
}
public class HomeController: BaseController
{ ... }
Adding that ctor is one way
public class HomeController: BaseController
{
public HomeController(INavigationRepository navigationRepository, IMembershipService membershipService, ISessionService sessionService)
: base(navigationRepository, membershipService, sessionService) { }
}
or property injection
public class BaseController : Controller
{
[Inject]
public INavigationRepository navigationRepository { get; set; }
[Inject]
public ISessionService sessionService { get; set; }
}