views:

413

answers:

2

Hello,


A) Why, when using templates with CreateUserWizard control, does including Textbox with ID=Email depend on whether CreateUserWizard.RequireEmail property is set to true, but TextBox with ID=Question is required only if underlying membership provider requires password question? In other words, why wouldn’t it also be up to underlying membership provider to decide whether Textbox ( with ID=email ) is required?


B) On the other hand, why would be up to membership provider to decide whether password question is required? Shouldn’t this be up to Membership class to decide? Afterall, the job of membership provider should just be to provide access to underlying data store, and not to decide what data users must provide?!


thanx


EDIT:

A)

It comes down to the fact that the membership provider has an obvious mapping: RequiresQuestionAndAnswer, which you can set and have this enforced, but you can't specify that the user must supply an email address.

So RequiresUniqueEmail in essence tells that user doesn’t have to specify an email address, but if she does, it must be unique?


B)

  • If I understand membership providers correctly, they are the entities that send SQL queries to data storage?! Thus I assume they have full knowledge of tables and relationships etc this data storage has?

  • But still, what if data storage doesn’t have a column for storing email addresses, but CreateUser() specifies email address as one of its parameters? How does membership provider handle that?

+1  A: 

It comes down to the fact that the membership provider has an obvious mapping: RequiresQuestionAndAnswer, which you can set and have this enforced, but you can't specify that the user must supply an email address.

Specifying that they must supply a unique email address with RequiresUniqueEmail is not the same as saying "requires an email" - so the CreateUserWizard is offering you the option of saying "I don't care that the email addresses aren't unique, just that there is one".

As to why the membership provider should control whether a question is required: It's because the provider is also controlling things like EnablePasswordReset and EnablePasswordRetrieval - these are things that the memebership class has no knowledge of - in fact, even though the membership class has a "ValidateUser" method, it will use the default provider specified in the web.config to do this:

The Membership class relies on membership providers to communicate with a data source.


In response to question edits:

a. That is correct, as Stephen points out, you could have one user with an empty email address, and then all others would have to have a value. Depending on your validators, this doesn't actually have to be a valid email addres.

b.1. Not quite - The providers send data to and from your user data store - this might be SQL, but it could also be Active Directory, LDAP, a text file, etc, but yes, your provider acts as the seperation layer between your application and your user store.

b.2. There are many parts to membership - the documentation on implementing a custom Membership User takes you through the steps needed to create a custom user - if your data storage didn't handle email addresses (or you wanted multiple emails stored in a profile), then your provider could just ignore any value sent through to you on create or update, and populate it with null on get.

Zhaph - Ben Duguid
+1  A: 

It is an interesting point that email is part of the expected data fields.

Let me clarify... if you set RequiresUniqueEmail to true for the SQL Provider, the email will NOT be required --strictly speaking. It just means that every user will have to use a different email address from any other user. So there can be one user without an email address. A null value will be set in the database. But no other user would be able to omit the email address after that because that would cause two users to have null emails... So functionally it may as well be the same as required email addresses, but it is not technically the same.

The wizard controls provide a default UI for collecting membership information, and it assumes you use will be using the default SQL provider. If you are not using the default provider, your provider doesn't support all of the fields, or you have other unique constraints in your provider then you should customize the wizard steps with your own templates and handle the wizard's events to provide your own validations and additional logic as appropriate.

As for understanding the Membership system itself...

The Membership system in asp.net is a compromise between strict OO design and convenience. There are a few assumptions in the base MembershipProvider class from which the specific Membership providers inherit that are presumptuous. The fact that email addresses will be part of the membership data in one of the more liberal assumptions the base provider makes.

By making that assumption though, which is true in most environments, the membership system is able to expose some functionality related to email addresses in a simple and intuitive way (such as getting a user by their email address instead of user name and prohibiting multiple accounts with the same email address). If the base class didn't make that assumption, then every time you wanted to do stuff with emails in your specific provider, you'd have to cast the reference to the specific type you are using within your application. This is cumbersome.

From a purely OO point of view, these assumptions are uncomfortable. But you can, and many membership providers do, provide empty implementations for methods and properties from the base class if they don't use them.

You see this more with role providers... for example the Windows Token Role provider has a lot of members that throw NotImplmentedException (the Token role provider is a read-only provider for AD, so all of the property set accessors throw exceptions).

Stephen M. Redd
May I just ask: If Membership.CreateUser() specifies already existing email, while membership provider requires unique email, the Status parameter will notify you of this and also Membership.CreateUser() will return a null reference. But if membership provider has RequiresQuestionAndAnswer set to true, but Membership.CreateUser() doesn’t provide you with password question and answer, then exception will be thrown.But why isn’t exception also thrown when unique email is not provided by Membership.CreateUser()? Afterall, in both cases user is not created?!
SourceC
BTW - I assume Membership.CreateUser() calls MembershipProvider.CreateUser()?
SourceC
Yes, Membership.CreateUser() is just a pass-through to the default provider's CreateUser() method.
Stephen M. Redd
The reason for the different behavior when password question/answer are omitted vs email not being unique is just due to where the problem gets detected. CreateUser() has the information necessary to detect the invalid password question/answer parameters in the code directly. Errors there are thrown as exceptions. But with emails, the unique check isn't done in the code. It is done in the stored procedure itself just before the record is created in the table. Errors coming back from the stored proc passed back via the status variable instead of being throw as an exception.
Stephen M. Redd
Sorry for not replying sooner. Anyways, thank you both for your kind help
SourceC