1

Startup.Auth.cs //I have added my DbContext here

// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ProjectPlannerContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

In the AccountController.cs I want to create an instance of service which needs UnitOfWork instance to do Database related stuff. So here is the code:

public AccountController()
{
    contactManager = new ContactManager(UnitOfWork);
}

where the UnitOfWork is a property defined like this:

public UnitOfWork UnitOfWork
{
    get
    {
        if (unitOfWork == null)
        {
            //Here the HttpContext is NULL
            unitOfWork = new UnitOfWork(HttpContext.GetOwinContext().Get<ProjectPlannerContext>());
        }

        return unitOfWork;
    }
}

I have a global Authorization filter applied, so when I run the application the first thing to do is to Login to the website(this will cause a request to AccountController's login method - and gives an error Object reference not set to an instance, because of the call to UnitOfWork in controllers constructor).

The strange thing for me is that if I comment the contactManager line in the constructor, upon Login Asp.NET MVC Uses a SignInManager defined like this:

public ApplicationSignInManager SignInManager
{
    get
    {
        return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
    }
    private set 
    { 
       _signInManager = value; 
    }
}

And this works perfectly, I can register (Object reference error not thrown here) and see that in the Database my User is inserted. So my question is why this happens, and how to initialize my Service if not in the constructor?

Actually there is workaround if I define the UnitOfWork like:

public UnitOfWork UnitOfWork
{
    get
    {
       if (unitOfWork == null)
       {
           unitOfWork = new UnitOfWork(ProjectPlannerContext.Create());
       }

       return unitOfWork;
    }
}

But this means that I should Create database context in every Controller..

What is the best practice/solution to that?

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
M.Veli
  • 519
  • 1
  • 6
  • 15
  • 6
    because it is not yet created, it gets created after controller instantiated – Ehsan Sajjad Jun 01 '16 at 17:54
  • 2
    This question has been asked *many* times - [here](http://stackoverflow.com/questions/28254247/mvc5-ninject-binding-and-httpcontext), [here](http://stackoverflow.com/questions/3432685/accessing-httpcontext-request-in-a-controllers-constructor), [here](http://stackoverflow.com/questions/6850073/why-cant-i-access-the-httpcontext-from-the-controller-initializer), [here](http://stackoverflow.com/q/24342887/181087), [here](http://stackoverflow.com/q/223317/181087). Ok, you go find the rest, there are tons more. – NightOwl888 Jun 01 '16 at 18:29
  • 1
    It has been asked many times but sometimes if you're looking for an answer you need the right question. – Carlo Luther Jul 09 '16 at 23:50

1 Answers1

2

I ended up with implementing BaseController which will be derived from other controllers, and here is the example:

public abstract class BaseController : Controller
{
    public virtual UnitOfWork UnitOfWork
    {
        get
        {
            return unitOfWork;
        }
    }

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);

        if (unitOfWork == null)
        {
            unitOfWork = new UnitOfWork(HttpContext.GetOwinContext().Get<ProjectPlannerContext>());
        }
    }

    #region Private members
    private UnitOfWork unitOfWork;
    #endregion
}

And AccountController which needs additional service (IContactManager):

public class AccountController : BaseController
{
    public AccountController()
    {

    }

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);

        contactManager = new ContactManager(UnitOfWork);
    }

    public ActionResult CreateContact(string firstName, string lastName, string email)
    {
        ContactModel contact = contactManager.Create(firstName, lastName, email);

        return JsonNet(new { contact = contact });
    }

    #region Private members
    private IContactManager contactManager;
    #endregion
}
M.Veli
  • 519
  • 1
  • 6
  • 15