Click here to Skip to main content
Email Password   helpLost your password?

Introduction

ASP.NET 2.0 provides a Web Parts framework, allowing programmers to easily integrate drag �n drop menus etc. in their web portals. This framework is easy to use and all client based design settings are stored by ASP.NET data providers in an easy way. The developer has nothing to do with the save or load process of Web Parts design based settings. This article will not cover how we can use Web Parts. It�s possible to find lots of articles around the web about Web Parts.

ASP.NET 2.0 Web Parts framework works with the Membership framework as well as the Forms or Windows authentication modes. The problem is that, if you don�t want to use any authentication mode, you can�t use Web Parts. The client user, who will able to change the web site's design with Web Parts, should be authenticated. If not authenticated, the ASP.NET Web Parts framework can�t save users' design settings with data providers and for that reason can�t allow even to switch design modes.

The Idea

If we just need that all users connecting to our web site be authenticated, we need to register all users to our web site's authentication system. We will use Forms Authentication and provide some tricky ways. Users will be registered with our site in a hidden way with some cookie. We will recognize our visitors with their cookie and authenticate them automatically to get Web Parts design options available for them.

Using Hidden Authentication

First, we will set up our web site for Forms Authentication. You just need to modify your Web.Config file as below:

        <!--
            The <authentication> section enables configuration 
            of the security authentication mode used by 
            ASP.NET to identify an incoming user. 
        -->
        <authentication mode="Forms" />

We will provide for each visitor a cookie to recognize the user's identity to be able to show them their design settings. We need an identity name for each visitor. We will create a random guide number to use as identity.

Dim MyCookieName As String = "Reminder"
Dim MyCookie As System.Web.HttpCookie = Request.Cookies(MyCookieName)
Dim UserID As String
UserID = System.Guid.NewGuid.ToString.Replace("-", "")
MyCookie = New System.Web.HttpCookie(MyCookieName, UserID)
MyCookie.Expires = DateTime.Now.AddYears(10)
Response.Cookies.Add(MyCookie)

Our cookie name is �Reminder�. You can change the name for your projects. Our Cookie data is the random guide name �UserID� that we generated using .NET Framework's �System.Guid.NewGuid� class. Now we can programmatically recognize our visitors each time they visit our web portal.

We should now authenticate our user with his GUID name "UserID" to our Forms Authentication system. In a normal situation ASP.NET uses cookies to store Forms Authentication data. We will just simulate that process manually.

Dim authTicket As FormsAuthenticationTicket = _
    New FormsAuthenticationTicket(1, UserID, DateTime.Now, _
    DateTime.Now.AddSeconds(30), False, "roles")
Dim encryptedTicket As String = FormsAuthentication.Encrypt(authTicket)
authCookie = New HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
Response.Cookies.Add(authCookie)

Now our user is authenticated to our web site with Forms Authentication and can access Web Parts design properties.

We will have lots of visitors designing our web site for themselves and then just never visit again our web site or just delete their cookie and loose their identity as well as their design settings. So why do we need to store all visitor design settings if they haven�t visited our web site since last year? With the code below we connect manually to the ASP.NET Membership data store and delete users settings and profile manually, checking the last activity date of the user.

Dim LastDate As Date = Date.Now.AddYears(-1)

Dim cnn As System.Data.SqlClient.SqlConnection = New _
  System.Data.SqlClient.SqlConnection(_
  ConfigurationManager.ConnectionStrings("LocalSqlServer").ConnectionString)
Dim cmd As System.Data.SqlClient.SqlCommand

cmd = New System.Data.SqlClient.SqlCommand("DELETE FROM" & _ 
      " aspnet_PersonalizationPerUser where UserID IN " & _ 
      "(SELECT UserID from aspnet_Users where " & _ 
      "[LastActivityDate] < @Date)", cnn)
cmd.Parameters.Add("@Date", Data.SqlDbType.DateTime)
cmd.Parameters.Item("@Date").Value = LastDate
Try
    cnn.Open()
    cmd.ExecuteNonQuery()
Catch ex As Exception
Finally
    cnn.Close()
End Try

cmd = New System.Data.SqlClient.SqlCommand("DELETE FROM" & _ 
      " aspnet_Users where [LastActivityDate] < @Date", cnn)
cmd.Parameters.Add("@Date", Data.SqlDbType.DateTime)
cmd.Parameters.Item("@Date").Value = LastDate
Try
    cnn.Open()
    cmd.ExecuteNonQuery()
Catch ex As Exception
Finally
    cnn.Close()
    cmd.Dispose()
    cnn.Dispose()
End Try

The complete solution is as below:

Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)

If Page.IsPostBack = False Then
    Dim authCookie As HttpCookie = _
        Request.Cookies(FormsAuthentication.FormsCookieName)
    If authCookie Is Nothing Then
        Dim MyCookieName As String = "Reminder"
        Dim MyCookie As System.Web.HttpCookie = _
                     Request.Cookies(MyCookieName)
        Dim UserID As String
        If MyCookie Is Nothing Then
            UserID = System.Guid.NewGuid.ToString.Replace("-", "")
            MyCookie = New System.Web.HttpCookie(MyCookieName, UserID)
            MyCookie.Expires = DateTime.Now.AddYears(10)
            Response.Cookies.Add(MyCookie)
        Else
            UserID = MyCookie.Value
        End If
        Dim authTicket As FormsAuthenticationTicket = New _
          FormsAuthenticationTicket(1, UserID, DateTime.Now, _
          DateTime.Now.AddSeconds(30), False, "roles")
        Dim encryptedTicket As String = _
            FormsAuthentication.Encrypt(authTicket)
        authCookie = New HttpCookie(FormsAuthentication.FormsCookieName, _
                                                        encryptedTicket)
        Response.Cookies.Add(authCookie)
        Response.Redirect(Request.Url.ToString)
    End If
    
    Dim LastDate As Date = Date.Now.AddYears(-1)
    
    Dim cnn As System.Data.SqlClient.SqlConnection = New _
      System.Data.SqlClient.SqlConnection(_
      ConfigurationManager.ConnectionStrings(_
      "LocalSqlServer").ConnectionString)
    Dim cmd As System.Data.SqlClient.SqlCommand
 
    cmd = New System.Data.SqlClient.SqlCommand("DELETE FROM" & _ 
          " aspnet_PersonalizationPerUser where UserID IN " & _ 
          "(SELECT UserID from aspnet_Users where " & _ 
          "[LastActivityDate] < @Date)", cnn)
    cmd.Parameters.Add("@Date", Data.SqlDbType.DateTime)
    cmd.Parameters.Item("@Date").Value = LastDate
    Try
        cnn.Open()
        cmd.ExecuteNonQuery()
    Catch ex As Exception
        Response.Write(ex.Message)
    Finally
        cnn.Close()
    End Try
    
    cmd = New System.Data.SqlClient.SqlCommand("DELETE FROM" & _ 
          " aspnet_Users where [LastActivityDate] < @Date", cnn)
    cmd.Parameters.Add("@Date", Data.SqlDbType.DateTime)
    cmd.Parameters.Item("@Date").Value = LastDate
    Try
        cnn.Open()
        cmd.ExecuteNonQuery()
    Catch ex As Exception
        Response.Write(ex.Message)
    Finally
        cnn.Close()
        cmd.Dispose()
        cnn.Dispose()
    End Try
End If

End Sub

The scenario starts with checking the Forms Authentication cookie. If we have already authenticated the user, we need not do anything. If there isn�t the Forms Authentication cookie, we check further if we have got our identity cookie. If there is an identity cookie �Reminder�, we can load the user's identity and authenticate it with Forms Authentication. This way, all users' old design settings comes automatically to our web portal. If the user doesn�t have our �Reminder� cookie, we create an identity and store it for that user and authenticate it with the new identity to the authentication system.

After having done all this process, we check for old users and delete the ones which don�t have at least one year activity on the web portal.

Conclusion

You just need to use this system on the "Page_Load" event of your web forms where you are using web parts design properties. Have fun using this tricky method on your future portal developments.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
General:)
idda
21:04 23 Jun '09  
great article

go go go!

GeneralWebpart and Login Form
dwilsonhcf
7:35 20 Apr '09  
I have a login screen that stores the username into a session("userid") and multiple pages that have webparts. How can I use the userid session to load and save webparts?
GeneralQuery about multiple pages personalization..
mr_muskurahat
0:31 31 Mar '09  
dear sir,

can i implement this article with multiple pages
for example ,
i have page 1 and implemented this feature working fine...
can i have same personalization feature for second page of same website what will i have to do????

can i implement this article with authentication mode="windows"

Government Dyal Singh College Lahore.

GeneralSources.
Michael Soliman.
3:42 19 Feb '09  
Moin Moin.
Is it possible to download a vstudio project zip-file .
_Tschuess,
__Michael.
Generaldeploying ???
Member 3290722
0:48 21 Jan '09  
hi,

I would like to know what should be the authetication setting in IIS.
GeneralWhich catalog(database) is used in this article?
PadmaDarji
3:19 30 Sep '08  
hi
Your article is so fentastic.
I have one question in connenction string (LocalSqlServer) which catalog(database) is used?

Thanks

by me

GeneralNice Article
sundeep38
5:30 29 Aug '08  
It helped me a lot. Thanks Daron!
GeneralThanks a lot!
jeevansd
23:59 10 Jun '08  
Hi,
Great Article. It helped me a lot. Thanks for guiding.
Keep it up.
Thanks

Jeevan Desarda
Software Developer

GeneralRe: Thanks a lot!
vishalMGiri
2:26 9 Jul '09  
From me too Helped a lot
General"Personalization is not enabled and/or modifiable" error (I guess the Cookie is expired?) [modified]
Raxxa_
3:02 28 Apr '08  
Hello,

I'm using C# and I've also added a statement in Page_Load where I set the DisPlayMode of the WebPartManager to "DesignDisplayMode". This is because I want my page to load in designmode as the default mode. But I keep getting the following error if I wait a while between every drag n drop of my my web parts:
Personalization is not enabled and/or modifiable. The Enabled property must be set to true, and a registered personalization provider must be selected. The current user must be granted the right to modify personalization state.

I'm guessing this is because the FormsAuthenticationTicket has expired. If I keep dragging & dropping my web parts constantly this problem won't occour, but if i stop for a while and try drag & drop again I get the error message above. I know it has to do with my statement where I set the "DesignDisplayMode" and I've tried moving it around in several ways, but it just won't work anyway! (I even removed it entirely from Page_Load and made a button to switch to designmode, but that didn't work either!)

The only thing that solves my problem is to remove the "if (!Page.IsPostBack)" check and let the FormsAuthenticationTicket be renewed every time the page is loaded. But that's not how this trick was ment to work...so...I can't see why no one else ever experienced the same problem?)

Please help!



protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{

//*********** Enable anonymous web parts personalization ************************//
HttpCookie authCookie = Request.Cookies.Get(FormsAuthentication.FormsCookieName);
if (authCookie == null)
{
string MyCookieName = "Reminder";
HttpCookie MyCookie = Request.Cookies.Get(MyCookieName);
string UserID;
if (MyCookie == null)
{
UserID = System.Guid.NewGuid().ToString().Replace("-", "");
MyCookie = new HttpCookie(MyCookieName, UserID);
MyCookie.Expires = DateTime.Now.AddYears(10);
Response.Cookies.Add(MyCookie);
}
else
{
UserID = MyCookie.Value;
}
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, UserID, DateTime.Now, DateTime.Now.AddSeconds(30), false, "roles");
Session["Expired"] = authTicket.Expiration.ToString();
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Response.Cookies.Add(authCookie);
Response.Redirect(Request.Url.ToString());
}

//****** the code for deleting old user data goes here ***************//

WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode;

}//end of if(!Page.IsPostBack)

WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode

}//end of Page_Load



modified on Monday, April 28, 2008 8:21 AM

GeneralRe: "Personalization is not enabled and/or modifiable" error (I guess the Cookie is expired?)
satalaj
4:14 9 Mar '09  
Did you solved it. I have same error using ASP.net and C#
GeneralRe: "Personalization is not enabled and/or modifiable" error (I guess the Cookie is expired?)
satalaj
7:07 9 Mar '09  
Hi guys I have solved my error with the code provided by author. I forget to add authentication mode="Forms">
so it was taking it mode as windows
Now my web will enjoy anonymous webpart feature Smile
Thanks
Satalaj
QuestionRe: "Personalization is not enabled and/or modifiable" error (I guess the Cookie is expired?)
gopala krishna G
3:17 2 Jun '09  
Hi,
If I leave the browser idle for 10-15 minutes and then try to change the display mode, I get this error. I am using fake authentication as above with cookie timeout as 1 year.
Please help...
GeneralThanks
semgoksu
11:58 26 Apr '08  
Thanks daron Smile))
GeneralEasier with Authentication Mode "Windows"?
samtaz
5:16 17 Aug '07  
All I do is add the following to my web.config:


<?xml version="1.0"?>
<configuration>
   ...
   <system.web>
      ...
      <!-- The following changes page layout for all users whenever a user makes a change
      <authorization>
         <allow verbs="enterSharedScope" users="*" />
      </authorization>
      -->
      <authentication mode="Windows" />
      <identity impersonate="true" userName="[IIS_Server_Domain]\[Some_User]" password="[User_Password]" />
      <roleManager enabled="true" />
      ...
   </system.web>
   ...
</configuration>

Now IIS impersonates the given windows user for every page call, and web parts works just fine! Big Grin

-Sam
GeneralI get error "User does not have permission to perform this action"
Goran___
1:01 25 May '07  
FOA -- Very nice trick

During first:

Try
cnn.Open() <------------------ HERE !!! cannot open connection
cmd.ExecuteNonQuery()
Catch ex As Exception
Finally
cnn.Close()
End Try

I'm using standar connectionstring: ("LocalSqlServer"):

data source=.\SQLEXPRESS;Integrated security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true

Please help...

Regards

GeneralSql Command Suggest
tychi
1:59 2 Apr '07  
IF we use following sql command text, we can use just single SqlCommand without parameter.

DELETE FROM aspnet_PersonalizationPerUser
WHERE UserID IN
   (SELECT UserID from aspnet_Users
   where LastActivityDate < DATEADD(YEAR, -1, GETDATE()));
DELETE FROM aspnet_Users
WHERE LastActivityDate < DATEADD(YEAR, -1, GETDATE())

GeneralRe: Sql Command Suggest
Daron Yöndem
4:39 25 Apr '07  
Yup, thanks for the contribution Wink
GeneralC# Code
cavedog6
8:35 12 Dec '06  
Here is the C# code for the first part in case anyone needs it. I didn't need the part that deletes records so I didn't code it.


protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
HttpCookie authCookie = Request.Cookies.Get(
FormsAuthentication.FormsCookieName);

if (authCookie == null)
{
string MyCookieName = "Reminder";
HttpCookie MyCookie = Request.Cookies.Get(MyCookieName);
string UserId;
if (MyCookie == null)
{
UserId = System.Guid.NewGuid().ToString().Replace("-", "");
MyCookie = new HttpCookie(MyCookieName, UserId);
MyCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(MyCookie);
}
else
{
UserId = MyCookie.Value;
}
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1, UserId, DateTime.Now, DateTime.Now.AddSeconds(30),
false, "roles");
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
authCookie = new HttpCookie(
FormsAuthentication.FormsCookieName, encryptedTicket);
Response.Cookies.Add(authCookie);
Response.Redirect(Request.Url.ToString());
}
}
}

GeneralRe: C# Code
Daron Yöndem
3:58 22 Dec '06  
Thanks for support Wink
NewsRe: C# Code completed [modified]
samtaz
0:57 17 Aug '07  
Completed the C# translation, havent really tested this yet, but seems to work:


protected void Page_Load(object sender, EventArgs e)
{
// allow anonymous personalization of web parts
if (!Page.IsPostBack)
{
HttpCookie authCookie = Request.Cookies.Get(
FormsAuthentication.FormsCookieName);

if (authCookie == null)
{
DateTime LastDate = DateTime.Now.AddYears(-1);

System.Data.SqlClient.SqlConnection cnn =
new System.Data.SqlClient.SqlConnection(
ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString);

System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(
"DELETE FROM aspnet_PersonalizationPerUser where UserID IN " +
"(SELECT UserID from aspnet_Users where [LastActivityDate] < @Date)", cnn);
cmd.Parameters.Add("@Date", System.Data.SqlDbType.DateTime);
cmd.Parameters["@Date"].Value = LastDate;
try
{
cnn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception loginE)
{
Response.Write(loginE.Message);
}
finally
{
cnn.Close();
}

cmd = new System.Data.SqlClient.SqlCommand(
"DELETE FROM aspnet_Users where [LastActivityDate] < @Date", cnn);
cmd.Parameters.Add("@Date", System.Data.SqlDbType.DateTime);
cmd.Parameters["@Date"].Value = LastDate;
try
{
cnn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception loginE)
{
Response.Write(loginE.Message);
}
finally
{
cnn.Close();
}

string MyCookieName = "Reminder";
HttpCookie MyCookie = Request.Cookies.Get(MyCookieName);
string UserId;
if (MyCookie == null)
{
UserId = System.Guid.NewGuid().ToString().Replace("-", "");
MyCookie = new HttpCookie(MyCookieName, UserId);
MyCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(MyCookie);
}
else
{
UserId = MyCookie.Value;
}
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1, UserId, DateTime.Now, DateTime.Now.AddSeconds(30),
false, "roles");
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
authCookie = new HttpCookie(
FormsAuthentication.FormsCookieName, encryptedTicket);
Response.Cookies.Add(authCookie);
Response.Redirect(Request.Url.ToString());
}

}
}



-- modified at 6:21 Friday 17th August, 2007
GeneralRe: C# Code
Matt Langley
8:53 16 May '08  
I also ported the code to C# before seeing this, and I'm glad to say it came out the same as your port!

However, during testing I have found that the Forms Authentication cookie seems to have to be recreated even on a postback. I don't know if this is because I have a setting wrong somewhere in IIS or whether the authentication cookie is just not persisting (maybe the expires property needs setting).

In anycase, commenting out the '
If (!Page.IsPostBack)
' construct out seems to work very well.

btw, in my case I wanted all users to share the same layout (I'll control which users can access edit and catalog modes using my own login process). If anyone else needs this then you can dispense with the Reminder cookie and GUID based UserID and simply use a constant name like 'common'.

Very handy technique: Hidden authentication. Thanks very much for sharing.
GeneralRe: C# Code
vishalMGiri
2:29 9 Jul '09  
Thanks all 3 of you for converting to c#
GeneralCouple of ?'s
robertfah
9:21 7 Nov '06  
I can get your code to work, but am I supposed to see the username in the aspnetdb tables?

Also, when I log in and try to switch to design mode of the web parts, it gives me the following error:

The specified display mode is currently disabled on this page. Make sure personalization is enabled for the current user.
Parameter name: value

Any ideas?
AnswerRe: Couple of ?'s
Daron Yöndem
0:14 10 Dec '06  
Solving the error you are getting is the main purpose of this article.

There should be something wrong about your project. Actually this article is written to solve your problem and it does when I try Smile


Last Updated 13 Nov 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010