Abstracting Identity 2.0 to domain model layer - c#

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?

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.

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>()))

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.

Related

Choose between adopting ASP.NET Identity and custom entity models?

By adopting ASP.NET Identity, I mean we reuse as many parts of it as possible including the IdentityDbContext and the related built-in models such as IdentityUser, IdentityUserClaim, ...
However when writing code with Entity Framework or even with any other frameworks, we commonly have our own BaseEntity class as the root of all other entities although it may even be empty, but in future we may need to add some common properties later.
So I've found that those 2 things cannot live together, I prefer to have a BaseEntity class but still re-using the ASP.NET Identity has its own benefit.
What would you do in this case? I have a feeling that the ASP.NET Identity has something faulted in design, it's not perfect and makes me confused while choosing the approach to go (when we have just one choice we can take it easy but when we have some choices we may need several days to evaluate and weight before ending up with the final hard decision).

Identity in ASP.NET Core (2.1): Why do we need to add a new Context to customize IdentityUser?

EDIT: I should probably add that in my project (which was based on the ASP.NET Core 2.1 - WebApp with MVC, with "Individual User Accounts), I don't have "AppUser" (or an equivalent class that inherits from IdentityUser), and ApplicationDbContext inherits from IdentityDbContext - not from IdentityDbContext (or IdentityDbContext).
I'm currently learning / starting with ASP.NET Core and use "Add New Scaffolding Item" to Add Custom user data to Identity and noticed that I cannot use the existing context (ApplicationDbContext) if I want the scaffolder to create my custom user class. The only way to have that field enabled is if I add a new context, which will also add a new connection string. But the new context seems to be essentially doing the same that my already existing context does.
I also noticed that the two new classes (AppExtendedContext and AppExtendedUser in my case) were put under Areas/Identity/Data, while I'd actually expect them to be under Data and Models.
So I was wondering: Why? ;-)
Or, to put it in more actionable terms: Would it be safe to refactor the generated code back to only use a single ApplicationDbContext? What would I be losing / what kind of trouble would I get myself into?
The answer could be as simple as "for pragmatic reasons" (e.g. because it makes the automatic code generation easier / safer); and in that case, moving these things around should be fairly safe as long as I'm not going to use the scaffolder again. But then again, it might make life more difficult/confusing when upgrading (e.g. to ASP.NET Core 2.2, or ASP.NET Core 3.0).
Just trash your AppExtendedContext and AppExtendedUser classes and use the ApplicationDbContext and AppUser and add your customizations there.
They are ready for modification (they inherit from IdentityDbContext<TUser> and IdentityUser<TKey> respectively. Feel free to rename them to something more familiar to your application (such as Customer or CustomerUser), if you don't like the AppUser name.
There's really no need to inherit from AppUser or ApplicationDbContext, they are the final/concrete classes for your Core Identity.
Make sure your context inherits from IdentityDbContext<>. You have to specify the type to use for your application user, which you can just create as a class that extends IdentityUser (given the fact you want to start extending the IdentityUser class). Go for something like YourCustomContextType : IdentityDbContext<YourCustomUserType>.
As for the Identity services registration you need to specify your class there too using AddDefaultIdentity<YourCustomUserType>().AddEntityFrameworkStores<YourCustomContextType>().
Make sure you also look at how other people approach extending the Identity functionality:
How to extend available properties of User.Identity

EF6 and layered architecture

I know this question come back again and again, I read a lot about it, but I can't find an answer to my question.
I dont have a lot of exp on asp.net mvc but I already did a project using ef, repository and uow pattern.
In my last project, I had several layers including :
Web (project MVC)
BLL (my business layer)
DAL (data acces, with ef context, repository and uow implementation)
Now, I want to start a new project, with EF6. I read that uow is not need and I want to give a try.
So far I understand that you must pass your dbContext to your services and your services to your controllers, am I right ?
So you must have a ref to entityFramework in your service layer too ? Still right ?
And because of identity implementation, you need a ref to entityFramework in your UI too.
So what's the point of layer anymore ?
If I read this microsoft guide, all I have to do its make a folder to my DAL and other layer ?! Dont seem right to me ... But maybe ?
I read this post too, who seem to confirm my opinion. And if you add unity and configure it in your UI, its just more ref in your UI :)
So my question is, if you must start a new project now, with EF6, asp.net MVC5, what will you do ?
Am I right to want to do layer ? Or just go on with my MVC project only ?
The ONE thing I miss, is a tuto who explain step to step how to start with microsoft MVC 5 template and transform it with layer, decoupling identity, and finally no ef ref in my UI. Is this thing exist ?
There is no silver bullet here. Some people do it one way, some - the other. Depending on level of abstraction needed. I used to have 3 projects:
Web
Core/Business (Services)
Model/EF/Domain (Entity Framework context and models)
And it's fine if Web has reference to Domain or EntityFramework. Web can return EF Models (just to avoid code duplications). And if you need more complex model, you create ViewModel.
I don't recommend using UoW or Repository pattern (unless you really need it). EF context is already an implementation of UoW pattern. If you want to implement repository pattern with Entity Framework, don't expose anything related to EF in the interface e.g. SaveChanges(), Dispose() as in this case you will not take advantage of repository pattern benefits.
So this is how I would build typical small/medium ASP.NET MVC + EF website. But like I said, everything depends on level of abstraction needed. Abstraction level is proportional to amount of code needed to write. So think first and keep it simple. Good luck.
I like the repository pattern very much, since it abstracts your actual data store from your client application. The front end doesn't need to know where the data comes from, it can be either from frameworks such as Entity Framework but it could as well be a simple converted DataTable. This is a generic approach and you can reuse it for all your future projects if your repository framework has passed all your tests. This tutorial gives you a good view on how to implement the combination of UOW and Repository pattern.
Basically your client application (=MVC) doesn't need to have a reference to Entity Framework, it is sufficient for your service layer to have a reference. You then use this reference to pass your own DbContext to the repository layer (assuming that you have written a repository layer for Entity Framework), ideally through DI containers like Unity.
Of course, there is a lot of discussion about whether or not to use the repository pattern with EF (as it already is an abstraction of your database) but I think it's a good exercice of creating and using reusable components.

Why is the IdentityUser class in the Microsoft.AspNet.Identity.EntityFramework namespace and not in the Core package?

Why is the IdentityUser class in the Microsoft.AspNet.Identity.EntityFramework package instead of being included in the Microsoft.AspNet.Identity.Core package?
Why should it depend on EntityFramework? It seems to be a simple class.
What am I missing?
I typically separate by Data layer from my DAL. Adding a dependency to EntityFramework for the IdentityUser class seems a bit much.
The design of the core of Identity is not coupled to EF or to any specific shape of user and role types. Everything is abstracted by the stores. In fact, for any given persistence provider, the types don't even need to be POCOs at all!
For Identity 3.0 we considered having our current types in core (in fact, at some point we had them there) but we got pretty solid feedback from people familiar with other persistence frameworks that although those types can comply to a common definition of "POCO", they are very EF specific.
We also considered having base classes in core that we would extend for EF in the EF package. We landed where we are because there didn't seem to be enough benefit in this. It was between adding the complexity of an extra layer of inheritance (more complexity would make it easier for us to introduce bugs) vs. the fact that the types themselves aren't that complex and that persistence provider writers who want to take them as a starting point are welcome to copy & paste the code.
You asked:
Why is the IdentityUser class in the
Microsoft.AspNet.Identity.EntityFramework package...Why should it
depend on EntityFramework?
This is because the out-of-the-box implementation for Identity actually depends on Entity Framework.
The ASP.NET site has the following article:
Overview of Custom Storage Providers for ASP.NET Identity which indicates:
By default, the ASP.NET Identity system stores user information in a
SQL Server database, and uses Entity Framework Code First to create
the database. For many applications, this approach works well.
However, you may prefer to use a different type of persistence
mechanism, such as Azure Table Storage, or you may already have
database tables with a very different structure than the default
implementation. In either case, you can write a customized provider
for your storage mechanism and plug that provider into your
application.
The same page also should answer your question in the comments about creating a custom implementation of IUser:
Customize the user class
When implementing your own storage provider, you must create a user
class which is equivalent to the IdentityUser class in the
Microsoft.ASP.NET.Identity.EntityFramework namespace:

If Entity Framework / DbContext is the DAL / Repository, where does it fit within 3-tier architecture?

I've been reading articles on StackOverflow and other sites all day about best architecture practices and there are just so many conflicting ideas and opinions.
I've finally settled on an approach, but I am having a really hard time deciding where to place the EF objects (DbContext, Fluent APIs, Seeding data, etc). Here is what I currently have:
ASP.NET MVC Project: The actual web project. Contains the standard views, controllers and View Models (inside a Models folder).
Domain Model Project: Contains all POCO classes that define the database (domain) objects. Currently, does not mention or reference any EF objects.
Service Layer Project: Contains service objects for each type of domain object (e.g., IProductService, IOrderService, etc). Each service references EF objects like DbSets and handles business rules - e.g., add a Product, fetch a Product, append a Product to an Order, etc.
So the question is, in this configuration, where do EF classes go? Initially I thought in the Service Layer, but that doesn't seem to make sense. I then thought to put them in the Domain Model Layer, but then it ties the Domain Models to EF, which is essentially a DAL / Repository. Finally, I thought about creating a separate DAL Project just for EF, but it seems like a huge waste considering it will likely have 3-4 files in it (DbContext and a few other small files).
Can anyone provide any guidance?
There is no need for Domain Model since it will be redundancy. EF classes directly can act as Domain Model and they are converted to View Models while sending it to View. EF can be separated into different class library. Most of them use repository pattern along with any ORM incase it would be easy if they go for replacement. But I've seen criticism over using repository pattern, check this out.
Here is what I do:
Data:
Has one class inheriting from DbContext.
It has all the db sets.
Overrides OnModelCreating.
Mapping primary keys and relationships.
Entities:
Has every POCO classes.
Each property is decorated with needed data annotations.
Services:
Each service has common methods (GetList(), Find(), Create(), etc.).
Business:
Called from clients, orchestrate using services to perform a specific task UserChangePassword (this will check if this can be performed, then perform the task, or return error/unauthorized statuses among many others to make the client shows the correct information regarding the task. This on my case is where I log.
Clients (Desktop/Web/Wpf/etc).
I'm not saying this is the best approach, I'm just sharing what's been working for me.

Categories

Resources