Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstracting Identity 2.0 to domain model layer

I'm trying to implement Identity 2.0 in my ASP.NET MVC 5 solution that abides the onion architecture.

I have an ApplicationUser in my core.

namespace Core.DomainModel
{
    public class ApplicationUser {...}
}

In my Data Access Layer I'm using Entity Framework 6.1 and my context derives from IdentityDbContext and herein lies the problem. ApplicationUser needs to derive from Microsoft.AspNet.Identity.EntityFramework.IdentityUser

namespace Infrastructure.DAL
{
    public class TestContext : IdentityDbContext<ApplicationUser> {...}
}

My domain model shouldn't reference Microsoft.AspNet.Identity.EntityFramework that would go against the idea of the onion.

What's a good solution?

like image 882
Snæbjørn Avatar asked Aug 12 '14 13:08

Snæbjørn


3 Answers

The problem is that you are trying to use the Onion pattern. In its foundations that you will always build dependencies.

Thrive for single responsibility of your models you are creating. You can do easily this by trying to follow Domain Driven Design properly by implementing individual models per layer:

  • BusinessLogic.Models.ApplicationUser
  • Presentiation.Models.ApplicationUser
  • DAL.Models.ApplicationUser

Note that all of those models are different classes even if they have 100% same properties (although it is never 100%). The drawback is that you may need to map from one model to another, but if you are trully aim for clean, modular and extensible architecture - that is the way. Hint you can use Automapper (or ExpressMapper) to avoid code needed for mapping.

like image 93
Vladimir Moushkov Avatar answered Nov 07 '22 09:11

Vladimir Moushkov


Yep, this is the big problem with the Identity framework which I have found no good solution yet.

I contemplated adding EF to my domain project, but decided against it in one project: domain models are not aware about ApplicationUser, only using Id for the current user which they get from

ClaimsPrincipal.Current.Claims
    .FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)
    .Value

In that project I kept all Identity code in Web and Data projects.

In my other project I have added Identity and EF all over the place, including Domain project. And guess what? nothing bad happened.

I also have looked on solutions like already provided link to Imran Baloch' blog. It looked like a lot of work to me to gain no customer value.

Just to repeat myself, there is no good solution to separate EF from Identity without rewriting a pile of code (don't like it). So either add EF to your Domain project (don't like it) or keep your Identity code in Web/Data project (sometimes not possible, so I also don't like it).

Sorry to say, but this is a low-level limitation of .Net.

like image 44
trailmax Avatar answered Nov 07 '22 07:11

trailmax


You can inherit IUser from the Core namespace and the usermanager will be happy. You will need to replace the IUserStore with your own implementation. Then initializer the user manager something like:

new UserManager<ApplicationUser>(new YourNameSpace.UserStore<YourApplicationUser>()))
like image 31
Philip Nelson Avatar answered Nov 07 '22 09:11

Philip Nelson