2

Is there anything holding me back from just doing the whole membership, roles, and profiles custom, without inheriting from the abstract classes like MembershipProvider, etc.?

MSDN clearly states: "When implementing a custom role provider, you are required to inherit the RoleProvider abstract class." (http://msdn.microsoft.com/en-us/library/system.web.security.roleprovider.aspx)

However, as I'm going along here, I'm finding that I'm really customizing the whole thing to our specific needs, and in many cases, I'm not even implementing what's inherited, but instead going my own way. One example of what I'm doing is the "GetAllRoles" method. .NET wants me to implement a method that returns a string array. I find this doesn't meet my needs, as a "Role" in our case contains much more information than just a name --- we have descriptions of roles in multiple languages, for example. So I went and made my own custom class called ProjectRole, and made my GetAllRoles method return a List<ProjectRole>. And then on the presentation layer I can extract all the data from each ProjectRole with a simple foreach loop.

Similarly, I don't want to return MembershipUser for users, but rather ProjectUser where I can supply my own fields.

So far, everything is working fine. But I'm not finished yet. What I want to know is, am I somehow screwing myself and just haven't realized it yet? For logging in, I'm doing

if (ProjectMembershipProvider.ValidateUser(UsernameTextBox.Text, PasswordTextBox.Text == true)
{
   FormsAuthentication.SetAuthCookie(UsernameTextBox.Text, true);
}

If I'm not mistaken, I'm not even using the ASP.NET providers in any way at this point, other than to inherit a bunch of stuff I end up throwing [Obsolete] tags on because I spin off my own methods. However, what worries me is that in the end, I still want to be able to use certain things like User.Identity.IsAuthenticated and User.Identity.Name and such to display the user name once inside, like "Welcome " + User.Identity.Name. Is this going to be possible if I go down this route?

tl;dr --- Am I somehow screwing myself by not properly using the Providers I'm inheriting from and just haven't realized it yet?

pnuts
  • 58,317
  • 11
  • 87
  • 139
CptSupermrkt
  • 6,844
  • 12
  • 56
  • 87
  • While it is hardly an answer, when I've asked that question in the past I typically get back the answer *Because it is Microsoft's way of doing it and we're a Microsoft shop*. It's a good question though, I wish I could provide more insight then the BS I've been fed. – M.Babcock Feb 09 '12 at 03:46

2 Answers2

3

Although Tim is wrong about the specifics of the implementations, his arguments are correct. If you wish to use the Membership API you MUST inherit from the abstract classes, because the API is dependant upon those abstract classes. There is no other way for the API to know the interface to use.

That doesn't mean you have to use the Membership API, however. But, as Tim mentions, you lose one of the great benefits of Membership, which is that you can plug in a generic provider, and this is completely independent of your app.

The reason that RoleProvider has a specific interface that returns strings is so that those strings can be compared against standard declarations for roles (ie User.IsInRole(), etc..) This built-in plumbing knows nothing of your extended versions. And if you don't implement the standard versions, it will throw exceptions if you try to use inherent functionality.

There are solutions. Membership, Roles, etc.. are just implementations of other systems, particularly IPrincipal and IIdentity. You can completely bypass Roles, Membership, etc.. if you implement your own versions of these interfaces. Then using User.IsInRole() will call your IPrincipal implementation, and User.Identity.Name will return data from your custom IIdentity implementation. You have then dropped support for the official Membership and Role api's (there is no lower level Profile interface, Profile is just part of the membership api)

Why should you care about these? Because the frameworks entire security infrastructure is built around them. If you just try to do your own security using session variables, you will have a system that is insecure and prone to breakage.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
0

You don't have to inherit from MembershipProvider, RoleProvider, and ProfileProvider.

However, if you don't, you lose a great number of benefits for things that know how to talk with classes that do. All of a sudden, you'll have to roll your own mechanisms for:
- Logging in users (you can't use the OOTB login / logout controls )
- Anything that uses the Roles or Membership classes, such as Roles.IsInRole("Admin")
- Storing the authenticated user details in cookies
- User Registration (well, ok, the OOTB implementation of this is rather limited)
- Setting which pages/directories require authentication, and what to do if the user tries to hit them and isn't authenticated (with MembershipProvider/RoleProviders, this is accomplished by OOTB web.config elements)
- Anything that uses the Authorize attribute

All of those can be overcome without too much effort. However, the main detriment to rolling your own is that you are tightly coupling your authentication/authorization mechanisms to your site, whereas with MembershipProvider / RoleProvider implementations you can create a site that can swap out your membership system simply by dropping a new DLL in the bin folder and changing the web.config settings.

Of course, you can have your own BetterMembershipProvider / BetterRoleProvider abstract classes that you inherit from to still have loose coupling. But then you can no longer drop your membership class in to a system that knows how to deal with MembershipProviders, such as many existing .Net websites, sharepoint, Dot Net Nuke, etc.

CodeThug
  • 3,054
  • 1
  • 21
  • 17
  • Good to know. How about the case where I inherit them, but pretty much just leave most of them as throw new NotImplementedException? or just have them return null/0/""/etc. That way I'm still "connected" to the ASP.NET pipeline, but without implementing stuff I don't need. – CptSupermrkt Feb 09 '12 at 04:15
  • 1
    There's no such interfaces as IMembershipProvider, IRoleProvider, or IPRofileProvider that are part of the Membership API. Membership API is based entirely on Abstract classes, not Interfaces. – Erik Funkenbusch Feb 09 '12 at 04:58
  • -1 to answer for the simple fact that it is wrong - whoever upvoted that nees to learn english and programming. The interfaces it refers to never existed, which is part of the problem. – TomTom Feb 09 '12 at 05:34
  • 1
    @TomTom: when you say 'nees to learn english', that should be 'needs to learn English.' 'nees' is not an English word, and the word 'English', when referring to the language, should be capitalized. http://english.stackexchange.com/questions/381/when-should-the-word-english-be-capitalized – CodeThug Feb 09 '12 at 06:27
  • @CptSupermrkt, sure, that's a valid approach. For MembershipProvider, you'll want to be sure to properly implement ValidateUser so that authentication can happen. Other than that, only implement the pieces that you think you need. Down the road, if you run across a scenario where you need more functionality, such as the OOTB password reset tools, then you can flesh out more of the methods. http://stackoverflow.com/questions/4978951/what-is-the-minimum-asp-net-provider-implementation-i-need-to-get-a-user-authent – CodeThug Feb 09 '12 at 06:38