A profile provider writes profile property values supplied by an ASP.NET application to a persistent profile data store and reads the property values back from the data store when requested by the application. Profile providers also implement methods that enable users and administrators to manage profile data stores using specific parameters. Table 9-4 shows the methods required by DotNetNuke to implement a custom profile provider.
Method | Description |
---|---|
GetUserProfile | Returns a user's profile. |
UpdateUserProfile | Updates a user's profile. |
Listing 9-7 sets properties for the default AspNet profile provider. It's contained in the web.config's memberrolesprototype section. The items listed as properties are what will be exposed to each user at time of registration by default.
Listing 9-7: Profile Provider Set in Web.Config
<profile enabled="true"> <providers> <add name="AspNetSqlProvider" type= "DotNetNuke.Security.Membership.AspNetSqlProfileProvider, DotNetNuke.Provider.AspNetProvider" connectionStringName= "SiteSqlServer" applicationName="/" description="Stores and retrieves profile data from the local Microsoft SQL Server database" /> </providers> <properties> <add name="FirstName" type="string" allowAnonymous="true" /> <add name="LastName" type="string" allowAnonymous="true" /> <add name="Unit" type="string" allowAnonymous="true" /> <add name="Street" type="string" allowAnonymous="true" /> <add name="City" type="string" allowAnonymous="true" /> <add name="Region" type="string" allowAnonymous="true" /> <add name="PostalCode" type="string" allowAnonymous="true" /> <add name="Country" type="string" allowAnonymous="true" /> <add name="Telephone" type="string" allowAnonymous="true" /> <add name="Fax" type="string" allowAnonymous="true" /> <add name="Cell" type="string" allowAnonymous="true" /> <add name="Website" type="string" allowAnonymous="true" /> <add name="IM" type="string" allowAnonymous="true" /> <add name="TimeZone" type="integer" allowAnonymous="true" /> <add name="PreferredLocale" type="string" allowAnonymous="true" /> </properties> </profile>
A Profile Provider needs to be more flexible than the other Membership Service Providers. In the Membership Service Providers already discussed, the data items are consistent one way or another. For example, the Membership Provider has a series of consistent methods that are required in your data schema in the majority of any web-facing sites. You will always need a UserName and Password set of columns using a defined data type that works for all cases. In a Roles Provider, you always need a RoleId and RoleName set of columns that are also using a defined data type that works for all its cases. Things aren't as straightforward in the Profile Provider. One install can require a list of 10 properties collected at time of registration, whereas another install may require 20 properties. Because you cannot account for how many properties an install will require, the flexibility needs to be there to allow changes without requiring changes to the actual provider that result in schema changes or changes in the code that would need a recompile.
A Profile Provider also must supply you with the capability to add profile items from other aspects of your application. For example, you may want to add a profile item such as an avatar image for a user in a web site's membership base. If you want the avatar image to persist with the user and be accessible anytime, it needs to be part of the user's profile object regardless of when it is collected from the user. This permits the avatar image in this example to be exposed to all modules used in a DotNetNuke portal and allows the module developers to know ahead of time where to access this image.
If you want to create your own concrete profile provider, you need to add some additional properties that are exposed throughout the DotNetNuke application and can be consumed by items plugged into the framework, such as modules. Table 9-5 shows these properties, each of which has a constant assigned to it in case the concrete provider does not include these properties. (If the property is not used in the concrete provider, the value will be assigned to that of the constant.)
Property | Description |
---|---|
Cell | User's cell/mobile phone |
City | User's city |
Country | User's country |
Fax | User's Fax number |
FirstName | User's first name |
FullName | User's first and last names |
IM | User's instant messenger name |
IsDirty | Determines if a property in the Hash table has changed. |
LastName | User's last name |
ObjectHydrated | If the object is hydrated or not |
PostalCode | User's postal code |
PreferredLocale | User's preferred locale |
ProfileProperties | Hash table of profile properties of a user |
Region | User's region or state |
Street | User's street address |
Telephone | User's telephone number |
Unit | User's address unit |
TimeZone | User's time zone |
Website | User's web site address |
These properties look familiar because most of them are the same ones exposed in the web.config used by the default AspNet Profile Provider. The files containing the logic to construct the abstract profile provider can be found within a single folder at $AppRoot\Library\Components\Users\Profile\.
In the default AspNet concrete provider, a user's profile is stored as what has been referred to as a "blob" of data. This means that instead of having multiple columns, each with a clearly defined data type and column name, the entire set of properties is stored within a single column. This provides the flexibility to add properties to or remove properties from a profile without requiring major changes in the architecture. Listing 9-8 shows how a user's profile is created or updated.
Listing 9-8: UpdateUserProfile Method in the Concrete AspNet Profile Provider
Public Overrides Sub UpdateUserProfile(ByVal user As UserInfo) Dim objProfile As AspNetProfile.ProfileBase Dim objSecurity As New PortalSecurity Dim propHash As Hashtable = user.Profile.ProfileProperties 'Set Application Name If user.IsSuperUser Then SetApplicationName(Common.Globals.glbSuperUserAppName) Else SetApplicationName(user.PortalID) End If objProfile = AspNetProfile.ProfileBase.Create (user.Membership.Username, True) 'Looping through each key in profile hashtable. 'Each key is profile property name. Dim profProperty As ProfileProperty For Each key As Object In propHash.Keys profProperty = propHash(key) 'checking if property's datatype is string. 'if it is string then we do input filter on value. If AspNetProfile.ProfileBase.Properties (key.ToString()).PropertyType Is GetType(String) Then 'Checking if value is set or not? if value is set then do input filter 'otherwise assign Nullstring. If Not profProperty Is Nothing Then objProfile(key.ToString()) = objSecurity.InputFilter (profProperty.PropertyValue.ToString(), PortalSecurity.FilterFlag.NoScripting Or PortalSecurity.FilterFlag.NoMarkup) Else objProfile(key.ToString()) = Null.NullString End If Else objProfile(key.ToString()) = Null.SetNull(profProperty.PropertyValue, AspNetProfile.ProfileBase.Properties(key.ToString()). PropertyType) End If Next objProfile.Save() End Sub
As with the other concrete provider examples, this method first sets the application name using a private function. However, the next step is different because essentially several rows of data are being passed in so they can be combined into a single row that will ultimately be a single column in the data store. The logic loops through each row of the hash table that was passed in as a parameter and verifies that the data is not nothing. If it is nothing, a default Null string value is assigned. After all of this is complete for each row of the hash table, the object is passed to the save method of the concrete provider. The save method is what actually sends the profile data to the data store.