Reputation:
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?
Upvotes: 0
Views: 1555
Reputation: 5203
EDIT 2015-01-26: Hmm... my just got upped 1, but I actually think it shouldn't have been. Now that I reread the question and my own answer of over 2 years ago I actually DON'T think profile groups are the way to enable multiple profile 'types'. You could perhaps stuff in the properties of two different types into two different groups (at least 'orthogonal' properties), but you still need code to distinguish the two. So I would go with apiguy or Jim Schubert's answer ENDEDIT
Isn't this what profile groups are for? Like:
<profile>
<properties>
<group name="UserInfo">
<add name="Name"/>
<add name="Age"/>
</group>
<group name="MemberInfo">
<add name="MemberID"/>
<add name="JoinDate"/>
</group>
</properties>
</profile>
Upvotes: 1
Reputation: 20357
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.
Upvotes: 0
Reputation: 1677
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.
Upvotes: 0
Reputation: 5362
You really only have 2 options here:
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).
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
Upvotes: 1