ASP.NET Profile Properties provide a convenient way to store application and user-specific preferences and personalization choices without having to write a lot of code to manage the back-end data storage and retrieval. The ASP.NET Application Services Database SqlProfileProvider can be leveraged to store and retrieve the Profile settings in a SQL Express or SQL Server database. The SqlProfileProvider will manage the storage of user-specific settings by login name for both forms-based and Windows authentication applications (anonymous user data can be stored in cookies if enabled).
SharePoint 2007 provides an extensive personalization model with it’s own set of management user interfaces and APIs. If your SharePoint site is based on Windows Authentication then SharePoint User Profile Properties are available for storing user-specific data provided personalization has been enabled for the farm and the personalization items have been setup in SharePoint and/or Active Directory.
In certain circumstances functionality being developed for deployment to SharePoint may still need to make use of ASP.NET SQL Server profiles instead of SharePoint user profiles. Some examples of when this might occur:
Recently I found myself in situation #2 and planned on using the ASP.NET SqlProfileProvider to save user preferences within common code that would be deployed to multiple ASP.NET web applications, one of which runs within a SharePoint site collection. After settings things up in Web.config and multiple rounds of writing prototype code, googling, and debugging I was unable to get anything working. No matter what I did, the Profile object was not available and it seemed as if I had hit a dead end. However, thanks to this MSDN forum post I was able to track down why things were not working. By default, SharePoint removes the Profile module which is normally available to an ASP.NET web application and you have to manually add it back in to the Web.config to be able to get and set ASP.NET Profile properties.
<profile enabled="true" automaticSaveEnabled="true" defaultProvider="AspNetSqlProfileProvider"> <providers> <clear/> <add name="AspNetSqlProfileProvider" connectionStringName="YOUR_CONNECTION_STRING_NAME" applicationName="YOUR_APPLICATION_NAME" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> </providers> <properties> <add name="Property1" type="System.String" /> <add name="Property2" type="System.String" /> <add name="Property3" type="System.String" /> </properties> </profile>
<add name="Profile" type="System.Web.Profile.ProfileModule" />
As explained in this post by Becky Bertram in SharePoint the Profile attributes defined in Web.config are not available at compile-time to SharePoint code. In order to get code to compile for deployment to SharePoint as a solution you have 2 choices:
1. Write a custom provider which maps to each attribute (Becky’s article provides an example of this for forms-based authentication which will also work for Windows authentication).
2. Make calls to Profile.GetPropertyValue and Profile.SetPropertyValue to get and set the profile values for the current user.
For example, given the above Web.config definitions, the code below would set values for the current user that would be saved to the ASP.NET SQL Profile database:
Profile.SetPropertyValue("Property1", "blue"); Profile.SetPropertyValue("Property2", System.DateTime.Now.ToString());
I’ve found an effective way to work through “it should work but I better make sure before I design a system around it” issues like this in SharePoint is to write up prototype code that is simply deployed manually to the _layouts folder. Then I just open the ASPX/CS files in Visual Studio, make changes, and reload the page in the browser the same as if I was developing for ASP.NET. To help get you going with setting up the Profile database I’ve included my Windows authentication and ASP.NET Profile prototype code below which you can also download as a zip file (see the zip file readme for steps to deploy on your SharePoint development server). Here’s an example of the prototype code output followed by the code listings:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="WindowsAuthenticationContext.aspx.cs" Inherits="WindowsAuthenticationContext" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Windows Authentication Context</title> </head> <body> <form id="form1" runat="server"> <div> <pre><asp:Literal ID="IdentityInfoLiteral" runat="server" /> </pre> </div> <div> <asp:Literal ID="ExceptionLiteral" runat="server" /> <asp:Literal ID="ExceptionStackTraceLiteral" runat="server" /> </div> </form> </body> </html>
using System; using System.Data; using System.Configuration; using System.Collections; using System.IO; using System.Security; using System.Security.Principal; using System.Text; using System.Web; using System.Web.Profile; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class WindowsAuthenticationContext : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { try { StringWriter writer = new StringWriter(); writer.WriteLine("Context.User.Identity.AuthenticationType=" + Context.User.Identity.AuthenticationType); writer.WriteLine("Context.User.Identity.IsAuthenticated=" + Context.User.Identity.IsAuthenticated); writer.WriteLine("Context.User.Identity.Name=" + Context.User.Identity.Name); writer.WriteLine(); WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); writer.WriteLine("WindowsIdentity.GetCurrent().AuthenticationType=" + windowsIdentity.AuthenticationType); writer.WriteLine("WindowsIdentity.GetCurrent().IsAuthenticated=" + windowsIdentity.IsAuthenticated); writer.WriteLine("WindowsIdentity.GetCurrent().Name=" + windowsIdentity.Name); writer.WriteLine("WindowsIdentity.GetCurrent().User=" + windowsIdentity.User.ToString()); if (Context.Profile != null) { writer.WriteLine(); writer.WriteLine("Profile.IsAnonymous=" + Profile.IsAnonymous); writer.WriteLine("Profile.UserName=" + Profile.UserName); writer.WriteLine("Profile.LastActivityDate=" + Profile.LastActivityDate.ToLongDateString()); writer.WriteLine("Profile.LastUpdatedDate=" + Profile.LastUpdatedDate.ToLongDateString()); writer.WriteLine("Profile.GetType=" + Profile.GetType()); foreach (SettingsProperty property in ProfileBase.Properties) { writer.WriteLine(">>Property name=" + property.Name + " value=" + Profile.GetPropertyValue(property.Name)); } writer.WriteLine(); } IdentityInfoLiteral.Text = writer.ToString(); } catch (Exception ex) { ExceptionLiteral.Text = ex.ToString(); ExceptionStackTraceLiteral.Text = ex.StackTrace.ToString(); } } }