Wednesday, September 30, 2009

How to: Programmatically remove a Field (SPField) from a view (SPView)

How to: Programmatically remove a Field (SPField) from a view (SPView) 

Introduction

This is yet another very simple example of a question I've been getting over and over the past couple of months through comments and emails - instead of answering it each time in the mail, I'm simply shooting it out here.

Deleting a Field from a View programmatically

Alright, here's a good starting point for you to check out if you simply want to remove a field from the view. Simple as that.

SPList list = SPContext.Current.Web.Lists["MyAwesomeList"];
SPView view = list.Views["MyView"]; 

if(view.ViewFields.Exists("MyField"))
{
    bool allowUnsafe = SPContext.Current.Web.AllowUnsafeUpdates; 

    SPContext.Current.Web.AllowUnsafeUpdates = true;
    view.ViewFields.Delete("MyField");
    view.Update(); 

    SPContext.Current.Web.AllowUnsafeUpdates = allowUnsafe;
}

Summary

The aforementioned code is all there's to it in order for you to get started.
Simple, quick, effective!

Tuesday, September 15, 2009

Detecting the current mode (display/edit) - SharePoint Page

One of these days I came accross a simple requirement that led me to a couple of scenarios: "How do I detect if I am in display mode or in edit mode?". This has some significant importance in WCM (Web Content Management) world, where you may need some tricks to hide fields, controls or even alter the look of a component. Thhis can be achieved (at least) in three ways:

  • in the Layouts (aspx) code only:

In this case you have specific zones where to put controls that appear in edit mode and in display mode (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.webcontrols.editmodepanel.aspx):

For any part you need to hide from Edit mode surround it by

<PublishingWebControls:EditModePanel runat=server id="EditModePanel1" PageDisplayMode="Display">
<!-- your code here -->
</PublishingWebControls:EditModePanel>

For any part you need to hide from Display mode surround it by

<PublishingWebControls:EditModePanel runat=server id="EditModePanel1" PageDisplayMode="Edit">
<!-- your code here -->
</PublishingWebControls:EditModePanel>
  • code behind: webparts

In this case, the object responsible for the information of the current mode is the WebPartManager.DisplayMode (http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.webparts.webpartmanager.displaymode.aspx). The allowued values for this enumerate are (from msdn):

 

Display mode Description
BrowseDisplayMode Displays Web Parts controls and UI elements in the normal mode in which end users view a page.
DesignDisplayMode Displays zone UI elements and enables users to drag Web Parts controls to change the layout of a page.
EditDisplayMode Displays special editing UI elements and enables end users to edit the controls on a page.
CatalogDisplayMode Displays special catalog UI elements and enables end users to add and remove page controls.
ConnectDisplayMode Displays special connections UI elements and enables end users to connect Web Parts controls.

Note that this only works correctly if there is only 1 webpart on the page as the test is done individually.

  • code behind: other situations

This is probably the least used mode, nevertheless, I had to used a couple of times. You can detect the current mode through:

Microsoft.SharePoint.SPContext.Current.FormContext.FormMode

This is an enumerate with the values:

  • SPControlMode.Display
  • SPControlMode.Edit

Thus you can build a very simple test:

  if (Microsoft.SharePoint.SPContext.Current.FormContext.FormMode == SPControlMode.Display)
  {
   // your code to support display mode
  }
  else // Microsoft.SharePoint.SPContext.Current.FormContext.FormMode = SPControlMode.Edit
  {
   // your code to support edit mode
  }
  

How to Create Delimited Lists of Related Data in Your MS SQL Queries



A project I'm working on requires me to return asset records along with a comma-delimited list of related keywords. The keywords are stored in their own table and there is a one-to-many relationship from assets to keywords.

The following code returns what I'm looking for, but only for one record:

DECLARE @KeywordList varchar(1000)

SELECT @KeywordList = COALESCE(@KeywordList + ', ', '') + k.keyword
FROM assets a
JOIN keywords k ON a.asset_guid = k.asset_guid
WHERE a.asset_guid = 'xxxxxxxx-xxxx-xxxx-xxxx-023ECD4EBB4C'

SELECT @KeywordList

The problem was that I needed to return the results in a column for every record in the result set, and that code won't work in a subquery.

My solution was to create a SQL user defined function.

Before proceeding, I should note that the method I'm posting should only be used if absolutely necessary. In addition to running your main query, you will also be running an additional query for every returned record, which can get pretty expensive.

But if you have a need as I did, this method should do the trick. Te following function accepts an asset GUID and returns the associated keywords in a comma-delimited list:

CREATE FUNCTION getDelimitedKeywords
(@asset_guid uniqueidentifier )
RETURNS varchar(1000)
AS
BEGIN
DECLARE @KeywordList varchar(1000)
SELECT @KeywordList = COALESCE(@KeywordList + ', ', '') + keyword
FROM keywords
WHERE asset_guid = @asset_guid

RETURN ( @KeywordList )
END

Now I can easily include the list in every row of my query by calling the function in my SELECT:

SELECT asset_name, dbo.getDelimitedKeywords(asset_guid) as Keywords
FROM assets

I didn't research how to achieve the same results in mySQL, but it's probably pretty easy to do using the GROUP_CONCAT function.


Thursday, September 10, 2009

How to show task creator's & modifier's name instead of "System Account" in the Task Library

Whenever we create a SharePoint site we will get a default list called "Tasks". This is one of great features available in SharePoint. Tasks list is being used to track workflow tasks in SharePoint. So, whenever we start a workflow and assign a task to somebody, and if he or she approve or reject it all those task activities will track and log in to the Task list.

 

That is all about the Task list. Now we can come to the reason why I am writing this blog post. We all know that whenever a task item added to a Task list, the "created by" and "modified by" columns will show the value "system account" always!

 

Once I got cool requirement from one my customers, he doesn't want to display the "System account" as the default creator or the modifier in his task list. He want to show the name of the user who has created the task, in the "created by" column and if somebody modify that task by approving/rejecting that workflow task, then that person's name has to show in the "modified by" column.

 

Interesting!

 

As a work-around what I did that, I have created an event handler – ItemAdded & ItemUpdated, which will capture the event whenever a new task Item added to the Task List and whenever we modify that task by approving/rejecting the workflow task.

 

And whenever we add or edit a task item, I just tried to update the "created by" and "modified by" columns using SPWeb.CurrentUser property. But, then I have found that, though a different user log in to the application, in the event handler that property returning the current user as "System Account".

 

More info on how to update the "created by" and "modified by" columns, please  see this post.

 

After digging into the workflow task creation process, I have found that all the tasks are creating and adding to the Task list under the Application pool identity and that is why we are getting SPWeb.CurrentUser value as "System account".

 

I was really upset because of this and in one point I had felt that we can't update the "created by" and "modified by" columns L. But I believed that there will be some hidden treasure in SharePoint which will help us really to accomplish our customization requirements.

 

I just checked the fields available for the Tasks list then I have found that, there were 2 fields:

 

Workflow List ID    =  which will return the GUID of the List from which workflow task has been created.

Workflow Item ID  =  which will return the list item from which workflow task has been created.

 

Cooool! Once we get those 2 fields then no need to worry anymore!

 

I just modified my existing custom event handler code as like below and it worked like charm!

 

    1: using System;
    2: using System.Collections.Generic;
    3: using System.Text;
    4: using Microsoft.SharePoint; 
    5:  
    6: namespace UpdateTaskColumns
    7:  
    8: {
    9:     public class UpdateColumns : SPItemEventReceiver
   10:  
   11:     {
   12:  
   13:         public override void ItemAdded(SPItemEventProperties properties)
   14:  
   15:         {
   16:             UpdateUserColumns(properties,false);       
   17:  
   18:         } 
   19:  
   20:         public override void ItemUpdated(SPItemEventProperties properties)
   21:         {
   22:             UpdateUserColumns(properties,true);
   23:  
   24:         } 
   25:  
   26:         private void UpdateUserColumns(SPItemEventProperties properties,bool IsUpdate)
   27:  
   28:         {
   29:  
   30:             SPWeb oWeb = properties.OpenWeb();
   31:  
   32:             Guid oSourceListID = new Guid(properties.ListItem["Workflow List ID"].ToString());
   33:  
   34:             SPList oSourceList = oWeb.Lists.GetList(oSourceListID, true);
   35:  
   36:             SPListItem oSourceListItem = oSourceList.GetItemById(Convert.ToInt32(properties.ListItem["Workflow Item ID"]));
   37:  
   38:             if (IsUpdate)
   39:  
   40:                 properties.ListItem["Editor"] = oSourceListItem["Editor"];
   41:  
   42:             else
   43:             {
   44:                 properties.ListItem["Author"] = oSourceListItem["Editor"];
   45:  
   46:                 properties.ListItem["Editor"] = oSourceListItem["Editor"];
   47:  
   48:             } 
   49:  
   50:             properties.ListItem.Update(); 
   51:  
   52:         }
   53:  
   54:     }
   55:  
   56: }

 

Code is self explanatory


Monday, September 7, 2009

Drop/Remove/Delete all tables in a SQL Server database

To drop all tables in a SQL Server 2005 database use :

sp_MSforeachtable command1 [,replacechar] [, command2]
[,command3] [,whereand] [,precommand] [,postcommand

Example :
exec sp_MSforeachtable "DROP TABLE ? PRINT '? dropped' "

This is the same in both SQL Server 2000 and SQL Server 2005

You have to execute the code a number of times or until no more tables remain in your database

Thursday, September 3, 2009

CSS Reference Chart for SharePoint 2007 (Microsoft Office SharePoint Server 2007 and Windows SharePoint Services v3)

www.heathersolomon.com/content/sp07cssreference.htm

How to Turn Off SharePoint Custom Error Message and Display Stack and Page Output Trace


When error occurs in SharePoint, by default the following error message is displayed:

20090111-2

To see the "true" description of the ASP.NET errors along with the Stack and Page Output Trace messages, the following steps are required:

  • In Windows Explorer, browse to the following folder: C:\inetpub\wwwroot\wss\VirtualDirectories\{SharePoint Port Number} 
  • Double-click the SharePoint web.config file.
  • In the SharePoint web.config file, look for <customErrors mode="On" /> tag and change it to <customErrors mode="Off" /> - this enables the detailed ASP.NET errors to be shown to the remote clients and to the local host (You can also set the mode value to "RemoteOnly" so that the remote clients can see the Custom Error Message and the local host is shown with detailed ASP.NET errors.).
  • In the SharePoint web.config file, locate the <SafeMode MaxControls="200" CallStack="false" tag and change it to <SafeMode MaxControls="200" CallStack="true" - this enables you to received ASP.NET exception messages with stack trace information.
  • Next, in the <system.web> element, add the following line <trace enabled="true" pageOutput="true"/> - this enables you to use the tracing feature in ASP.NET to monitor the page output and environment variables of the local host.
  • Save and close the file.

You will no longer see the SharePoint Custom Error Message page instead you get the "true" & "lovely" standard ASP.NET error page with the stack and page output trace as shown below:

20090111-1

SharePoint development has got that little bit easier!!.. I would recommend only making the following changes in a development environment and not production environment...

Windows Internal Database is not listed in the Add or Remove Programs tool and is not removed when you remove Windows SharePoint Services 3.0 from the computer

Consider the following scenario. You deploy a single-server configuration of Microsoft Windows SharePoint Services 3.0 by using the Basic installation option. After Windows SharePoint Services 3.0 is successfully installed on the computer, you open the Add or Remove Programs tool. You notice that Microsoft Windows Internal Database does not appear in the list of currently installed programs even though it is installed on the computer.

Later, you remove Windows SharePoint Services 3.0 from the computer. However, Windows Internal Database is still installed on the computer. You cannot use the Add or Remove Programs tool to remove Windows Internal Database from the computer because it does not appear in the list of currently installed programs.

Note Windows Internal Database is also referenced as Embedded Edition (Windows).
 
When you deploy Windows SharePoint Services 3.0 in a single-server configuration by using the Basic installation option, the Setup program automatically installs and configures Windows Internal Database. However, an entry for Windows Internal Database is not created in the Add or Remove Programs tool. If you remove Windows SharePoint Services 3.0, the Setup program does not automatically remove Windows Internal Database from the computer. You must use the msiexec.exe command to remove Windows Internal Database from the computer.
 
Use the msiexec.exe command to remove Windows Internal Database from the computer. To do this, use one of the following procedures, as appropriate for your situation:
  • If you are running an x86-based edition of Microsoft Windows Server 2003, use the following command line to remove Windows Internal Database from the computer:
    msiexec /x {CEB5780F-1A70-44A9-850F-DE6C4F6AA8FB} CALLERID=ocsetup.exe
  • If you are running an x64-based edition of Windows Server 2003, use the following command line to remove Windows Internal Database from the computer:
    msiexec /x {BDD79957-5801-4A2D-B09E-852E7FA64D01} CALLERID=ocsetup.exe
When you use the Basic installation option to deploy a single-server configuration of Windows SharePoint Services 3.0, Windows Internal Database is used to create the configuration database and the content database.
 
APPLIES TO
  • Microsoft Windows SharePoint Services 3.0

Configuring Forms Based Authentication (FBA) in SharePoint

Saturday, August 8, 2009


If we want to configure Forms Based Authentication (FBA) in SharePoint,
then we have to follow following steps -

Configuration Steps:
1) Setup the membership data store.
2) Create an ASP.Net Web Site to manage Roles and Users.
3) Open ASP.Net Web Site's Web Administration Tool.
4) Create a new Web Application from SharePoint Central Administration site.
5) Extend Web Application
6) Change Authentication Provider for Forms based site.
7) Change configuration files settings.
8) Change policy for Web Application
9) Add users/roles as site administrator (Primary and Secondary).
10) Check Forms Based Authentication



Now I will explain each steps in some detail -



1) Setup the membership data store.

To create database, Microsoft has provided a tool/ utility called aspnet_regsql.exe that creates a database for us.
This utility can be found in
%windir%\Microsoft.Net\Framework\vx.x.xxxxx folder.

Double click or run aspnet_regsql.exe,
it opens a pop-up window as demonstrated in following images :




[Figure - 1]



[Figure - 2]



[Figure - 3]
Note: Enter your Server Name and Database name in fields.




[Figure - 4]



[Figure - 5]



[Figure - 6]


Note: Check whether your custom MembershipDB is accessible by NT AUTHORITY\ NETWORK SERVICE or not.

Steps:
a) Open MS SQL Server Management Studio
b) Select SERVER (in Tree-node at left side)
c) Select Security
d) Select Logins
e) Select NT AUTHORITY\NETWORK SERVICE
f) Right-click on it, select Properties
g) Its pop-ups Login Properties window.
Select User Mapping (in Tree-node at left side)
h) Check your database name in top-right pane and
its corresponding access in bottom-right pane.
i) Click OK.
j) Then to check effective permissions of your custom MembershipDB,
select DB from left side tree view.
Server – Databases – custom MembershipDB
k) Right-click on custom MembershipDB, select Properties.
l) In Database Properties window, select Permission
(in left pane).
m) Select NT AUTHORITY\NETWORK SERVICE (in right pane),
click Effective Permissions button.
n) Check whether it has required permissions or not.
If not then assign required permissions.




2) Create a new ASP.Net Web Site to manage Roles and Users.

Do following changes in temporary ASP.Net web site's configuration file:

Web site's configuration file (web.config) ---



<configuration>
<!--Remaining settings-->

<connectionStrings>
<add name="CustomMembershipDBCNX"
connectionString="SERVER=Server-Name; DATABASE=CustomMembershipDB;
TRUSTED_CONNECTION=true;"
providerName="System.Data.SqlClient" />
</connectionStrings>

<system.web>
<!--Remaining settings-->

<machineKey validationKey="Copy-it-from-sharepoint-site-cofig-file"
decryptionKey="Copy-it-from-sharepoint-site-cofig-file"
validation="SHA1" />

<authentication mode="Forms">
<forms loginUrl="/_layouts/login.aspx" />
</authentication>

<membership defaultProvider="CustomMembershipProvider">
<providers>
<add name="CustomMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="CustomMembershipDBCNX"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
/>
</providers>
</membership>

<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
<add name="CustomRoleProvider"
connectionStringName="CustomMembershipDBCNX"
applicationName="/"
type="System.Web.Security.SqlRoleProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
</providers>
</roleManager>
</system.web>
</configuration>




Changed following 4 settings in above snippet (quick review):
a) connectionStrings
b) machineKey
c) authentication
d) membership
e) roleManager



3) Open ASP.Net Web Site's Web Administration Tool

Go To ---
Menu -> Website -> ASP.Net Configuration




[Figure - 7]


a) Security tab: To manage/create Roles and User
b) Provider tab: To test both Custom membership and role provider
(click Select a different provider for each feature (advanced) link).



4) Create a new Web Application from SharePoint Central Administration site

Step:

Central Administration > Application Management >
Create or Extend Web Application > Create New Web Application

After creating the Web Application create Site Collection (link gets displayed after completing the above step)



5) Extend Web Application

Note: Select proper site (from top-right dropdown) that you want to extend.
Step:

Central Administration > Application Management > Create or Extend Web Application > Extend Web Application to Another IIS Web Site

In above step/page select Zone as Extranet or Internet as per your requirement.



6) Change Authentication Provider for Forms based site

Note: Select proper site and zone (from top-right dropdown) whose Authentication Provider you want to change to Forms Based.

Step:

Central Administration > Application Management > Authentication Providers > Edit Authentication

a) Select Authentication Type as Forms.
b) Disable Anonymous access
c) Enter custom Membership provider name
d) Enter custom Role manager name

Save the changes.



7) Change configuration files settings

Changes required in SharePoint Central Administration configuration file (web.config).

IMPORTANT: Do take the back-up of web.config file.





<configuration>
<SharePoint>
<!--Remaining settings-->

<PeoplePickerWildcards>
<clear />
<add key="AspNetSqlMembershipProvider" value="%" />
<add key="CustomMembershipProvider" value="%" />
</PeoplePickerWildcards>

</SharePoint>
<!--Remaining settings-->

<connectionStrings>
<add name="CustomMembershipDBCNX"
connectionString="SERVER=Server-Name; DATABASE=CustomMembershipDB;
TRUSTED_CONNECTION=true;"
providerName="System.Data.SqlClient" />
</connectionStrings>

<system.web>
<!--Remaining settings-->

<membership>
<providers>
<add name="CustomMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="CustomMembershipDBCNX"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
/>
</providers>
</membership>

<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
<providers>
<add name="CustomRoleProvider"
connectionStringName="CustomMembershipDBCNX"
applicationName="/"
type="System.Web.Security.SqlRoleProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
</providers>
</roleManager>
</system.web>
</configuration>






Changed following 4 settings in above snippet (quick review):
a) PeoplePickerWildcards – To detect your custom provider
b) connectionStrings
c) membership – Don't specify default provider
d) roleManager – Change default provider to AspNetWindowsTokenRoleProvider

Note : Don't change MachineKey.



Now made following changes in SharePoint Web Application's (created in step 4) configuration file (default one with Windows authentication) (web.config)





<configuration>
<SharePoint>
<!--Remaining settings-->

<PeoplePickerWildcards>
<clear />
<add key="AspNetSqlMembershipProvider" value="%" />
<add key="CustomMembershipProvider" value="%" />
</PeoplePickerWildcards>

</SharePoint>
<!--Remaining settings-->

<connectionStrings>
<add name="CustomMembershipDBCNX"
connectionString="SERVER=Server-Name; DATABASE=CustomMembershipDB;
TRUSTED_CONNECTION=true;"
providerName="System.Data.SqlClient" />
</connectionStrings>

<system.web>
<!--Remaining settings-->

<membership defaultProvider="CustomMembershipProvider">
<providers>
<add name="CustomMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="CustomMembershipDBCNX"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
/>
</providers>
</membership>

<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
<add name="CustomRoleProvider"
connectionStringName="CustomMembershipDBCNX"
applicationName="/"
type="System.Web.Security.SqlRoleProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
</providers>
</roleManager>
</system.web>
</configuration>







Changed following 4 settings in above snippet (quick review):
a) PeoplePickerWildcards – To detect your custom provider
b) connectionStrings
c) membership
d) roleManager

Note : Don't change MachineKey.



Repeat above configuration changes for Forms Based Web Application's (created in step 5) configuration file (web.config)
(port number will be different).

The only difference in case of Forms Based Web Application's config file will be:




<configuration>
<system.web>
<!--Remaining settings-->

<authentication mode="Forms">
<forms loginUrl="/_layouts/login.aspx"
timeout="120"
cookieless="UseCookies"
slidingExpiration="true" />
</authentication>
</system.web>
</configuration>





Changed following 5 settings in Forms based site's config (quick review):
a) PeoplePickerWildcards – To detect your custom provider
b) connectionStrings
c) membership
d) roleManager
e) Authentication – It will be automatically set by STEP 6.


So in total, we have to change 3 configuration files:
a) SharePoint's Central Administration
b) Web Application with Default zone (Windows) [created in step 4]
c) Web Application with Internet/Extranet zone (Forms) [created in step 5]



8) Change policy for Web Application

Note: Select proper site (from top-right dropdown).

Step:

Central Administration > Application Management > Policy for Web Application

Click Add Users (top-left) to add new users/roles. Assign permission as per requirement.
Common Error: Access Denied

Steps to solve above error :

a) Go to --- SharePoint Central Administration > Application Management > Policy for Web Application
b) Select proper Web Application (from top-right)
c) Click "Add User" (top-left)
d) Add required User or Role in it.
e) Grant it "Full Control" (as per requirement) out of following options:
• Full Control - Has full control.
• Full Read - Has full read-only access.
• Deny Write - Has no write access.
• Deny All - Has no access.



9) Add users/roles as site administrator (Primary and Secondary)

Note: Select proper site (from top-right dropdown).

Step:

Central Administration > Application Management > Site Collection Owners



10) Open Forms based URL in browser; it will redirect you to login page

It means site is properly configured for Forms Based Authentication (FBA).

Enter the <Username> and <Password> (refer step 3) in login page; if you are able to login, its mean database is properly configured.
Otherwise check username, password, roles in DB and also the effective permissions of NT AUTHORITY\NETWORK SERVICE.

Deploy a SharePoint Solution Programmatically

A lot of you are familiar with the new solutions story within Windows SharePoint Services 3.0. In short, you package your solution components (assemblies, features, …) together with a manifest file into a SharePoint solution file (represented by a wsp file). Next, you can add the SharePoint solution to the solution store (typically using stsadm) and the using the SharePoint 3.0 Central Administration, you can deploy it to one of the available site collections either locally or on front-end Web Servers or application servers.

All of this is also exposed in the object model. I am currently finishing an MSDN article titled 'SharePoint Development Tools and Techniques for Creating, Packaging, Deploying, and Maintaining Code' and I have included some discussions on all of this. As a small teaser, here are the steps how you can add a solution to a solution store and deploy it to a site collection using C# code assuming you deploy everything on a local machine.

// -- adding the solution to the solution store
SPSolution solution = SPFarm.Local.Solutions.Add(@"C:\Packages\HelloWebPart.wsp");

// -- deploying the solution to a site collection
Collection<SPWebApplication> webapps = new Collection<SPWebApplication>();
SPWebApplication webapp = SPWebApplication.Lookup(new Uri("http://wss.litwareinc.com"));
webapps.Add(webapp);
solution.DeployLocal(true, webapps, true);

The assembly you need to reference is the Microsoft.SharePoint.dll and the namespaces used here are Microsoft.SharePoint.Administration and System.Collections.ObjectModel.

C# Example: How to get all sites from SharePoint using SPGlobalAdmin and SPVirtualServer objects.

SPListGallery class is the example to learn how people can easy connect the SharePoint gallery and get fast all sites from there by SharePoint object model.

Run example:

SPListGallery gallery = new SPListGallery("http://localserver/");
gallery.GetSharePointSites();       


//===================================================================
// Developer : Tomek Prentki
// Description : Example to get all sites from SharePoint.
//===================================================================

using System;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace Framework.Business.Components
{
   /// <summary>
   /// SPListGallery class is the example to learn how people can easy connect into SharePoint gallery and get fast all sites from there.
   /// The is most fastest solution, but very safe to get all object modal important information's.    
   /// </summary>

   public class SPListGallery
   { 
      private string _locationPath;

      /// <summary>
      /// Before you run the SPListGallery functions, first set the properties.
      /// Example -> http header value  of your site ->
http://localhost/
      /// </summary>
      public string LocationPath
     {
         get{
            return _locationPath;
         }
         set{
           _locationPath = value;
      }

  }

  /// <summary>
  /// Constructor.
  /// </summary>

  public SPListGallery(string siteLocation)
  {
      if(siteLocation.Length > 0){
         LocationPath = siteLocation;
      }
      else
      {
       Console.WriteLine("ERROR SITE LOCATION: To run application you need the site location.");    
      }
  }

  /// <summary>
  /// This method get all sharepoint sites.
  /// </summary>

  public void GetSharePointSites()
  {
      SPSite site = null; //Site object
      Uri url = new Uri(LocationPath); 
   
      SPGlobalAdmin globalAdmin = new SPGlobalAdmin();
      SPVirtualServer  virtualServer = globalAdmin.OpenVirtualServer(url); 
   
      //Get all sites from SharePoint location.
      for(int cnt=0; cnt < virtualServer.Sites.Count;cnt++)
      { 
          try
          {
              site = virtualServer.Sites[cnt];
              foreach (SPWeb web in site.AllWebs)
              {
                  try
                     { 
                         //Get the site and web url.
                         Console.WriteLine("SITE NAME : " + web.Title);
                         Console.WriteLine("SITE URL    : " + web.Url);
                     }
                     catch(Exception ex)
                     {
                         Console.WriteLine("ERROR WEB MESSAGE: " + ex.ToString());
                     }
                     finally
                     {
                         web.Close(); //Close objects
                     }
                 }
          }
          catch(Exception ex)
          {
              Console.WriteLine("ERROR VIRTUAL SERVER MESSAGE: " + ex.ToString());
          }
          finally
          {
              site.Close(); //Close site object
          }
      }
   globalAdmin.Close();  // CloseSPGlobalAdmin object.
  }
 }
}

How to: Customize the ASP.NET CreateUserWizard Control

You can customize the contents of the CreateUserWizard control using the CreateUserWizardStep and CompleteWizardStep templates. By specifying the contents of the templates, you can specify your own custom user interface (UI) that includes controls that the CreateUserWizard control uses to gather information about the new user, as well as additional controls that you specify (for a list of the controls that the CreateUserWizard control uses, see Customizing the Appearance of ASP.NET Login Controls.)

Additionally, because the CreateUserWizard control inherits from the Wizard class, you can add your own custom steps to the CreateUserWizard control. For more information on the Wizard control, see Wizard Web Server Control Overview.

NoteNote:

You can also customize the appearance of the CreateUserWizard control using themes and style properties. For details, see ASP.NET Themes and Skins Overview and the properties of the CreateUserWizard control.

To customize the CreateUserWizard steps

  1. Place a CreateUserWizard control on your page using the following syntax.

    <asp:CreateUserWizard ID="CreateUserWizard1" Runat="server">
    <WizardSteps>
    <asp:CreateUserWizardStep runat="server">
    </asp:CreateUserWizardStep>
    <asp:CompleteWizardStep runat="server">
    </asp:CompleteWizardStep>
    </WizardSteps>
    </asp:CreateUserWizard>
  2. To customize the user account creation step, create a <ContentTemplate> element within the <asp:CreateUserWizardStep> element. Inside the template, add markup and controls to define the layout and content of the UI for gathering the user information you need.

    NoteNote:

    If your membership provider extends the MembershipProvider class with custom members, you must add any controls to gather custom information required by your membership provider for creating a new user. For details, see CreateUserWizardStep.

    The following code example shows a CreateUserStep property that includes CheckBox controls that enable users to specify additional options.

    Visual Basic
    <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
    <ContentTemplate>
    <table border="0" style="font-size: 100%; font-family: Verdana">
    <tr>
    <td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d">
    Sign Up for Your New Account</td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserName">
    User Name:</asp:Label></td>
    <td>
    <asp:TextBox ID="UserName" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="UserNameRequired" runat="server" ControlToValidate="UserName"
    ErrorMessage="User Name is required." ToolTip="User Name is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="PasswordLabel" runat="server" AssociatedControlID="Password">
    Password:</asp:Label></td>
    <td>
    <asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox>
    <asp:RequiredFieldValidator ID="PasswordRequired" runat="server" ControlToValidate="Password"
    ErrorMessage="Password is required." ToolTip="Password is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="ConfirmPasswordLabel" runat="server" AssociatedControlID="ConfirmPassword">
    Confirm Password:</asp:Label></td>
    <td>
    <asp:TextBox ID="ConfirmPassword" runat="server" TextMode="Password"></asp:TextBox>
    <asp:RequiredFieldValidator ID="ConfirmPasswordRequired" runat="server" ControlToValidate="ConfirmPassword"
    ErrorMessage="Confirm Password is required." ToolTip="Confirm Password is required."
    ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Email">
    E-mail:</asp:Label></td>
    <td>
    <asp:TextBox ID="Email" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="EmailRequired" runat="server" ControlToValidate="Email"
    ErrorMessage="E-mail is required." ToolTip="E-mail is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="QuestionLabel" runat="server" AssociatedControlID="Question">
    Security Question:</asp:Label></td>
    <td>
    <asp:TextBox ID="Question" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="QuestionRequired" runat="server" ControlToValidate="Question"
    ErrorMessage="Security question is required." ToolTip="Security question is required."
    ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="Answer">
    Security Answer:</asp:Label></td>
    <td>
    <asp:TextBox ID="Answer" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="AnswerRequired" runat="server" ControlToValidate="Answer"
    ErrorMessage="Security answer is required." ToolTip="Security answer is required."
    ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="center" colspan="2">
    <asp:CompareValidator ID="PasswordCompare" runat="server" ControlToCompare="Password"
    ControlToValidate="ConfirmPassword" Display="Dynamic" ErrorMessage="The Password and Confirmation Password must match."
    ValidationGroup="CreateUserWizard1"></asp:CompareValidator>
    </td>
    </tr>
    <tr>
    <td align="center" colspan="2" style="color: red">
    <asp:Literal ID="ErrorMessage" runat="server" EnableViewState="False"></asp:Literal>
    </td>
    </tr>
    </table>
    <asp:CheckBox ID="SubscribeCheckBox" runat="server" Checked="True" Text="Send me a monthly newsletter." />
    <br />
    <asp:CheckBox ID="ShareInfoCheckBox" runat="server" Checked="True" Text="Share my information with partner sites." />
    </ContentTemplate>
    </asp:CreateUserWizardStep>
    C#
    <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
    <ContentTemplate>
    <table border="0" style="font-size: 100%; font-family: Verdana">
    <tr>
    <td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d">
    Sign Up for Your New Account</td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserName">
    User Name:</asp:Label></td>
    <td>
    <asp:TextBox ID="UserName" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="UserNameRequired" runat="server" ControlToValidate="UserName"
    ErrorMessage="User Name is required." ToolTip="User Name is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="PasswordLabel" runat="server" AssociatedControlID="Password">
    Password:</asp:Label></td>
    <td>
    <asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox>
    <asp:RequiredFieldValidator ID="PasswordRequired" runat="server" ControlToValidate="Password"
    ErrorMessage="Password is required." ToolTip="Password is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="ConfirmPasswordLabel" runat="server" AssociatedControlID="ConfirmPassword">
    Confirm Password:</asp:Label></td>
    <td>
    <asp:TextBox ID="ConfirmPassword" runat="server" TextMode="Password"></asp:TextBox>
    <asp:RequiredFieldValidator ID="ConfirmPasswordRequired" runat="server" ControlToValidate="ConfirmPassword"
    ErrorMessage="Confirm Password is required." ToolTip="Confirm Password is required."
    ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Email">
    E-mail:</asp:Label></td>
    <td>
    <asp:TextBox ID="Email" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="EmailRequired" runat="server" ControlToValidate="Email"
    ErrorMessage="E-mail is required." ToolTip="E-mail is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="QuestionLabel" runat="server" AssociatedControlID="Question">
    Security Question:</asp:Label></td>
    <td>
    <asp:TextBox ID="Question" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="QuestionRequired" runat="server" ControlToValidate="Question"
    ErrorMessage="Security question is required." ToolTip="Security question is required."
    ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="Answer">
    Security Answer:</asp:Label></td>
    <td>
    <asp:TextBox ID="Answer" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="AnswerRequired" runat="server" ControlToValidate="Answer"
    ErrorMessage="Security answer is required." ToolTip="Security answer is required."
    ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="center" colspan="2">
    <asp:CompareValidator ID="PasswordCompare" runat="server" ControlToCompare="Password"
    ControlToValidate="ConfirmPassword" Display="Dynamic" ErrorMessage="The Password and Confirmation Password must match."
    ValidationGroup="CreateUserWizard1"></asp:CompareValidator>
    </td>
    </tr>
    <tr>
    <td align="center" colspan="2" style="color: red">
    <asp:Literal ID="ErrorMessage" runat="server" EnableViewState="False"></asp:Literal>
    </td>
    </tr>
    </table>
    <asp:CheckBox ID="SubscribeCheckBox" runat="server" Checked="True" Text="Send me a monthly newsletter." />
    <br />
    <asp:CheckBox ID="ShareInfoCheckBox" runat="server" Checked="True" Text="Share my information with partner sites." />
    </ContentTemplate>
    </asp:CreateUserWizardStep>
  3. To customize the completion step, create a <ContentTemplate> element within the <asp:CompleteWizardStep> element. Inside the template, add markup and controls to define the layout and content of the UI for displaying a confirmation message and optionally allowing the user to navigate to continue. (You must provide the controls to gather the information required by your membership provider for creating a new user account. For details, see CompleteWizardStep.)

    The following code example shows a CompleteStep property that references the CheckBox controls from the previous example.

    Visual Basic
    <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
    <ContentTemplate>
    <table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
    <tr>
    <td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d; height: 18px;">
    Complete</td>
    </tr>
    <tr>
    <td>
    Your account has been successfully created.<br />
    <br />
    <asp:Label ID="SubscribeLabel" runat="server" Text="You have elected to receive our monthly newsletter."></asp:Label><br />
    <br />
    <asp:Label ID="ShareInfoLabel" runat="server" Text="You have elected to share your information with partner sites."></asp:Label></td>
    </tr>
    <tr>
    <td align="right" colspan="2">
    &nbsp;<asp:Button ID="ContinueButton" runat="server" BackColor="#FFFBFF" BorderColor="#CCCCCC"
    BorderStyle="Solid" BorderWidth="1px" CausesValidation="False" CommandName="Continue"
    Font-Names="Verdana" ForeColor="#284775" Text="Continue" ValidationGroup="CreateUserWizard1" />
    </td>
    </tr>
    </table>
    </ContentTemplate>
    </asp:CompleteWizardStep>
    C#
    <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
    <ContentTemplate>
    <table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
    <tr>
    <td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d; height: 18px;">
    Complete</td>
    </tr>
    <tr>
    <td>
    Your account has been successfully created.<br />
    <br />
    <asp:Label ID="SubscribeLabel" runat="server" Text="You have elected to receive our monthly newsletter."></asp:Label><br />
    <br />
    <asp:Label ID="ShareInfoLabel" runat="server" Text="You have elected to share your information with partner sites."></asp:Label></td>
    </tr>
    <tr>
    <td align="right" colspan="2">
    &nbsp;<asp:Button ID="ContinueButton" runat="server" BackColor="#FFFBFF" BorderColor="#CCCCCC"
    BorderStyle="Solid" BorderWidth="1px" CausesValidation="False" CommandName="Continue"
    Font-Names="Verdana" ForeColor="#284775" Text="Continue" ValidationGroup="CreateUserWizard1" />
    </td>
    </tr>
    </table>
    </ContentTemplate>
    </asp:CompleteWizardStep>
  4. Add code to reference the additional controls. For example, handling the CreatingUser event enables you to enter code to gather, verify, and modify information before a new user account is created.

    The following code example shows a handler for the CreatedUser event that references the CheckBox controls from the previous examples and adds them to the Comment property of the newly created user account. You will need to add an OnCreatedUser attribute to the CreateUserWizard control on your page that references the handler for the CreatedUser event (for example, OnCreatedUser="CreateUserWizard1_CreatedUser".)

    Visual Basic
    Protected Sub CreateUserWizard1_CreatedUser(ByVal sender As Object, ByVal e As EventArgs)
    ' Determine the checkbox values.
    Dim subscribeCheckBox As CheckBox = _
    CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("SubscribeCheckBox"), CheckBox)
    Dim shareInfoCheckBox As CheckBox = _
    CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("ShareInfoCheckBox"), CheckBox)
    Dim userNameTextBox As TextBox = _
    CType(CreateUserWizardStep1.ContentTemplateContainer.FindControl("UserName"), TextBox)


    Dim user As MembershipUser = Membership.GetUser(userNameTextBox.Text)
    User.Comment = "Subscribe=" & subscribeCheckBox.Checked.ToString() & "&" & _
    "ShareInfo=" & shareInfoCheckBox.Checked.ToString()
    Membership.UpdateUser(user)

    ' Show or hide the labels based on the checkbox values.
    Dim subscribeLabel As Label = _
    CType(CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("SubscribeLabel"), Label)
    Dim shareInfoLabel As Label = _
    CType(CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("ShareInfoLabel"), Label)

    subscribeLabel.Visible = subscribeCheckBox.Checked
    shareInfoLabel.Visible = shareInfoCheckBox.Checked
    End Sub
    C#
    protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
    {
    // Determine the checkbox values.
    CheckBox subscribeCheckBox =
    (CheckBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("SubscribeCheckBox");
    CheckBox shareInfoCheckBox =
    (CheckBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("ShareInfoCheckBox");
    TextBox userNameTextBox =
    (TextBox)CreateUserWizardStep1.ContentTemplateContainer.FindControl("UserName");

    MembershipUser user = Membership.GetUser(userNameTextBox.Text);
    user.Comment = "Subscribe=" + subscribeCheckBox.Checked.ToString() + "&" +
    "ShareInfo=" + shareInfoCheckBox.Checked.ToString();
    Membership.UpdateUser(user);

    // Show or hide the labels based on the checkbox values.
    Label subscribeLabel =
    (Label)CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("SubscribeLabel");
    Label shareInfoLabel =
    (Label)CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("ShareInfoLabel");

    subscribeLabel.Visible = subscribeCheckBox.Checked;
    shareInfoLabel.Visible = shareInfoCheckBox.Checked;
    }

To add a wizard step

  1. Add an <asp:WizardStep> element to the <WizardSteps> section of the CreateUserWizard control. Include any controls and markup in the additional wizard step that your customized CreateUserWizard control will use.

    For example, the following code example shows a step to be added before the CreateUserStep of the CreateUserWizard control that includes a textbox control for users to enter a user name. The user name will be checked to ensure that it does not already exist in the membership database.

    Visual Basic
    <asp:WizardStep ID="CreateUserWizardStep0" runat="server">
    <table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
    <tr>
    <td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d">
    Select an Account Name</td>
    </tr>
    <tr>
    <td>
    <asp:Label ID="AccountNameLabel" runat="server" AssociatedControlID="SearchAccount" >
    Account Name:</asp:Label>
    <asp:TextBox ID="SearchAccount" runat="server"></asp:TextBox><br />
    <asp:Label ID="SearchAccountMessage" runat="server" ForeColor="red" />
    </td>
    </tr>
    </table>
    </asp:WizardStep>
    C#
    <asp:WizardStep ID="CreateUserWizardStep0" runat="server">
    <table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
    <tr>
    <td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d">
    Select an Account Name</td>
    </tr>
    <tr>
    <td>
    <asp:Label ID="AccountNameLabel" runat="server" AssociatedControlID="SearchAccount" >
    Account Name:</asp:Label>
    <asp:TextBox ID="SearchAccount" runat="server"></asp:TextBox><br />
    <asp:Label ID="SearchAccountMessage" runat="server" ForeColor="red" />
    </td>
    </tr>
    </table>
    </asp:WizardStep>
  2. Add code for your wizard step. You can handle the NextButtonClick event of the Wizard control to execute your code. The CurrentStepIndex property value indicates which additional wizard step raised the NextButtonClick event by the step index number (starting from 0 for the first step).

    The following code example shows a handler for the NextButtonClick event that takes the user name entered in the TextBox control in the wizard step from the previous code example and verifies that the user name is not blank and does not currently exist in the membership database. You will need to add an OnNextButtonClick attribute to the CreateUserWizard control on your page that references the handler for the NextButtonClick event handler (for example, OnNextButtonClick="CreateUserWizard1_NextButtonClick".)

    Visual Basic
    Private Function UserExists(ByVal username As String) As Boolean
    If Membership.GetUser(username) IsNot Nothing Then Return True

    Return False
    End Function

    Protected Sub CreateUserWizard1_NextButtonClick(ByVal sender As Object, ByVal e As WizardNavigationEventArgs)
    If e.CurrentStepIndex = 0 Then
    If SearchAccount.Text.Trim() = "" OrElse UserExists(SearchAccount.Text) Then
    SearchAccountMessage.Text = "That account already exists. Please select an different account name."
    e.Cancel = True
    Else
    Dim userName As TextBox = _
    CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("UserName"), TextBox)
    userName.Text = SearchAccount.Text
    SearchAccountMessage.Text = ""
    e.Cancel = False
    End If
    End If
    End Sub
    C#
    private bool UserExists(string username)
    {
    if (Membership.GetUser(username) != null) { return true; }

    return false;
    }

    protected void CreateUserWizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
    {
    if (e.CurrentStepIndex == 0)
    {
    if (SearchAccount.Text.Trim() == "" || UserExists(SearchAccount.Text))
    {
    SearchAccountMessage.Text = "That account already exists. Please select an different account name.";
    e.Cancel = true;
    }
    else
    {
    TextBox userName =
    (TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("UserName");
    userName.Text = SearchAccount.Text;
    SearchAccountMessage.Text = "";
    e.Cancel = false;
    }
    }
    }
    Security noteSecurity Note:

    This control has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages validate user input to ensure that the input does not contain HTML elements or script. For more information, see Script Exploits Overview.

The following code example shows a CreateUserWizard control with templates defined for the two basic steps, CreateUserStep and CompleteStep, and an additional wizard step added before the CreateUserStep.

Security noteSecurity Note:

This control has a textbox that accepts user input, which is a potential security threat. User input in a Web page can potentially contain malicious client script. By default, ASP.NET Web pages validate user input to ensure that the input does not contain HTML elements or script. As long as this validation is enabled, you do not need to explicitly check for script or HTML elements in user input. For more information, see Script Exploits Overview.

Visual Basic
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
Protected Sub CreateUserWizard1_CreatedUser(ByVal sender As Object, ByVal e As EventArgs)
' Determine the checkbox values.
Dim subscribeCheckBox As CheckBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("SubscribeCheckBox"), CheckBox)
Dim shareInfoCheckBox As CheckBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("ShareInfoCheckBox"), CheckBox)
Dim userNameTextBox As TextBox = _
CType(CreateUserWizardStep1.ContentTemplateContainer.FindControl("UserName"), TextBox)


Dim user As MembershipUser = Membership.GetUser(userNameTextBox.Text)
User.Comment = "Subscribe=" & subscribeCheckBox.Checked.ToString() & "&" & _
"ShareInfo=" & shareInfoCheckBox.Checked.ToString()
Membership.UpdateUser(user)

' Show or hide the labels based on the checkbox values.
Dim subscribeLabel As Label = _
CType(CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("SubscribeLabel"), Label)
Dim shareInfoLabel As Label = _
CType(CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("ShareInfoLabel"), Label)

subscribeLabel.Visible = subscribeCheckBox.Checked
shareInfoLabel.Visible = shareInfoCheckBox.Checked
End Sub

Private Function UserExists(ByVal username As String) As Boolean
If Membership.GetUser(username) IsNot Nothing Then Return True

Return False
End Function

Protected Sub CreateUserWizard1_NextButtonClick(ByVal sender As Object, ByVal e As WizardNavigationEventArgs)
If e.CurrentStepIndex = 0 Then
If SearchAccount.Text.Trim() = "" OrElse UserExists(SearchAccount.Text) Then
SearchAccountMessage.Text = "That account already exists. Please select an different account name."
e.Cancel = True
Else
Dim userName As TextBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("UserName"), TextBox)
userName.Text = SearchAccount.Text
SearchAccountMessage.Text = ""
e.Cancel = False
End If
End If
End Sub
</script>

<html >
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:CreateUserWizard ID="CreateUserWizard1" runat="server" BackColor="#F7F6F3" BorderColor="#E6E2D8"
BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em"
OnNextButtonClick="CreateUserWizard1_NextButtonClick"
OnCreatedUser="CreateUserWizard1_CreatedUser" ContinueDestinationPageUrl="~/Default.aspx">
<WizardSteps>
<asp:WizardStep ID="CreateUserWizardStep0" runat="server">
<table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d">
Select an Account Name</td>
</tr>
<tr>
<td>
<asp:Label ID="AccountNameLabel" runat="server" AssociatedControlID="SearchAccount" >
Account Name:</asp:Label>
<asp:TextBox ID="SearchAccount" runat="server"></asp:TextBox><br />
<asp:Label ID="SearchAccountMessage" runat="server" ForeColor="red" />
</td>
</tr>
</table>
</asp:WizardStep>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana">
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d">
Sign Up for Your New Account</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserName">
User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server" ControlToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User Name is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="PasswordLabel" runat="server" AssociatedControlID="Password">
Password:</asp:Label></td>
<td>
<asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat="server" ControlToValidate="Password"
ErrorMessage="Password is required." ToolTip="Password is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="ConfirmPasswordLabel" runat="server" AssociatedControlID="ConfirmPassword">
Confirm Password:</asp:Label></td>
<td>
<asp:TextBox ID="ConfirmPassword" runat="server" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="ConfirmPasswordRequired" runat="server" ControlToValidate="ConfirmPassword"
ErrorMessage="Confirm Password is required." ToolTip="Confirm Password is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Email">
E-mail:</asp:Label></td>
<td>
<asp:TextBox ID="Email" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="EmailRequired" runat="server" ControlToValidate="Email"
ErrorMessage="E-mail is required." ToolTip="E-mail is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="QuestionLabel" runat="server" AssociatedControlID="Question">
Security Question:</asp:Label></td>
<td>
<asp:TextBox ID="Question" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="QuestionRequired" runat="server" ControlToValidate="Question"
ErrorMessage="Security question is required." ToolTip="Security question is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="Answer">
Security Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="server" ControlToValidate="Answer"
ErrorMessage="Security answer is required." ToolTip="Security answer is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<asp:CompareValidator ID="PasswordCompare" runat="server" ControlToCompare="Password"
ControlToValidate="ConfirmPassword" Display="Dynamic" ErrorMessage="The Password and Confirmation Password must match."
ValidationGroup="CreateUserWizard1"></asp:CompareValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="ErrorMessage" runat="server" EnableViewState="False"></asp:Literal>
</td>
</tr>
</table>
<asp:CheckBox ID="SubscribeCheckBox" runat="server" Checked="True" Text="Send me a monthly newsletter." />
<br />
<asp:CheckBox ID="ShareInfoCheckBox" runat="server" Checked="True" Text="Share my information with partner sites." />
</ContentTemplate>
</asp:CreateUserWizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d; height: 18px;">
Complete</td>
</tr>
<tr>
<td>
Your account has been successfully created.<br />
<br />
<asp:Label ID="SubscribeLabel" runat="server" Text="You have elected to receive our monthly newsletter."></asp:Label><br />
<br />
<asp:Label ID="ShareInfoLabel" runat="server" Text="You have elected to share your information with partner sites."></asp:Label></td>
</tr>
<tr>
<td align="right" colspan="2">
&nbsp;<asp:Button ID="ContinueButton" runat="server" BackColor="#FFFBFF" BorderColor="#CCCCCC"
BorderStyle="Solid" BorderWidth="1px" CausesValidation="False" CommandName="Continue"
Font-Names="Verdana" ForeColor="#284775" Text="Continue" ValidationGroup="CreateUserWizard1" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:CompleteWizardStep>
</WizardSteps>
<SideBarStyle BackColor="#5D7B9D" BorderWidth="0px" Font-Size="0.9em" VerticalAlign="Top" />
<TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
<SideBarButtonStyle BorderWidth="0px" Font-Names="Verdana" ForeColor="White" />
<NavigationButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<HeaderStyle BackColor="#5D7B9D" BorderStyle="Solid" Font-Bold="True" Font-Size="0.9em"
ForeColor="White" HorizontalAlign="Center" />
<CreateUserButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<ContinueButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<StepStyle BorderWidth="0px" />
</asp:CreateUserWizard>
&nbsp;</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
// Determine the checkbox values.
CheckBox subscribeCheckBox =
(CheckBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("SubscribeCheckBox");
CheckBox shareInfoCheckBox =
(CheckBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("ShareInfoCheckBox");
TextBox userNameTextBox =
(TextBox)CreateUserWizardStep1.ContentTemplateContainer.FindControl("UserName");

MembershipUser user = Membership.GetUser(userNameTextBox.Text);
user.Comment = "Subscribe=" + subscribeCheckBox.Checked.ToString() + "&" +
"ShareInfo=" + shareInfoCheckBox.Checked.ToString();
Membership.UpdateUser(user);

// Show or hide the labels based on the checkbox values.
Label subscribeLabel =
(Label)CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("SubscribeLabel");
Label shareInfoLabel =
(Label)CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("ShareInfoLabel");

subscribeLabel.Visible = subscribeCheckBox.Checked;
shareInfoLabel.Visible = shareInfoCheckBox.Checked;
}

private bool UserExists(string username)
{
if (Membership.GetUser(username) != null) { return true; }

return false;
}

protected void CreateUserWizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
{
if (e.CurrentStepIndex == 0)
{
if (SearchAccount.Text.Trim() == "" || UserExists(SearchAccount.Text))
{
SearchAccountMessage.Text = "That account already exists. Please select an different account name.";
e.Cancel = true;
}
else
{
TextBox userName =
(TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("UserName");
userName.Text = SearchAccount.Text;
SearchAccountMessage.Text = "";
e.Cancel = false;
}
}
}
</script>

<html >
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:CreateUserWizard ID="CreateUserWizard1" runat="server" BackColor="#F7F6F3" BorderColor="#E6E2D8"
BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em"
OnNextButtonClick="CreateUserWizard1_NextButtonClick"
OnCreatedUser="CreateUserWizard1_CreatedUser" ContinueDestinationPageUrl="~/Default.aspx">
<WizardSteps>
<asp:WizardStep ID="CreateUserWizardStep0" runat="server">
<table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d">
Select an Account Name</td>
</tr>
<tr>
<td>
<asp:Label ID="AccountNameLabel" runat="server" AssociatedControlID="SearchAccount" >
Account Name:</asp:Label>
<asp:TextBox ID="SearchAccount" runat="server"></asp:TextBox><br />
<asp:Label ID="SearchAccountMessage" runat="server" ForeColor="red" />
</td>
</tr>
</table>
</asp:WizardStep>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana">
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d">
Sign Up for Your New Account</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserName">
User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server" ControlToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User Name is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="PasswordLabel" runat="server" AssociatedControlID="Password">
Password:</asp:Label></td>
<td>
<asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat="server" ControlToValidate="Password"
ErrorMessage="Password is required." ToolTip="Password is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="ConfirmPasswordLabel" runat="server" AssociatedControlID="ConfirmPassword">
Confirm Password:</asp:Label></td>
<td>
<asp:TextBox ID="ConfirmPassword" runat="server" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="ConfirmPasswordRequired" runat="server" ControlToValidate="ConfirmPassword"
ErrorMessage="Confirm Password is required." ToolTip="Confirm Password is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Email">
E-mail:</asp:Label></td>
<td>
<asp:TextBox ID="Email" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="EmailRequired" runat="server" ControlToValidate="Email"
ErrorMessage="E-mail is required." ToolTip="E-mail is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="QuestionLabel" runat="server" AssociatedControlID="Question">
Security Question:</asp:Label></td>
<td>
<asp:TextBox ID="Question" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="QuestionRequired" runat="server" ControlToValidate="Question"
ErrorMessage="Security question is required." ToolTip="Security question is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="Answer">
Security Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="server" ControlToValidate="Answer"
ErrorMessage="Security answer is required." ToolTip="Security answer is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<asp:CompareValidator ID="PasswordCompare" runat="server" ControlToCompare="Password"
ControlToValidate="ConfirmPassword" Display="Dynamic" ErrorMessage="The Password and Confirmation Password must match."
ValidationGroup="CreateUserWizard1"></asp:CompareValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="ErrorMessage" runat="server" EnableViewState="False"></asp:Literal>
</td>
</tr>
</table>
<asp:CheckBox ID="SubscribeCheckBox" runat="server" Checked="True" Text="Send me a monthly newsletter." />
<br />
<asp:CheckBox ID="ShareInfoCheckBox" runat="server" Checked="True" Text="Share my information with partner sites." />
</ContentTemplate>
</asp:CreateUserWizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white; background-color: #5d7b9d; height: 18px;">
Complete</td>
</tr>
<tr>
<td>
Your account has been successfully created.<br />
<br />
<asp:Label ID="SubscribeLabel" runat="server" Text="You have elected to receive our monthly newsletter."></asp:Label><br />
<br />
<asp:Label ID="ShareInfoLabel" runat="server" Text="You have elected to share your information with partner sites."></asp:Label></td>
</tr>
<tr>
<td align="right" colspan="2">
&nbsp;<asp:Button ID="ContinueButton" runat="server" BackColor="#FFFBFF" BorderColor="#CCCCCC"
BorderStyle="Solid" BorderWidth="1px" CausesValidation="False" CommandName="Continue"
Font-Names="Verdana" ForeColor="#284775" Text="Continue" ValidationGroup="CreateUserWizard1" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:CompleteWizardStep>
</WizardSteps>
<SideBarStyle BackColor="#5D7B9D" BorderWidth="0px" Font-Size="0.9em" VerticalAlign="Top" />
<TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
<SideBarButtonStyle BorderWidth="0px" Font-Names="Verdana" ForeColor="White" />
<NavigationButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<HeaderStyle BackColor="#5D7B9D" BorderStyle="Solid" Font-Bold="True" Font-Size="0.9em"
ForeColor="White" HorizontalAlign="Center" />
<CreateUserButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<ContinueButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<StepStyle BorderWidth="0px" />
</asp:CreateUserWizard>
&nbsp;</div>
</form>
</body>
</html>