views:

153

answers:

3

My application has a few different user types with their own members. For example, I have the student user as well as the teacher user. I authenticate my users through active directory in my custom MembershipProvider's ValidateUser method. While querying AD, I pull out all their relevant information. I'd like to put that information into a Profile, but from what I've read and the examples I've sen, you can only define a single Profile (like so):

<profile defaultProvider="CustomProfileProvider" enabled="true">
  <properties>
      <add name="YearLevel" type="String" />
      <add name="Name" type="String" />
      <add name="Age" type="String" />
  </properties>
</profile>

The above profile would work for a student, but not for a teacher, who does not have a value for "YearLevel" in AD. Is it possible to have multiple profiles to accomplish this? Or is it easier to add all properties from AD spanning all user types, then in my code, just check what user type they are and then access their specific properties?

A: 

You really only have 2 options here:

  1. You can just create a "big" profile with fields for all user types and then only access the fields for the user type you are currently using. (I don't recommend this, but it could be a quick fix).

  2. Implement a custom profile provider - which isn't that hard at all. You can learn more about this here: http://msdn.microsoft.com/en-us/library/0580x1f5.aspx

free-dom
A: 

Yeah, I'm afraid you would have to specify all possible properties if you are going to be using profile model. If you go that route, I would suggest using some sort of proxy that would take a user and based on it's type populate the appropriate properties.

something like

public static class ProfileProxy<T>
{
    public static void FillProperties(T user)
    {
        if(user is Teacher)
        {
            //Pull & fill profile properties for teacher
        }
        else
        {
            //Pull & fill profile properties for student
        }
    }
}

I would consider having two different tables though that keep the two objects separate, or implement a custom profile provider.

Marcus King
A: 

You could create an object and store that in the Profile. For instance:

[Serializable]
public class ProfileObject { }

[Serializable]
class StudentProfile : ProfileObject
{
    public string Year {get;set;}
    public string Name {get;set;}
    public string Age {get;set;}
}

[Serializable]
class TeacherProfile : ProfileObject
{
    public string Department {get;set;}
    public string Tenure {get;set;}
    public string Rating {get;set;}
}

In web.config:

<profile>
...
      <properties>
        <add name="UserProfile" allowAnonymous="false" type="ProfileObject" serializeAs="Xml"/>
      </properties>
</profile>

Edit: I can't remember if you can use an interface as the type or not. Changed it to object.

Access this via Profile.UserProfile (redundant, but it works). Then, to process this, you'll have to check the type:

if(Profile.UserProfile is StudentProfile) { /* do something */ } else
if(Profile.UserProfile is TeacherProfile) { /* do something */ } // etc.

You could also store generics in the profile object (Perhaps Dictionary? The following is an implementation I've used)

For instance:

namespace Model
{
    [Serializable]
     public class RecentlyViewed : List<Model.Product>
     {
         public RecentlyViewed() {}
     }
 }

And in web.config:

 <profile>
...
      <properties>
        <add name="RecentlyViewed" allowAnonymous="false" type="Model.RecentlyViewed" serializeAs="Xml"/>
      </properties>
</profile>

I used this method in .NET 3.5, I'm not sure if it works in .NET 2 or 3. I would assume the generics are processed the same way, since the compiler hasn't changed.

Note: It is necessary to inherit the generic object into an empty object, because the profile setting doesn't like the following:

<profile>
...
      <properties>
        <add name="RecentlyViewed" allowAnonymous="false" type="System.Collections.Generic.List`1[Model.Product]" serializeAs="Xml"/>
      </properties>
</profile>

The above is the fully-qualified IL name as it really should look. The XML doesn't like the tick mark, it seems.

I haven't researched any performance issues with storing serialized objects in the Profile object, and therefore I wouldn't recommend this for any properties you'll need on a fairly regular basis.

Jim Schubert