How can I integrate EF 5.0 with membership provider using code first?
I have my own database schema which I want to use for registration of users etc.
You should take a look at the SimpleMembershipProvider
It is very easy to use it together with EF.
Update
For MVC4 I would start with the blank template.
you need WebSecurity.InitializeDatabaseConnection to set up the database.
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "UserName", true);
It takes as parameters a name of a connectionstring, the table, a unique identifier column and the username-column.
The model I use for this piece of code above is:
[Table("Users")]
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string UserName { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
To log someone in:
WebSecurity.Login(aUsername, aPassword);
The method above returns a bool, if it is true, login was successfull.
In the Web.config you do not need to define a membershipProvider as it was with default ASP.NET Membership.
If you need to gain access to the provider (to delete an account):
var provider = (SimpleMembershipProvider) Membership.Provider;
provider.DeleteAccount(aUsername); // Delete the account
provider.DeleteUser(aUsername, true); // delete the user and its data
For creating a new user (with my given model in this case)
WebSecurity.CreateUserAndAccount(aUsername, aPassword, new { Email = aEmail, FirstName = aFirstName, LastName = aLastName });
Benefit is, that you can now use your model for other EF classes as a foreign key without having the hassle when you want to do this with the normal asp.net membership. :-)
http://msdn.microsoft.com/en-us/library/f1kyba5e
This is actually nothing to do with EF.
EF is just a way to read data.
See also FORMS Authentication
http://support.microsoft.com/kb/301240?wa=wsignin1.0
Related
I have a Posts model class that has a relation with Users model.
When I call API to get Posts with the owner of it (user), it returns with all user info including password.
How to prevent model from returning sensitive information like passwords?
You should create new classes that you return from your actions. Only include the fields/information you want to return.
These classes are also known as Data Transfer Objects (DTO).
You can use [JsonIgnore] to avoid serializing the property value:
public class Users
{
public int Id { get; set; }
[System.Text.Json.Serialization.JsonIgnore]
public string Password{ get; set; }
//...
}
When we apply the migration to an Asp Net Core Identity application, the system creates a set of basic Identity tables, where each table has its own columns. For example: the AspNetUsers table has its own set of columns, and it is possible to add new columns to that table.
Is it possible to remove columns?
If I don't want to use a particular column, is it possible to remove it?
Ofcouse you can.Take the AspNetUsers table as an example.
First:Create a new ApplicationUser
public class ApplicationUser:IdentityUser
{
//add a new colum
public string FullName { get; set; }
//remove a EmailConfirmed colum
[NotMapped]
public override bool EmailConfirmed { get; set; }
}
In your DbContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
In your startup(Change IdentityUser to ApplicationUser).
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
In your Views/Shared/_LoginPartial,change to
#inject SignInManager<ApplicationUser> SignInManager
#inject UserManager<ApplicationUser> UserManager
Then Migrate and generate database.
Test Result:You can see successfully add FullName and remove the EmailConfirmed colums.
For more details,you can see the doc.
Note:What you need to pay attention to is that many of these columns contain built-in methods of Identity. If you delete some of these columns, it may result in abnormal usage of Identity, so you need to be careful when deleting these columns.
Using ASP.NET Core identity, I create a new user with UserManager.CreateAsync() and assign them to an existing role with UserManager.AddToRoleAsync. This works, as the realtion between user and role is stored in the AspNetUserRoles table of the database.
But when I fetch the user using the UserManager (e.g. UserManager.FindByMail() method) then the Role list is empty. I also tried the Include function from EF like this:
var user = userManager.Users.Include(u => u.Roles).FirstOrDefault(u => u.Email == "test#test.de");
This gave me the Ids of the n:m association table, which is not very usefull as I need the role names. Loading them using a second query is also not possible, since the Roles attribute of the identity user is readonly. I would expect to get a List<string> of the role-names. Couldn't find any information about this.
For me the only workaround seems to add a custom attribute to my user and fill them with the data, which I fetch using a second query. But thats not a nice solution. Cant belive that ASP.NET Core Identity has no better way of getting those data...
UserManager does not load the relations by default.
The manual inclusion is a good way but as stated here - direct M:N relationships are not yet supported by EntityFramework Core.
So there are two ways I see:
(The preffered one) Use
userManager.GetRolesAsync(user);
This will return a List<string> with user's role names. Or use some EF query to get an IdentityRole objects by joined IdentityUserRole. Unfortunatelly, this requires an acceptance with the fact the roles will not be directly in the User entity.
OR you can implement custom IdentityUserRole, create a relation to IdentityRole there and then query it with `
Include(user => user.Roles).ThenInclude(role => role.Role)
How to implement own Identity entities is described e.g. here. But it's complicated approach and the Role objects will be nested in the binding entities.
However, you can declare a property in your ApplicationUser:
[NotMapped]
public List<string> RoleNames {get; set;}
and use it at you free will...
Here is the solution I came up with. It may not be the most efficient. Hope it helps someone.
public class UserVM
{
public string Id { get; set; }
public string UserName { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Roles { get; set; }
}
// Project each element of query into List<UserVM>
var list = (from user in _userManager.Users
select new UserVM
{
Id = user.Id,
UserName = user.UserName,
Name = user.Name,
Email = user.Email
}).ToList();
list.Select(async user =>
{
var userEntity = await _userManager.FindByIdAsync(user.Id);
user.Roles = string.Join("; ", await _userManager.GetRolesAsync(userEntity));
}).ToList();
I need assistance with gathering Active Directory data based on a table in my DB. I have an entity class that holds user requests. Each request has the user's windows name from System.Web.HttpContext.Current.User.Identity.Name. My problem is I cannot figure out how to setup a linq query to associate the AD username to the rest of the AD so I can display their full names instead of their username in my table. Here is what I have so far, any help will be appreciated.
public partial class RequestInfo
{
public int RequestInfoId { get; set; }
public string RequestByUserADId { get; set; }
public System.DateTime RequestDateTime { get; set; }
public string Explanation { get; set; }
public virtual UserInfo UserInfo { get; set; } // where I define my custom roles
}
I can query AD by using the code below. I have tried Get Active Directory User Information With Windows Authentication in MVC 4, but it did not help.
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
using (UserPrincipal user = UserPrincipal.FindByIdentity(context, requestByAdId))
{
return user.DisplayName
}
I may be off here because I am not sure if you are able to successful establish a user principal or not but if you have the user principal you can get property information like the following:
user.GetProperty("propertyName")
Here is a static method that should get you the department for a user, for example.
public static String GetDepartment(UserPrincipal principal)
{
return principal.GetProperty("department");
}
Let me know where this gets you and I can elaborate further if this isn't working.
Edit
It appears you need to go one level deeper to get the fields that aren't by default a part of the user principal. For this you will need to get the directory entry from the user principal first:
DirectoryEntry directoryEntry = (userPrincipal.GetUnderlyingObject() as DirectoryEntry);
Then you need to check if the attribute you are looking for exists, and if it does, get the value. A great way to do this is to create a helper method that you pass your directory entry to along with the string value for the property name that you want to get.
public string GetProperty(DirectoryEntry directoryEntry, string propertyName)
{
if (directoryEntry.Properties.Contains(propertyName))
{
return directoryEntry.Properties[propertyName][0].ToString();
}
else
{
return string.Empty;
}
}
Please note that going to the underlying object is expensive. I believe this operation, by default, is cached for you so subsequent use of this information can be retrieved from cache. Playing around with
directoryEntry.RefreshCache
will get you started with that.
Let me know if this does the trick for you!
I'm looking to do partial updates on a web api controller action by using the Delta wrapper.
I have a model like such:
public class Person
{
public Guid PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
public int NumVacationDays { get; set; }
public double Salary { get; set; }
}
I have the api controller like such:
public void Put(Delta<Person> person)
{
var p = person.GetEntity();
Person existingPerson = _repository.Get(p.PersonId);
person.Patch(existingPerson);
_repository.Update();
return;
}
I make the call to the web api like such (using fiddler)
url: http://localhost:49933/api/Person (PUT)
Response Body
{
"PersonId": "b269c49f-8a90-41d6-b102-7cfba3812b1c",
"FirstName": "sample string 2",
"LastName": "sample string 3",
"IsActive": true,
"NumVacationDays": 5,
"Salary": 6.1
}
The controller is hit and al
l the data is populated other than the NumVacationDays (which is 0) and the PersonId (which defaults to 00000000-0000-0000-0000-000000000000)
Does anyone know why the GUIDs and int fields are not populating from the json?
This problem is mentioned in this bug: http://aspnetwebstack.codeplex.com/workitem/562 ...Claims to be fixed but still exists in the 4.0 just released.
The problem being that Newtonsoft Json deserializes a number as Int64 which fails test that IsAssignable to an int, and so it is skipped. Similar issue for guids as strings.
You are supposed to be able to fix this by using the OData media type formatters, which are enabled by deriving from ODataController instead of ApiController. However this had no effect for me - int values still do not work (but when I change the data type to Int64, it works).
I would love to see a working example of posting json with a patch delta that contains an int.
I can venture a guess for what is happening with PersonId but NumVacationDays cannot be explained. My guess is that PersonId is the key property for the Person entity and by default the ODataFormatter does not patch key properties. If you want that behavior, you can change the setting on ODataMediaTypeFormatter.PatchKeyMode to Patch.
Also, it would be interesting to see the value of person.GetChangedPropertyNames() in the action to see if PersonId and NumVacationDays actually show up there or not.