I am trying to implement a custom membership provider in ASP.NET MVC 3 with the Enitty Framework. For the user data I created a User class that holds all the login data plus some more.
When I tried to implement the MembershipProvider, some methods appeared that I need to implement which have a MembershipUser parameter in the signature:
public override void UpdateUser(MembershipUser user)
I know I can make my User class inherit the MembershipUser class and this won't be a problem. But when I tried to make it inherit, I couldn't set values for the readonly properties, like Email and others.
Is there any way that these methods can accept an object of type User? Or maybe there is some other better approach to this?
References
http://msdn.microsoft.com/en-us/library/ms152065.aspx
Custom MembershipUser with only needed parameters
http://www.codeproject.com/Articles/165159/Custom-Membership-Providers
Answer
You can create instances of MembershipUser and pass the properties (readonly or not) on the constructor, and then return that MembershipUser instance.
The documentation for the MembershipUser class has a quote that helped me to understand this better:
Creating a new MembershipUser object does not add a new membership
user object to the membership data store.
If adding the custom properties is important that will require you to subclass MembershipUser.
For an example see: Custom MembershipUser with only needed parameters
The last reference link shows a nice article with a custom membership provider using Linq-to-Sql rather than EF but the similarities are many.
Hope that helps.
Related
I have an asp.net mvc project that uses asp.net Identity to authenticate users. The database has been designed in entity framework designer.
There is a table named "Farmers" and I want to allow each farmer to login to the application. As I know in order to achieve this, the farmer must inherit from IdentityUser, but how can I do this in entity framework designer?
what is your mvc version??
in mvc5 this is a good response
http://blogs.msdn.com/b/webdev/archive/2013/10/16/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates.aspx
for this way u can mixed the two tables.
the other way is create an relationship between the two tables an use
User.Identity.Name or
User.Identity.GetHashCode
an use this to obtain the values of connected user
After a lot of hours of research I figured out that inherit from ApplicationUser or IdentityUser is not possible using the Entity Framework Designer.
My solution is to create a Code First Model from the existing database and then inherit from ApplicationUser.
As far as I know you can't really do that and I would argue that you shouldn't even try to do that even if you could.
By inheriting from IdentityUser you are saying that the Farmer can be described by properties like SecurityStamp, Roles or PasswordHash (inherited from IdentityUser) which does not make that much sense from a design point of view.
If what you are looking for is having a direct association between a user and a farmer you could simply add a required UserId property in you Farmer model. So whenever you create a new UserIdentity instance you also create a new Farmer instance as well with the UserId set to be the Id property of the newly created UserIdentity.
I´ve added some custom attributes to UserProfile asp.net membership table, lastname, address, cellphone, etc. So
I can create new users using.
WebSecurity.CreateUserAndAccount(UserName, Password,
propertyValues: new
{
UserId = model.userId,
UserLastName = model.lastName,
UserAddress = model.address,
.
.
}
);
So I want to know if it´s possible in similar way achieve an update query, including this custom attributes.
Thank you.
Yes you can. However I do not think WebSecurity provides a way to update extra column in membership tables e.g. UserProfile through its API.
This is how we did it, we have MVC4 ASP.NET internet application project and we are using EF5.0 Code First.
You already know how to add extra column in the UserProfile table (table name can be anything).
Once we have a class (that has all required extra columns along with UserId and UserName),
Added a controller UserController dedicated to facilitate CRUD operation for UserProfile.
UserController uses a UserService class in business layer that is taking care of all CRUD operation on UserProfile class (entity).
On Edit Post operation, controller call UserService class UpdateUser() method which looks like below:
public void UpdateUser(UserProfile user)
{
Guard.ArgumentNotNull(user, "user");
if (_roleWrapper.GetRolesForUser(user.UserName).Any())
{
_roleWrapper.RemoveUserFromRoles(user.UserName, _roleWrapper.GetRolesForUser(user.UserName));
}
if (!_roleWrapper.IsUserInRole(user.UserName, user.Role))
{
_roleWrapper.AddUserToRole(user.UserName, user.Role);
}
_dataContext.Update<UserProfile>(user);
}
Above text and sample is for example only, you can simplify it. Basically you need to get hold of UserProfile class and using DbContext to update it manually. WebSecurity has limited APIs keeping simplicity in mind.
Hope that helps (if anything confusing please let me know, i will expand further).
I have a class set up to hold values on a registration form (VB.NET, MVC), and among the properties is a Password property:
Public Class RegisterModel
...
Private _password As String
<DisplayName("Password:"), Required(), ValidatePasswordLength(), DataType(DataType.Password)> _
Public Property Password() As String
Get
Return _password
End Get
Set(ByVal value As String)
_password = value
End Set
End Property
This works great when registering a new user, but I'd like to use the same class to update existing users. (Note: this app is run by an admin who is in charge of registering individuals and assigning passwords.) The way I'd like it to behave is if the admin leaves the password blank, then the password is not changed, but the rest of the information is. If I use this class, the password can't be left blank because it fails on the Required() and ValidatePasswordLength() calls.
Is there a way to use this class but tell the model to ignore these particular validations? Even if I leave the password field off my edit form, it still fails. Do I need to create a whole duplicate class without these restrictions on the password field? There must be a better way.
You could implement IDataErrorInfo and have a flag set on the model which indicates whether it is being used by an admin or not - you could then validate conditionally.
But overall, I'd say this is a bit of a code smell. You're using a model for two different, incompatible purposes. It'd be better to use a separate view model.
I'd recommend using the FluentValidation library. It's a fantastic way to separate the concerns of your view (view model) and the actual validation you want to perform. You could pass parameters into it to drive different behavior. Check out When/Unless conditions or just writing completely custom validation methods with the Must operator.
public class RegisterModelValidator: AbstractValidator<RegisterModel>
{
public RegisterModelValidator(bool isAdmin)
{
RuleFor(x => x.Password).NotEmpty().Unless(isAdmin);
...
}
}
As long as your view model would have identical properties in both scenarios, you should use the one view model and one validation class. If the model varies at all I'd use two view models as David recommends.
You can do this in 2 ways:
1: add the [ValidateInput(false )] attribute to the action
or
2: Add a new property to the Register Model
public bool IsNewUser {get;}
3: Create a new class level attribute that takes IsNewUser into account when validating
I've managed to successfully implement a custom MembershipProvider for my MVC2 application. I have my own User table as well as Role table.
My problem right now is that when I put in the [Authorize(Roles="blah")] attribute, it doesn't work. I've searched a bit but haven't found a definitive answer I'm looking for, which is -- how does this Role authorization work? My web.config uses the standard AspNet role provider.
My understanding is that I have to have my User.cs class implement the IPrincipal interface, which means, adding the code to check for IsInRole.
My question(s) -- is this correct? How does the framework know to and know how to get my custom User object? My understanding is that the Asp.Net authentication & authorization pieces work with MembershipUser.
Any tips, thoughts, or links would be greatly appreciated,
Thx
Is your roles table / code an implementation of a RoleProvider? I believe the IPrincipal works against the default RoleProvider as configured in the web.config.
This forum post talks about what you would need to do in order to implement your own IPrincipal, if need be.
Ok, I think I figured it out, I'm just a little blind.
Since I created my own custom MembershipProvider (with its own custom User table AND Role table), it only stands to reason that I had to implement a custom RoleProvider. So, once I did that, it all makes sense, because the RoleProvider has the IsUserInRole method, i.e.
public override bool IsUserInRole(string username, string roleName)
{
IUserRepository userRepository = GetUserRepository();
User user = userRepository.Retrieve(username);
// and here, my User class implements IPrincipal
if (user != null && user.IsInRole(roleName))
return true;
else
return false;
}
I am currently building a custom Membership Provider for my Asp.net MVC website. I have an existing database with a Users table and I'm using Linq-to-Sql to automatically generates this class for me.
What I would like to do is have this generated User class inherit from the MembershipUser class so I can more easily use it in my custom Membership Provider in methods such as GetUser. I already have all the necessary columns in the table.
Is there any way to do this? Or am I going about this the completely wrong way?
Thanks!
Usually code generation tools creates so called partial classes, like:
public partial class User
{
// class definition here
}
This means that you can extend definition of that class somewhere within the same namespace like that:
public partial class User: MembershipUser
{
// if MembershipUser doesn't have parameterless constructor then you need
// to add here one
}
And then you'll have User class inheriting from MembershipUser.