I'm new to ASP.Net Identity, and I'm looking for a good tutorial for using Identity in conjunction with other classes in my model.
As an example I have a basic Ratings class that looks like this (from a project not using Identity)
public class Rating
{
public int Id { get; set; }
public Product Product { get; set; }
public User User { get; set; }
public int Stars { get; set; }
public string Comment { get; set; }
public bool Active { get; set; }
}
And a User Class that looks a bit like this
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public ICollection<Rating> Ratings { get; set; }
}
Looking for a way to achieve the same with Identity. My test project is set up with MVC5, and code first
The recommended solution is to add the properties you need to the ApplicationUser class
You can also use your own "User table", in your case that would be the User class. You'd have to inherit from IdentityUser.
This article has examples of how to do both.
I agree with Rui.
Here is a site that will teach you How to Extend Identity Accounts and also Implement Based Authentication. When I was starting with Identity, that site taught me a lot.
As a related hint: Watch out when you implement a Unit of Work pattern in your project. ASP.NET identities datacontext needs to be the same as the Uow datacontext, otherwise the whole think will crash.
A good starting point may be this: ASP.NET Identity with Repository and Unit of Work
Related
I just upgraded my .net 4.8 MVC web app to .net6.
I used Sessions to store objects.
for example the User class:
public class User
{
[Key]
public string UserID { get; set; }
public string TenantId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MobilePhone { get; set; }
public bool IsEnabled { get; set; }
public virtual ICollection<Department> Departments { get; set; }
}
This is how I set the session:
Session[Consts.CURRENTUSER] = userFromDb;
This is how I use it:
User _currentUser = Session[Consts.CURRENTUSER] as User;
Now, after the upgrade it does not compile. I get the following error:
Error CS0103 The name 'Session' does not exist in the current context
If i use the following HttpContext.Session[Consts.CURRENTUSER] as User it still does not allow the the above use.
Will appreciate an example on how I will be able to use the above scenario in .net core.
after reading Microsoft docs, I followed this guide from step 4 to allow the usage of Sessions.
Then, in order to use complex objects in .net core I followed this link which provided an extension method that implementing the use of complex objects in sessions.
Microsoft Identity introduces UserManager<T> and RoleManager<T> classes to interact with AspNetUsers, AspNetRoles and the other database tables. But why we should use them? Maybe it is a better solution to scaffold the database and work with its tables directly using the Entity Framework and forget about classes UserManager<T> and RoleManager<T>?
Why am I asking?
I my application I want to follow the multitier architecture.
I started with creating the DTO-class for the user:
public class UserDto
{
public string Id { get; set; }
public string UserName { get; set; }
...
public List<RoleDto> Roles { get; set; }
}
public class RoleDto
{
public string Id { get; set; }
public string Name { get; set; }
...
}
Type IdentityUser I want to map into UserDto, type IdentityRole - into RoleDto.
As you can see, in UserDto I want to store roles of a user.
Now let's have a look at the IdentityUser type: link.
It contains a lot of properties, but it doesn't have roles of the user.
So, when mapping IdentityUser into the UserDto, I need to work with RoleManager<T> to get roles of the user. I think, it's a dirty solution.
My idea
We can forget about UserManager<T> and RoleManager<T> types. We can simply scaffold the database and work with it using the Entity Framework.
After scaffolding of database I have the following:
public partial class AspNetUser
{
public string Id { get; set; }
public string UserName { get; set; }
public string NormalizedUserName { get; set; }
public string Email { get; set; }
public string NormalizedEmail { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string ConcurrencyStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public DateTimeOffset? LockoutEnd { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual ICollection<AspNetUserRole> AspNetUserRoles { get; set; }
public virtual ICollection<AspNetUserToken> AspNetUserTokens { get; set; }
}
// AspNetUserClaim, AspNetUserLogin, AspNetUserRole and AspNetUserToken
I introduced only AspNetUser class to be short. As you can see, it has a property AspNetUserRoles - roles of the user. It's great, because now it's really simple to map this class into the UserDto.
Question
Is it a good idea to scaffold the database and don't work with UserManager and RoleManager classes?
Maybe you can introduce a better solution?
Why do you think that this is a good idea? What would you gain by re-writing something like identity?
From the Introduction to Identity on ASP.NET Core
ASP.NET Core Identity:
Is an API that supports user interface (UI) login functionality.
Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.
It's not just database access. It is also code that manages login functionality, secure token creation, secure password management and much more.
You need to take all of the above into consideration if you create a custom system, have an external auditor to pen-test your solution (even though this is a good idea whatever choice you make), unit test, performance test etc.
All the above is already done. You can easily customize the identity with various hook points too.
BTW, identity uses ef to access the datastore already by default.
Do structure your multilayer application, but leave identity out of it. It is a horizontal concern and it's presence is there to simplify your development and let you worry about your business needs only.
So I have a few model classes generated by entity framework and I want to customize at least one to fit my project needs. Here is the generated class:
public partial class Token
{
public string token_admin { get; set; }
public string username { get; set; }
public string password { get; set; }
}
And here is how I want to customize it:
public partial class Token : IdentityUser
{
public string token_admin { get; set; }
public string username { get; set; }
[JsonIgnore]
public string password { get; set; }
}
Obviously each time the models are generated, the IdentityUser and decoration [JsonIgnore] disappear, making it hard to be consistent in my web api returns and impossible to find users using the http filter I setup... (the latter is actually a whole different problem on it's own)
I've been searching but can't find a clear answer to what is required to do here. Any suggestions?
FYI, this is part of a school lab so be lenient on the quality of what I do ;)
You should not have to modify the Entity models because you should not return Entity models from your WebApi.
Create a separate Token class in your WebApi project and map it with entity framework's model class.
All,
I have read this article:
How AspNet Identity with my model
where the ApplicationUser has an additing property of
public int AddressId { get; set; }
that is a new property on the ApplicationUser.
But what I am wondering is what if I have a custom entity of my own and I want it to have a property that relates to the Application user:
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public ApplicationUser CurrentlyBorrowedBy { get; set; }
}
or
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public Guid CurrentlyBorrowedBy { get; set; }
}
The reason I might want to do this is so I can call a method like GetAllBooksBorrowedForUser(userid) for example.
Do I set the properties type to ApplicationUser as show above
or
use a Guid because the DataType of the Id on ApplicationUser is a Guid
or
is this the completely wrong way to do it?
All suggestions welcome.
Note: this is just psuedo code as I just want an understanding of this before I dive into my project.
thanks
Russ
From what I know, it should be:
public int CurrentlyBorrowedByID { get; set; }
public virtual ApplicationUser CurrentlyBorrowedBy { get; set; }
Where the ApplicationUser instance allows you to easily navigate
All,
Of course after finishing writing my question I found the answer right in front of me.
The sample and blog post written by pranav rastogi here:
http://blogs.msdn.com/b/webdev/archive/2013/10/20/building-a-simple-todo-application-with-asp-net-identity-and-associating-users-with-todoes.aspx
explains how do do what I am talking about.
Still, feel tree to comment as there is more than one way to skin a cat.
thanks
Russ
I am currently working on an event calendar website and I am still a novice when it comes to ASP.NET. I am using the MVC4 Framework, as well as the EntityFramework (CodeFirst) and the SimpleMembershipProvider, which comes with the MVC4 template. I am also using Migrations - If that is from any interest.
What I've got so far
I do currently have two models, with a one-to-many relationship, which work just fine:
_Events.cs (had to name it that way, because event is reserved)
public class _Event
{
public int _EventId { get; set; }
public string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public virtual List<Comment> comments { get; set; }
}
Comment.cs
public class Comment
{
public int CommentId { get; set; }
public string Text { get; set; }
public int _EventId { get; set; }
public virtual _Event _Event { get; set; }
}
The problem
Now, I would like to add another one-to-many relationship between Comment and the User from the Membership model, but can't seem to figure out how to do so.
The goal I would like to archieve is, that I can have a list of commments for each event and print out the user information for each comment. I tried several things, but could not get it to work yet. My last attempt looks like this:
public class Comment
{
// snip - see above
public virtual UserProfile User { get; set; }
}
I would like to thank you very much for any help in advance.
You need to have UserId in your Comments as so.
public class Comment
{
// snip - see above
public int UserId {get; set;}
public virtual UserProfile User { get; set; }
}
You will also need to set the relationship between your Comment and your User so in your account controller have something like this.
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
In an ASP.net MVC project if you want to use default Microsoft Membership Provider, note that you need to implement membership system like role provider to have relationships and navigation and more functionalists between your created models and membership system. Microsoft Stores User related info at the separate place (like databases in App_Data folder) in your project.
So you need to store other models to Microsoft storage place, work with Microsoft functions directly and set connection string for this purpose OR implement Microsoft Membership to store User Info at relevant database like this NUGET Package that implements codefirst membership provider in C#. You can install this package and learn to write your own membership provider. More helps will be found by searching 'custom membership provider for MVC or aspnet membership provider'.