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?

3
  • 6
    because it is not yet created, it gets created after controller instantiated Commented Jun 1, 2016 at 17:54
  • 2
    This question has been asked many times - here, here, here, here, here. Ok, you go find the rest, there are tons more. Commented Jun 1, 2016 at 18:29
  • 1
    It has been asked many times but sometimes if you're looking for an answer you need the right question. Commented Jul 9, 2016 at 23:50

1 Answer 1

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
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.