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:

  1. SharePoint personalization has not yet been configured and enabled or an organization has decided not to enable the personalization system and only a few user-specific properties need to stored.
  2. Common code will be developed that needs to store user-specific preferences in both ASP.NET and SharePoint web applications and the code needs to support both forms-based and Windows authentication.

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.

Web.config Profile (add to system.web)

<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> 

Web.config Module Include (add to httpModules)

<add name="Profile" type="System.Web.Profile.ProfileModule" />

Getting and Setting the Profile Properties in SharePoint Code

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()); 

Prototype Code

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:

image

WindowsAuthenticationContext.aspx

<%@ 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>

WindowsAuthenticationContext.aspx.cs

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();
        }
    }
}
Bookmark and Share  Comments [1] | Permalink | SharePoint
Saturday, August 29, 2009 7:43:30 AM (Mountain Daylight Time, UTC-06:00)
Great post, Mike!

Leave a Comment

Name (required)
Email (will not be published)
Website
 

Comment Preview
Subscribe
Top 5 Posts
Add Google Analytics to a SharePoint Publishing Site
Integrating jQuery 1.3, ASP.NET 3.5 Visual Studio 2008
Add Custom Table Formats to SharePoint Content Editor
Configuring log4net for SharePoint Windows Authentication
Convert Visual Studio 2008 Class Library Project to Web Application Project
Tags
ASP.NET (5) dasBlog (5) GoogleAnalytics (2) jQuery (1) log4net (2) SharePoint (18) WebDesign (3)
 
 
 
Spreadfirefox Affiliate Button
 
Download Notepad++