Implementing your own UserManager, UserStore without Entity Framework - c#

I'm looking for any insight and/or links for how to implement my own login/registration system for a MVC project. IS it worth using UserManager and UserStore? When you create a new MVC application it relies on Entity framework, thus I'm wondering if it's worth creating my own login/registration process or to use UserManager and UserStore but no longer rely on Entity? Additionally would it perhaps be easier to rely on Entity for that stage of the registration/loging in but create my own table/retrieval methods independent of entity?
To sum up:
1) Should i switch from Entity to use UserManager/UserStore
2) Create my own custom create/manage account controller /models
3) Hybrid it up where I used Entity for logging in / registration and then having my own additional table for additional data just keeping bare data on the entity manage Table.
Thanks!

Related

.Net Core 3.1 logged in user assistance

I'm looking for assistance here. I've built an application that uses .NET Core 3.1, identity, and EF Core. I've extended aspnetusers to include additional columns. My company uses stored procedures for all other db queries.
My question is how do I go about getting the currently logged-in users' information and using this information (that includes the custom extended identity) in a FromSqlRaw select statement against the database. Currently, my user is hard-coded but this should be whoever is logged into the application.
This is what I currently have.
Select * from dbo.CustomerList where usercode = 'BobS';
My guess is to use claims but I'm not sure why my code isn't working.
I'm assuming that at your entry point you already have the logged in User, most likely from the HttpContext.
You could inject the UserManager into your current class and load the user via something like this.
var user = await _userManager.GetUserAsync(HttpContext.User);
This user object then should contain all the fields including custom fields of the efcore entity that you created.
You can then extend your efcore dbcontext to map results of raw sql queries and run something like this.
var customers = context.CustomerList
.FromSqlInterpolated($"Select * from dbo.CustomerList where usercode = {user.Code}")
.ToList();
For further reference you might consult the following links:
https://learn.microsoft.com/en-us/ef/core/querying/raw-sql
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.usermanager-1?view=aspnetcore-5.0
In general using ORM frameworks like the entity framework while coding most of the application logic inside of the database via stored procedures might not be the best approach. Usually I create most of the business logic in .NET querying necessary data via the ORM framework and only using store procedures / functions via the raw query option for performance critical scenarios or when the mapping of the ORM framework fails.

ASP.NET Identity DBContext or Site DB Context?

I've been kind of out of the .net game for a while and I wanted to try the different new technologies.
I set up a site that uses code first migrations with EF 6 and MVC. The DBContext is created in my DAL and I'm using a repository / unit of work / n-tier implementation. I've created a User entity that holds profile information and a DBContext, let's call it SiteDbContext.
Now I'm at the MVC part and I'm trying to figure out the ASP.NET Identity. I have a few questions:
1) Should I use the ApplicationDBContext created in the UI along with SiteDbContext or dispose the ApplicationDBContext and use SiteDbContext (and just make sure it inherits IdentityDbContext)?
2) If I use the same DBContext, will it be a problem if I create a dependency on the asp.net identity in my DAL layer? Entity Layer (for ApplicationUser)? I don't want to create a dependency on my DAL regarding the DBContext so how would I supply it to the OwinContext?
3) I would like to use different DBContexts but I'm wondering how I'd make navigation properties to my User to the ASP.NET Identity user, vice versa etc.
Are there example projects I can download that implement multiple DBContexts or combine preexisting DBContexts with the ApplicationDBContext?
Thanks!
Eitan

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:

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?
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.

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