Question

I'm trying to integrate the recently released ASP.NET Identity 2.0.0 into a 3-layer MVC application. I'm not sure I'm going in the correct direction. I can see two approaches to take.

In the first approach, I've gone with integrating Identity into each logical layer. Having some technical issues integrating but still developing.

In the second approach, go with a a self-contained encapsulated assembly dedicated for security.

I've gone with approach 1 at the moment, but questioning it all. Also, any other approaches to take?


Approach 1

Web
Startup.cs
/App_Start/Startup.Auth
/Controllers/Account
/Controllers/Manage
/Controllers/RolesAdmin
/Controllers/UserAdmin
/ViewModels
/Views

Business Logic
/Service/AccountService
/Service/ApplicationRoleManager
/Service/ApplicationUserManager
/Service/EmailService
/Service/SmsService
/Service/SignInHelper

Data
ApplicationDbContext
ApplicationUser

So, I've simply taken Identity and plugged it into each layer I see that fits. I've put most of the log in the Business Logic layer, as it doesn't belong in the Web and there no 'real' database code for it to belong in the Data layer.

Side-issue: I'm a bit uncomfortable that in the Web/App_Start/Startup.Auth, I have to instantiate the Busness Logic object to call

app.CreatePerOwinContext(ApplicationDbContext.Create);

in the Data layer. I've yet to think about this more. This is another issue (but I see it is related to the architecture I've chosen).


Approach 2

Creating an assembly purely for Security which contains no layers, i.e. simply plug in Identity 2.0.0 into this one assembly. And my application can reference this. It goes against the layers though. But it encapsulates security. Given security objects can (or should) be resident throughout the application lifetime, this doesn't seem like a bad idea at all. Haven't thought about about scalability though.

Was it helpful?

Solution

I have taken approach 1, and when creating the context I have a helper class that I attempt to get the context from HttpContext.Current.["DbActiveContext"] and use it if it exists, if not create then new one, and use a single context for the entire application. So you do not end up with one context for aspnet idenity and another one for the rest of the app. It looks like you are trying to use a repository pattern in the first approach, if that is the case, then your model for your identity should be in the DB layer, and for full repository pattern, you should be using dependency injection when creating your objects, by doing so, you will not have a dependency until the object is created at run time.

namespace Data.Common
{
    public class ConnectionHelper : IConnectionHelper
    {
        private ApplicationDbContext _context;

        public ApplicationDbContext Context
        {
            get
            {
                 if (_context == null && HttpContext.Current.Items["DbActiveContext"] != null)
                {
                    _context = (ApplicationDbContext)HttpContext.Current.Items["DbActiveContext"];
                }
                else if (_context == null && HttpContext.Current.Items["DbActiveContext"] == null)
                {
                    _context = new ApplicationDbContext();
                    HttpContext.Current.Items.Add("DbActiveContext", _context);
                }
                return _context;
            }
            set { _context = value; }
        }
    }
}

Also if you want to use the usermanager in the service layer with DI you can do something like:

 public UserController()
         : this(
             new ApplicationUserManager(new UserStore<ApplicationUser>(new ConnectionHelper().Context)),
             new UserService())
    {

    }

With the UserService signature like:

public class UserService
{
    private readonly IRepository<ApplicationUser> _user;
    private readonly UserManager<ApplicationUser> _userManager;

    public UserService(IRepository<ApplicationUser> user,
        UserManager<ApplicationUser> userManager)
    {
        _user = user;
        _userManager = userManager;

    }

    public UserService()
        : this(
            new Repository<ApplicationUser>(new ConnectionHelper()),
            new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new   ConnectionHelper().Context)))
    {

    }

I hope this helps you!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top