I am using the built in .net authentication in my project and am creating class entities in entity framework 4.0.
My classes are a Student, University and Company class. My question is can I inherit the System.Web.Security.MembershipUser class for these classes? The ef class already inherit the EntityObject class so I don't know how to do it?
thanks
Your question is a little lacking in detail but I have a go at answering.
To start you won't want to inherit from the MembershipUser class. You can (because its abstract) but you would only inherit from it if you were going to use your own logic and db tables to store the validation fields.
You wouldn't put Membership onto a University or Company class but on the members of those Entities e.g. a Student is a member of a University, as there are Employees to a Company.
Neither of the Student or Employee would have Membership information on them (within their db tables) but would more likely have information relating directly to them (e.g. an Employee has a Payroll number)
Student and Employee are both of type Person (e.g they both have Name, Address, etc.)
A Student or an Employee maybe a User of your Application (web site, desktop, etc.) but then they maybe not also, or they may be deactivated as a User but you want to keep their Person and Student/Employee information for your records.
A User will have the usual info like... UserId, Username and Password, etc. but you don't want to use this entity if you were going to put a DisplayName on the App. For security reasons, I also do not put Session information onto the User but use the UserId (encrypted MD5 one way encryption) and SessionId to validate my users Session, this means that if some how I did have a breach of security (SQL injection) the hacker would not be able to access Usernames and Password details. Anyway, I digress.
So, what is the MembershipUser class? It gets used mainly in your Authentication object which will have methods like... Login, ChangePassword, Logout, etc. These methods would call
if (!Membership.ValidateUser('username', 'password')) return false; etc.
If you wanted to use your own db tables and entityframework calls for the membership then you would look to implement a Custom Membership Provider, overriding all the standard methods and put you entity DAO requests (hopefully using Design Patterns e.g. Repositories etc.). This can be risky and difficult, but with experience not too big a deal.
Otherwise, just stick with the standard Membership (User) Provider, stick what it needs in the web.config file and have it deal with the security and you can get on with developing you Application...
a good book is Pro Asp.Net MVC Framework ... it goes through everything including unit-testing, design patterns, etc. Also a great way to spend some money is on the GOF (Gang of Four) design patterns source code... get the full works, best £60 spend ever.
I hope this helped.
Hugh
There is no EF provider, but you can write your own provider.
Write a mapper class for your MembershipUser derived class.
I found a nice example over here:
efmembership.codeplex.com
Related
I'm just getting started with DDD and implementing the Onion Architecture.
I'm making an invitation system, where a super user can invite another user by email to his company. However when creating the invitation, I want to ensure that the user is not already created in the system. I want to do that by checking if there's any record in the database with that email. I'm using Entity Framework to handle the database context.
And I've made a repository for both Invitation and UserAccount, that contain methods to find items based on an Id.
I need to use the DB context in order to see if the invitation is still valid, but since the method is declared in the Domain Layer, I can't really figure out how to do it, without breaking the design pattern. The Domain layer should not know anything about the persistence layer.
I thought about injecting the IUserAccountRepository and then executing the required methods in order to complete the Accept() method, but I'm afriad this is wrong.
The Domain layer should not know anything about the persistence layer.
That's right - the domain layer should not know about persistence.
But that constraint doesn't apply to the application layer.
In other words, we design our domain model interface so that it "asks for" the information that we (might) need to successfully compute the next state of the model, and the application has the problem of figuring out where that information comes from.
public UserAccount Accept(Guid userId, Boolean userExistsInDatabase)
What you will see in some designs, is that instead of passing in the answer to the question, we'll pass in the capability of asking the question, and let the model decide for itself whether the question should be asked and what to do with the answer
public UserAccount Accept(Guid userId, Roster roster)
In this case, Roster would be an interface defined by your model, that accepts some piece of information that the model already has and reports back some other piece of information that your model understands. Then your application would provide an implementation of this interface when invoking the method.
Passing values across the boundaries is a bit more "pure", in that the model code doesn't need to know anything about the failure modes of the Roster -- all of that code would instead live in the application layer.
It's OK to use Contracts in your Domain Services.
"IUserAccountRepository" is a Contract that we create in the domain and the domain service doesn't know about implementation.
So Do not worry about that it's right
I have a scenario in which I need advice on. I have an application where there are two kinds of users Student and Teacher. Student and Teacher share some of the common properties like FirstName, LastName, Email, UserName, Password etc. For this reason I derive Student and Teacher classes from User.
Now, the problem is that there are times where I don't really know that if the user is student or teacher. Like when implementing a custom membership provider and in the GetUser function. GetUser takes userName but now I lost that what should I return.
For Student functions I have created IStudent and ITeacher for teachers. But sometimes I just want to return a User and do not care about if he is student or teacher. But then returning base class does not seems like a good idea too.
UPDATE:
I think it is good idea to return User and not even have Student and Teacher classes. Student and Teacher are simply the roles and can be managed by StudentServices and TeacherServices.
A classic scenario and a classic runaway from the problem. Yes there is always pain to work with inheritance as they constrain. But benefits occur when you inject behavior into your class(es). Now it seems like you have decided for jut using User class and not having User as a base and child classes Teacher and Student. It can be a good idea if you make Teacher and Student as roles, but handling them in separate services... well it smells i my opinion. You'll likely end up with duplicate code in these services since they both need to handle User logics.
The fact is if you start to fend off difficulties like this by compensate in service layer, that's the road to an anemic domain model where logic leaks out from domain layer to gui or service layer.
What is unique with teacher and student and what logic/behavior differs should be represented in domain layer.
You can use inheritance (maybe the best solution) or making these as a role where you actually make Role as a custom Enum - Look at (I Think) Jimmy Bogard for how to extend a custom Enum with behavior.
I've recently started tinkering with ASP.NET MVC, but this question should apply to classic ASP.NET as well. For what it's worth, I don't know very much about forms authentication and membership providers either.
I'm trying to write my own MembershipProvider which will be connected to my own custom user table in my database. My user table contains all of the basic user information such as usernames, passwords, password salts, e-mail addresses and so on, but also information such as first name, last name and country of residence.
As far as I understand, the standard way of doing this in ASP.NET is to create a user table
without the extra information and then a "profile" table with the extra information. However, this doesn't sound very good to me, because whenever I need to access that extra information I would have to make one extra database query to get it.
I read in the book "Pro ASP.NET 3.5 in C# 2008" that having a separate table for the profiles is not a very good idea if you need to access the profile table a lot and have many different pages in your website.
Now for the problem at hand... As I said, I'm writing my own custom MembershipProvider subclass and it's going pretty well so far, but now I've come to realize that the CreateUser doesn't allow me to create users in the way I'd like. The method only takes a fixed number of arguments and first name, last name and country of residence are not part of them.
So how would I create an entry for the new user in my custom table without this information at hand in CreateUser of my MembershipProvider?
I think you should go on with your approach and add a new function in your implementation, I mean, overload the CreateUser method and have a CustomMembershipUser (that extends the MembershipUser) as a parameter.
In that way, before using the provider, cast it to your CustomMembershipProvider and use the overloaded method.
I agree with your analysis that you should keep both membership and profile information in the same table. Since you are correct that you are restricted by the number of parameters that CreateUser takes, you will need to design your field so that non-membership profile attributes are nullable. This does not mean that you will have required fields that are null in the database, however. Instead, you can you the below snippet:
string username = .../ retrieve username here
Membership.CreateUser(username , password, email);
ProfileBase newProfile = Profile.Create(username); //since the user has just been created, all properties will be blank
//set all entered properties
newProfile.SetPropertyValue("MyProp1", myProp1Value);
...
newProfile.SetPropertyValue("MyPropN", myPropNValue);
newProfile.Save();
In this way, you leverage ASP.NET's membership providers to create the user and save profile data, but to your end user it is a single atomic operation.
I'm having a hard time wrapping my head around how to use the Memberships in MVC. I know there is the built in ASPNETDB database which has all the basic tables for users and such. But what if I wanted to add a relationship between one of my custom tables and this built in user table?
If I had a database table that contained blog comments, we'll call it Comment. And each Comment had a userID associated with it could I do something like?
User.Comments.Add(someCommentObj)
Anyone know of a good article on this? Is this even possible?
Thanks
Have a look at this extensive article on the MembershipProvider:
https://web.archive.org/web/20211020202857/http://www.4guysfromrolla.com/articles/120705-1.aspx
Look at Part 6 and 7, you'll probably want to implement a custom ProfileProvider and store the comment reference in the Profile.
Part 6 - capture additional user-specific information using the
Profile system. Learn about the
built-in SqlProfileProvider.
Part 7 - the Membership, Roles, and Profile systems are all build using
the provider model, which allows for
their implementations to be highly
If you want to use your own custom membership tables then you'll need to build your own MembershipProvider. Matt Wrock has a walkthrough:
You'll notice that the default AccountModel allows you to inject your own provider:
public AccountMembershipService(MembershipProvider provider)
{
_provider = provider ?? Membership.Provider;
}
Nerdinner has an example of dependency injection that you would probably find useful:
Warning Here are two solutions that will work. The first one is easy. The 2nd one, I think is what you're after, but take it for what it's worth. Make sure you realize what you're doing, since this will take the membership provider data and access it directly, which could result in some hidden bombs if you're not careful (like deleting data).
The membership data is meant to just be used for authenticating; roles for authorizing; profiles for user speicific data (like time zone or favorite color.
Solution One
If you wanted to add a comment under the current user (or any user) you could do:
var comment = new Comment(....);
comment.userId = User.Identity.Name; //for user name
or
comment.userId = new Guid(Membership.GetUser().ProviderUserKey); //for guid in table
That's the eays way and you never really have direct access to the aspnet tables, you just use its info.
Solution Two
I'm assuming that you're using L2S and the designer in VS.
By adding the membership table(s) to your L2S design, you will get access to its data. This may even be preferable for some quick querying (like dates, lock out info, etc. since you don't have to use the built-in sprocs which have some serious over-kill and heavy code). If you create a relationship in the DB or in the L2S designer, you'll have a relationship that you can access like your question asks.
At this point, the designer has created your classes for comments and users. If you do anything with the actual user table you just created, you're circumventing the membership provider's design - don't do this unless you now what you're doing. When you add a comment to the User, it will add the comment to the comments tables with the correct relationship intact.
You should now be able to do:
var user = MyUser.GetById(userId);
user.Comments.Add(comment);
Remember, that the User in this case is different than when you do
var user = Membership.GetUser(userId);
Do most people use .NET's SqlMembershipProvider, SqlRoleProvider, and SqlProfileProvider when developing a site with membership capabilities?
Or do many people make their own providers, or even their own membership systems entirely?
What are the limitations of the SQL providers that would make you roll your own?
Is it easy to extend the SQL providers to provide additional functionality?
For Reference
Per Scott Gu's Blog, Microsoft provides the source code for the SqlMembershipProvider so that you can customize it, instead of starting from scratch. Just an FYI.
We use everything except the Profile Provider. The Profile Provider is completly text based and does full text seearches - this becomes exceedingly slow as you user base gets larger. We have found it a much better solution to "role our own" profile section of the membership api database that is keyed to the userid in membership.
I've rolled my own MembershipProvider classes using derived MembershipUser types to wrap the custom user schema, so profile-style properties are now available everywhere as part of the derived user via a cast.
I normally use the providers that come out of the box, the main problem I have is querying across profile attributes across users. For example finding all users that have a profile attribute called Car that equals true. This is down to the way they are stored in the underlying structure.
I've used SqlMembership before and it's quite nice, unless you need something custom. I remember needing something like firstname and lastname info and I realised there're no fields for that. In the end instead of extending I've used Comment field of the provider and added name info to there. This is probably a bad practice/lazy/hack way but it worked for me in a tight situation..
In theory they sound nice, but not a chance if you do any unit testing without creating lots of abstract wrappers.
If you only need the basic user support (roles, profiles, etc.) then the default providers will work great.
If you need more customized support (data storage in a database not supported by the default providers [like Oracle], provider on a database that already exists, a heavily customized schema) then you should roll your own providers.
As for me, my current site only needed basic Roles support (and minimal Profiles support), so I went with the default providers.
I have used both the custom classes and built in. When you need to get to a different database or schema or need to have extra info.
I abstracted out the layers so that it would work on the logic layer and have a DAL layer that used the data.common.dbprovider bit so it was reasonably generic.