About Author

Shabir has 12 yrs of exp in I.T using Asp, Asp.NET, Vb6/.NET/C#, MOSS/WMI/html/DOM, Ajax, XML,xsl.SharePoint

Name:Shabir Hakim
Country: India
Gender: Male

Sharepoint Programming with the Object Model

Creating a Web Application in a SharePoint Web Site

This programming task describes how to create a Web application in Visual Studio .NET that operates within the context of Windows SharePoint Services. The example creates a tool for reporting a list of all the SharePoint Web sites to which a specified user belongs, as well as a list of that user's membership in the security groups for each Web site.

Note  For information about how to create a Web application that coexists with Windows SharePoint Services, see Modifying Configuration Settings for an Application to Coexist with Windows SharePoint Services.

  1. In Visual Studio .NET, create a new Web application and set a reference to Microsoft.SharePoint.dll. For information on how to perform these steps, see Getting Started with Customizing a Team Web Site in Visual Studio .NET.
  2. In Design View, use the Toolbox to add a label, a text box, and a button to WebForm1.aspx. To open the Toolbox, click Toolbox on the View menu.

    Note  To create a Web application that modifies data in the content database, you need to add a FormDigest control and a page directive to the .aspx file containing the form. For information on how to add this control, see Security Validation and Making Posts to Update Data.

  3. Double-click the button to open the code-behind file named WebForm1.aspx.cs.
  4. At the beginning of the file, add using directives (Imports statements in Visual Basic .NET) that reference the Microsoft.SharePoint , Microsoft.SharePoint.Utilities , and Microsoft.SharePoint.WebControls namespaces, as follows:
    [Visual Basic .NET]
    
    Imports Microsoft.SharePoint
    Imports Microsoft.SharePoint.WebControls
    Imports Microsoft.SharePoint.Utilities
    [C#]
    
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.SharePoint.Utilities;

    The Microsoft.SharePoint.WebControls namespace must be referenced in order to instantiate a site object that corresponds to the current site context. The Microsoft.SharePoint namespace must be referenced in order to return the specified user and the groups to which the user belongs. The Microsoft.SharePoint.Utilities namespace must be referenced in order to encode strings that are displayed in the example.

    After you instantiate the site object using SPSite mySite = SPControl.GetContextSite(Context) (in Visual Basic .NET, use Dim mySite As SPSite = SPControl.GetContextSite(Context)), you can use the AllWebs property of the SPSite class, the Users property of the SPWeb class, and the Roles property of the SPUser class within nested foreach statements in order to return a user object for the user name specified in the text box, as well as the list of site groups to which that user belongs.

    Note  The Context value that is passed in the GetContextSite method is inherited from System.Web.UI.Page.

     

  5. Within the Button1_Click handler that Visual Studio .NET creates on the code-behind page, add the following code block:
    [Visual Basic .NET]
             
    Dim userList As String = SPEncode.HtmlEncode(TextBox1.Text) & " is a user in the following webs:<BR>"
    Dim mySite As SPSite = SPControl.GetContextSite(Context)
    Dim allSites As SPWebCollection = mySite.AllWebs
    Dim subSite As SPWeb
    
    For Each subSite In  allSites
    
        Dim listGroups As String = ""
        Dim allUsers As SPUserCollection = subSite.Users
        Dim user As SPUser
    
        For Each user In  allUsers
    
            If user.LoginName = TextBox1.Text Then
    
                Dim allGroups As SPRoleCollection = user.Roles
                Dim group As SPRole
    
                For Each group In  allGroups
    
                    listGroups += SPEncode.HtmlEncode(group.Name) & "  "
    
                Next group
    
                userList += subSite.ServerRelativeUrl.ToString() & " :: " & listGroups & "<BR>"
            End If
    
        Next user
    
    Next subSite
    
    Label1.Text = userList 
    [C#]
    
    string userList = SPEncode.HtmlEncode(TextBox1.Text) + " is a user in the following webs:<BR>";
    
    SPSite mySite = SPControl.GetContextSite(Context);
    SPWebCollection allSites = mySite.AllWebs;
    
    foreach (SPWeb subSite in allSites)
    {
        string listGroups = "";
    
        SPUserCollection allUsers = subSite.Users;
    
        foreach (SPUser user in allUsers)
        {
    
            if (user.LoginName == TextBox1.Text)
            {
                SPRoleCollection allGroups = user.Roles;
    
                foreach (SPRole group in allGroups)
                {
                    listGroups += SPEncode.HtmlEncode(group.Name) + "  ";
                }
    
                userList += subSite.ServerRelativeUrl.ToString() + " -- " + listGroups + "<BR>";
            }
        }
    }
    
    Label1.Text =  userList;

    The code example iterates through all the users of all the subsites for the current top-level site, and if the value of the LoginName property for a given user matches the user name that is entered in the text box, then the names of all the user's site groups for the site are collected and displayed.

  6. On the Build menu, click Build Solution.

    The browser opens the page. When you type the logon name of a user on the site, the label displays the Web sites and site groups to which the specified user belongs.

  7. To run the application after creating it in Visual Studio .NET, navigate to http://Server_Name/[sites/][Site_Name/]_layouts/Web_Application_Name/webform1.aspx.

Creating a Console Application

This programming task describes how to create a console application in Microsoft Visual Studio .NET. The example displays the number of lists within a site collection.

Note  For users to run a console application in the context of Microsoft Windows SharePoint Services 2.0, they must be administrators on the computer where the script is executed.

  1. On the File menu in Visual Studio .NET, point to New and then click Project.
  2. In the New Project dialog box, select Visual Basic Projects or Visual C# Projects in the Project Types box, depending on which language you prefer.
  3. In the Templates box, select Console Application.
  4. In the Location box, type the path to where to create the application, and then click OK.
  5. In Solution Explorer, right-click the References node, and then click Add Reference on the shortcut menu.
  6. On the .NET tab of the Add Reference dialog box, select Windows SharePoint Services in the list of components, click Select, and then click OK.
  7. In the .vb or .cs file, add a using directive for the Microsoft.SharePoint namespace, as follows.
    [Visual Basic .NET]
    
    Imports Microsoft.SharePoint
    [C#]
    
    using Microsoft.SharePoint;
  8. Add the following code to the Main method in the .vb or .cs file.
    [Visual Basic .NET]
    
    Overloads Sub Main(args() As String)
    
        Dim siteCollection As New SPSite("http://Server_Name")
        Dim sites As SPWebCollection = siteCollection.AllWebs
        Dim site As SPWeb
    
        For Each site In  sites
    
            Dim lists As SPListCollection = site.Lists
    
            Console.WriteLine("Site: " + site.Name + "  Lists: " + lists.Count.ToString())
    
        Next site
    
        Console.WriteLine("Press ENTER to continue")
        Console.ReadLine()
    
    End Sub 'Main
    [C#]
    
    static void Main(string[] args)
    {
        SPSite siteCollection = new SPSite("http://Server_Name");
        SPWebCollection sites = siteCollection.AllWebs;
    
        foreach (SPWeb site in sites)
        {
            SPListCollection lists =  site.Lists;
    
            Console.WriteLine("Site: " + site.Name + "  Lists: " + lists.Count.ToString());
        }
    
        Console.WriteLine("Press ENTER to continue");
        Console.ReadLine();
    }
  9. Click Start on the Debug menu or press F5 to run the code.

Customizing a Web Part

You can create custom Web Parts to work with site or list data. This programming task shows how to create a simple Web Part that displays the titles and number of items for all lists that contain more than ten items on subsites in the current Web site.

  1. Create a Web Part as described in Creating a Basic Web Part. This example assumes that you have created a SimpleWebPart application.
  2. Open WebCustomControl1.cs or WebCustomControl1.vb for the SimpleWebPart application and add directives for the Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces, as follows:
    [Visual Basic .NET]
    
    Imports Microsoft.SharePoint
    Imports Microsoft.SharePoint.Utilities
    Imports Microsoft.SharePoint.WebControls
    [C#]
    
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Utilities;
    using Microsoft.SharePoint.WebControls;
  3. Remove the HtmlControl objects used in the example, including declarations for their variables, the _mybutton_click handler, and the CreateChildControls method.
  4. Replace the contents of the RenderWebPart method with the following code block.
    [Visual Basic .NET]
             
    Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
    
    output.Write(SPEncode.HtmlEncode(mySite.Title))
    
    Dim subSites As SPWebCollection = mySite.Webs
    Dim site As SPWeb
    
    For Each site In  subSites
    
        output.Write(SPEncode.HtmlEncode(site.Title) & "<BR>")
    
        Dim lists As SPListCollection = site.Lists
        Dim list As SPList
    
        For Each list In  lists
    
            If list.ItemCount > 10 Then
    
                output.Write(SPEncode.HtmlEncode(list.Title) & " :: " & list.ItemCount & "<BR>")
    
            End If
    
        Next list
    
    Next site 
    [C#]
    
    SPWeb mySite = SPControl.GetContextWeb(Context);
    
    output.Write(SPEncode.HtmlEncode(mySite.Title));
    
    SPWebCollection subSites = mySite.Webs;
    
    foreach(SPWeb site in subSites)
    {
    
       output.Write(SPEncode.HtmlEncode(site.Title) + "<BR>");
    
       SPListCollection lists=site.Lists;
    
       foreach(SPList list in lists)
       {
    
          if (list.ItemCount>10) 
          {
              output.Write(SPEncode.HtmlEncode(list.Title) + " : " + list.ItemCount + "<BR>");
          }
       }
    }

    The example first writes out the title of the current Web site. It then iterates through all the subsites to print out their titles, and then through all the lists in each subsite to print out the list title and number of items for cases where there are more than ten list items in a list.

  5. On the Build menu, click Build Solution.
  6. Increase the trust level in Windows SharePoint Services from minimal (default) to medium by opening the web.config file at Local_Drive:\Inetpub\wwwroot and replacing the following line:
    <trust level="WSS_Minimal" originUrl="" />
    with the following:
    <trust level="WSS_Medium" originUrl="" />
  7. Reset Microsoft Internet Information Services (IIS) for changes in trust level to take effect.

 

The Web Part can be imported through the user interface into a Web Part Page or into the home page for viewing the list data.

Returning Sites and Site Collections

You can return all the sites within a site collection, including the top-level site and all subsites, by using the AllWebs property of the SPSite class. The following example displays the titles of all the sites and lists in the current site collection.

[Visual Basic .NET]

Dim mySite As SPSite = SPControl.GetContextSite(Context)
Dim subSites As SPWebCollection = mySite.AllWebs
Dim i As Integer

For i = 0 To subSites.Count - 1

    Dim lists As SPListCollection = subSites(i).Lists
    Dim j As Integer

    For j = 0 To lists.Count - 1

        Response.Write(SPEncode.HtmlEncode(subSites(i).Title) & " :: " _
            & SPEncode.HtmlEncode(lists(j).Title) & "<BR>")

    Next j

Next i
[C#]

SPSite mySite = SPControl.GetContextSite(Context); 
SPWebCollection subSites = mySite.AllWebs;

for (int i=0;i<subSites.Count;i++)
{
    SPListCollection lists = subSites[i].Lists;

    for (int j=0;j<lists.Count;j++)
    {
        Response.Write(SPEncode.HtmlEncode(subSites[i].Title) + " :: " + 
            SPEncode.HtmlEncode(lists[j].Title) + "<BR>");
    }
}

The previous example requires using directives (Imports in Visual Basic) for the

Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces.

To return a list of all the first-tier subsites for a site, use the Webs property of the SPWeb class. The following example displays a list of subsite titles.

[Visual Basic .NET]

Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim sites As SPWebCollection = mySite.Webs
Dim subSite As SPWeb

For Each subSite In  sites

    Response.Write(SPEncode.HtmlEncode(subSite.Title) & "<BR>")

Next subSite
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPWebCollection sites = mySite.Webs;

foreach (SPWeb subSite in sites)
{
    Response.Write(SPEncode.HtmlEncode(subSite.Title) + "<BR>");
}

The previous example requires using directives (Imports in Visual Basic) for

the Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces.

Instead of using a foreach statement, the following example uses nested for statements to display a list of subsite URLs and list titles.

[Visual Basic .NET]

Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim sites As SPWebCollection = mySite.Webs
Dim i As Integer

For i = 0 To sites.Count - 1

    Dim lists As SPListCollection = sites(i).Lists
    Dim j As Integer

    For j = 0 To lists.Count - 1

        Response.Write(sites(i).Url & " :: " & SPEncode.HtmlEncode(lists(j).Title) & "<BR>")

    Next j

Next i 
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPWebCollection sites = mySite.Webs;

for (int i=0;i<sites.Count;i++)
{
    SPListCollection lists = sites[i].Lists;

    for (int j=0;j<lists.Count;j++)
    {
        Response.Write(sites[i].Url + " :: " + SPEncode.HtmlEncode(lists[j].Title) + "<BR>");
    }
}

The previous example requires using directives (Imports in Visual Basic) for the

Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces.

The next example displays all the subsites and lists for the current site, as well as the number of items in each list. The example uses nested foreach statements to iterate through the collections of Web sites and lists.

[Visual Basic .NET]

Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim sites As SPWebCollection = mySite.Webs
Dim subSite As SPWeb

For Each subSite In  sites

    Response.Write("<B>" & SPEncode.HtmlEncode(subSite.Title) & "</B>" & "<BR>")

    Dim lists As SPListCollection = subSite.Lists
    Dim list As SPList

    For Each list In  lists

        Response.Write(SPEncode.HtmlEncode(list.Title) & " :: " & list.ItemCount & "<BR>")

    Next list

Next subSite 
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPWebCollection sites = mySite.Webs;

foreach (SPWeb subSite in sites)
{
    Response.Write("<B>" + SPEncode.HtmlEncode(subSite.Title) + "</B>" + "<BR>");

    SPListCollection lists = subSite.Lists;

    foreach (SPList list in lists)
    {

        Response.Write(SPEncode.HtmlEncode(list.Title) + " :: " + list.ItemCount + "<BR>");
    }
}

The previous example requires using directives (Imports in Visual Basic) for the

Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces.

To return the collection of site collections on a virtual server, use the Sites property of the SPVirtualServer class. Instantiate an SPGlobalAdmin object and use the OpenVirtualServer method to return a specific virtual server. The following example displays the URLs of all the site collections on a specified virtual server.

[Visual Basic .NET]

Dim globalAdmin As New SPGlobalAdmin()

Dim uri As New System.Uri("http://Server_Name")
Dim virtualServer As SPVirtualServer = globalAdmin.OpenVirtualServer(uri)
Dim siteCollections As SPSiteCollection = virtualServer.Sites
Dim siteCollection As SPSite

For Each siteCollection In  siteCollections

    Response.Write(siteCollection.Url + "<BR>")

Next siteCollection
[C#]

SPGlobalAdmin globalAdmin = new SPGlobalAdmin();

System.Uri uri = new System.Uri("http://Server_Name");
SPVirtualServer virtualServer = globalAdmin.OpenVirtualServer(uri);
SPSiteCollection siteCollections = virtualServer.Sites;

foreach (SPSite siteCollection in siteCollections)
{
    Response.Write(siteCollection.Url + "<BR>");
}

The previous example requires using directives (Imports in Visual Basic) for both the

Microsoft.SharePoint.Administration and Microsoft.SharePoint.Utilities namespaces.

The example assumes the existence of a .aspx page that contains a label control.

Creating or Deleting a Site or a Site Collection

To create a site, use one of the Add methods of the SPWebCollection class. To create a subsite beneath a site, use the Webs property of the SPWeb class to return the collection of subsites and call one of the Add methods for the collection.

The following example creates a new subsite based on the template of the current site and on information gathered from three text boxes. The text boxes specify the name to use in the new URL, the title to use for the site, and a description for the site.

[Visual Basic .NET]
         
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim subSites As SPWebCollection = mySite.Webs
Dim currentTemplate As String = mySite.WebTemplate

Dim siteUrl As String = TextBox1.Text.ToString()
Dim siteTitle As String = TextBox2.Text.ToString()
Dim siteDescription As String = TextBox3.Text.ToString()

subSites.Add(siteUrl, siteTitle, siteDescription, Convert.ToUInt32(1033), currentTemplate, True, False)
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPWebCollection subSites = mySite.Webs;
string currentTemplate = mySite.WebTemplate;

string siteUrl = TextBox1.Text.ToString();
string siteTitle = TextBox2.Text.ToString();
string siteDescription = TextBox3.Text.ToString();

subSites.Add(siteUrl, siteTitle, siteDescription, 1033, currentTemplate, true, false);

In the example, the WebTemplate property of the SPWeb class returns the name of the current site definition, which is passed as a parameter of the Add method. In addition, three parameters for this method pass the information gathered from the three text boxes, and three other parameters specify the locale folder, true to create a site with unique permissions, and false to convert any existing Web site at the same location to a SharePoint site.

To delete a site, use the Delete method of the SPWeb class or the Delete method of the SPWebCollection class.

The following example assumes the use of a text box to specify the URL of a site to delete and uses the Delete method of the SPWebCollection class to delete the site.

[Visual Basic .NET]
         
Dim deleteSite As String = TextBox1.Text.ToString()

Dim mySite As SPSite = SPControl.GetContextSite(Context)
Dim sites As SPWebCollection = mySite.AllWebs

sites.Delete(deleteSite)
[C#]

string deleteSite = TextBox1.Text.ToString();

SPSite mySite = SPControl.GetContextSite(Context);
SPWebCollection sites = mySite.AllWebs;

sites.Delete(deleteSite);

In the example, the AllWebs property of the SPSite class returns the collection of all sites within the current site collection.

To create a site collection, use the Sites property of the SPVirtualServer class to return the collection of site collections on the virtual server and use one of the Add methods of the SPSiteCollection class.

The following example creates a site collection within the collection of site collections for a specified virtual server.

[Visual Basic .NET]
         
Dim globAdmin As New SPGlobalAdmin()

Dim uri As New System.Uri("http://Server_Name")
Dim virtualServer As SPVirtualServer = globAdmin.OpenVirtualServer(uri)
Dim siteCollections As SPSiteCollection = virtualServer.Sites

siteCollections.Add("http://Server_Name/sites/Site_Collection_Name", "User_Name", "User_Email")
[C#]

SPGlobalAdmin globAdmin = new SPGlobalAdmin();

System.Uri uri = new System.Uri("http://Server_Name");
SPVirtualServer virtualServer = globAdmin.OpenVirtualServer(uri);
SPSiteCollection siteCollections = virtualServer.Sites;

siteCollections.Add("http://Server_Name/sites/Site_Collection_Name","User_Name","User_Email");

The example instantiates the SPGlobalAdmin class in order to call the OpenVirtualServer method and return the virtual server with the specified URI.

To delete a site collection from a virtual server requires security validation that uses the AdminFormDigest property of the SPGlobalAdmin class to insert a message digest on the page in the browser. This can be done by registering the digest as a hidden field through the RegisterHiddenField method of the System.Web.UI.Page class. In addition, use the RequestFromAdminPort field of the SPGlobalAdmin class to specify that the context of the request is through the administrative port.

The following example uses the Page_Load event to include an administrative form digest on the page and to establish the context of the request.

[Visual Basic .NET]
      
Private globalAdmin As New SPGlobalAdmin()

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

    Context.Items(SPGlobalAdmin.RequestFromAdminPort) = True
    Page.RegisterHiddenField("__REQUESTDIGEST", globalAdmin.AdminFormDigest)

End Sub 'Page_Load

Private Sub Button1_Click(sender As Object, e As System.EventArgs)

    Dim globalAdmin As New SPGlobalAdmin()
    Dim uri As New System.Uri("http://Server_Name")
    Dim vServer As SPVirtualServer = globalAdmin.OpenVirtualServer(uri)
    Dim siteCollections As SPSiteCollection = vServer.Sites

    siteCollections.Delete("sites/Site_Collection")

End Sub 'Button1_Click
[C#]

private SPGlobalAdmin globalAdmin = new SPGlobalAdmin();

private void Page_Load(object sender, System.EventArgs e)
{
    Context.Items[SPGlobalAdmin.RequestFromAdminPort] = true;
    Page.RegisterHiddenField("__REQUESTDIGEST", globalAdmin.AdminFormDigest);
}

private void Button1_Click(object sender, System.EventArgs e)
{
    SPGlobalAdmin globalAdmin = new SPGlobalAdmin();
    System.Uri uri = new System.Uri("http://Server_Name");
    SPVirtualServer vServer = globalAdmin.OpenVirtualServer(uri);
    SPSiteCollection siteCollections = vServer.Sites;

    siteCollections.Delete("sites/Site_Collection");
}

Creating or Deleting Lists

To create a new list, use the one of the Add methods of the SPListCollection class.

The following example adds a new Generic, Events, or Announcements list based on user input. A Switch clause is used to determine the type of list that the user specifies and sets the type of list template accordingly.

[Visual Basic .NET]
         
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim lists As SPListCollection = mySite.Lists

Dim listTitle As String = TextBox1.Text
Dim listDescription As String = TextBox2.Text
Dim listType As String = ListBox1.SelectedItem.Text

Dim listTemplateType As New SPListTemplateType()

Select Case listType

    Case "Generic List"

        listTemplateType = SPListTemplateType.GenericList
        Exit 

    Case "Events"

        listTemplateType = SPListTemplateType.Events
        Exit

    Case "Announcements"

        listTemplateType = SPListTemplateType.Announcements
        Exit 

End Select

lists.Add(listTitle, listDescription, listTemplateType)
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPListCollection lists = mySite.Lists;

string listTitle = TextBox1.Text;
string listDescription = TextBox2.Text;
string listType = ListBox1.SelectedItem.Text;

SPListTemplateType listTemplateType = new SPListTemplateType();

switch(listType)
{
    case "Generic List":
    {
        listTemplateType = SPListTemplateType.GenericList;
        break;
    }

    case "Events":
    {
        listTemplateType = SPListTemplateType.Events;
        break;
    }

    case "Announcements":
    {
        listTemplateType = SPListTemplateType.Announcements;
        break;
    }
}

lists.Add(listTitle, listDescription, listTemplateType);

The previous example instantiates an SPListTemplateType object in order to contain the type of list template specified by the user. This object must be passed as a parameter in the Add method. The example assumes the existence of two text boxes where the user can type a title and a description, as well as a drop-down list box that displays the list types for the user to select from.

In addition to using the SPListTemplateType enumeration to create a list, you can also create a list from an SPListTemplate object. The ListTemplates property of the SPWeb class can be used to return a collection of list template objects and a name indexer can be used to specify the list template to use, as in the following example, which assumes the existence of a Decision Meetings Workspace site:

[Visual Basic .NET]


Dim mySite As SPWeb = SPControl.GetContextWeb(Context)

Dim template As SPListTemplate = mySite.ListTemplates("Decisions")
mySite.Lists.Add("My Decisions", "This is a list of decisions", template)
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);

SPListTemplate template = mySite.ListTemplates["Decisions"];
mySite.Lists.Add("My Decisions", "This is a list of decisions", template);

Using the GetCustomListTemplates method of the SPSite class, the next example returns the custom list templates for a specified site and creates a new list based on a specified list template:

[Visual Basic .NET]

Dim siteCollection As SPSite = SPControl.GetContextSite(Context)
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)

Dim listTemplates As SPListTemplateCollection = siteCollection.GetCustomListTemplates(mySite)
Dim listTemplate As SPListTemplate = listTemplates("Custom List Template")
mySite.Lists.Add("Custom List", "A list created from a custom list template in the list template catalog", listTemplate)
[C#]

SPSite siteCollection = SPControl.GetContextSite(Context);
SPWeb mySite = SPControl.GetContextWeb(Context);

SPListTemplateCollection listTemplates = siteCollection.GetCustomListTemplates(mySite);
SPListTemplate listTemplate = listTemplates["Custom List Template"];
mySite.Lists.Add("Custom List", "A list created from a custom list template in the list template catalog", listTemplate);

To delete a list, you must specify the GUID of the list as the parameter for the Delete method. Use the ID property of the SPList class to find the GUID.

[Visual Basic .NET]
         
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim lists As SPListCollection = mySite.Lists

Dim list As SPList = lists(TextBox1.Text)
Dim listGuid As System.Guid = list.ID

lists.Delete(listGuid) 
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPListCollection lists = mySite.Lists;

SPList list = lists[TextBox1.Text];
System.Guid listGuid = list.ID;

lists.Delete(listGuid);

This example assumes the existence of a text box where the user specifies the name of the list.

Adding or Deleting a List in Multiple Web Sites

You can use one of the Add methods of the SPListCollection class to add a list to multiple Web sites across a site collection. The following example creates a generic list on every Web site, based on the title and description that is passed to the code from two text boxes. The AllWebs property of the SPSite class is used to return the collection of all Web sites that exist on the site.

This example assumes the existence of two text boxes on the .aspx page containing a form.

[Visual Basic .NET]
         
Dim listTitle As String = TextBox1.Text.ToString()
Dim listDescription As String = TextBox2.Text.ToString()

Dim mySite As SPSite = SPControl.GetContextSite(Context)
Dim allWebs As SPWebCollection = mySite.AllWebs
Dim web As SPWeb

For Each web In  allWebs

    Dim allLists As SPListCollection = web.Lists

    allLists.Add(listTitle, listDescription, SPListTemplateType.GenericList)

Next web
[C#]

string listTitle = TextBox1.Text.ToString();
string listDescription = TextBox2.Text.ToString();

SPSite mySite = SPControl.GetContextSite(Context);
SPWebCollection allWebs = mySite.AllWebs;

foreach (SPWeb web in allWebs)
{
    SPListCollection allLists = web.Lists;
    allLists.Add(listTitle,listDescription, SPListTemplateType.GenericList);
}

If you want to delete a list from every Web site in which it appears, use the Delete method of the SPListCollection class. The following example uses nested loops to drill down to a list that has a title matching the title specified in a text box.

This example assumes the existence of a text box on the .aspx page containing a form.

[Visual Basic .NET]
         
Dim mySite As SPSite = SPControl.GetContextSite(Context)
Dim allWebs As SPWebCollection = mySite.AllWebs
Dim web As SPWeb

For Each web In  allWebs

    Dim allLists As SPListCollection = web.Lists
    Dim i As Integer

    For i = 0 To allLists.Count - 1

        Dim list As SPList = allLists(i)

        If list.Title = TextBox1.Text Then

            Dim listGuid As Guid = list.ID

            allLists.Delete(listGuid)

        End If

    Next i

Next web 
[C#]

SPSite mySite = SPControl.GetContextSite(Context);
SPWebCollection allWebs = mySite.AllWebs;

foreach (SPWeb web in allWebs)
{
    SPListCollection allLists = web.Lists;

    for (int i=0; i<allLists.Count; i++)
    {
        SPList list = allLists[i];

        if (list.Title == TextBox1.Text)
        {
            Guid listGuid = list.ID;
            allLists.Delete(listGuid);
        }
    }
}

The Title property of the SPList class is used to identify a list in the collection of lists for each Web site that matches the specified title. The ID property returns the globally unique identifier (GUID) of the list, which is passed as the parameter for the Delete method.

Returning Items from a List

To return items from a list, you can instantiate an SPWeb object and drill down through the object model to the SPListItemCollection object for the list. Once you return the collection of all items for a list, you can iterate through the collection and use indexers to return specific field values.

The following example returns all the items for a specified events list. It assumes the existence of a text box for typing the name of an events list.

[Visual Basic .NET]
         
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim listItems As SPListItemCollection = mySite.Lists(TextBox1.Text).Items
Dim i As Integer

For i = 0 To listItems.Count - 1

    Dim item As SPListItem = listItems(i)

    Response.Write(SPEncode.HtmlEncode(item("Title").ToString()) & " :: " _
        & SPEncode.HtmlEncode(item("Location").ToString()) & " :: " _
        & SPEncode.HtmlEncode(item("Begin").ToString()) & " :: " _
        & SPEncode.HtmlEncode(item("End").ToString()) & "<BR>")

Next i
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPListItemCollection listItems = mySite.Lists[TextBox1.Text].Items;

for (int i=0;i<listItems.Count;i++)
{
    SPListItem item = listItems[i];

    Response.Write(SPEncode.HtmlEncode(item["Title"].ToString()) + " : " +
        SPEncode.HtmlEncode(item["Location"].ToString()) + " : " +
        SPEncode.HtmlEncode(item["Begin"].ToString()) + " : " +
        SPEncode.HtmlEncode(item["End"].ToString()) + "<BR>");
}

The previous example requires using directives (Imports in Visual Basic) for the Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces.

In the example, indexers are used both to return the list typed by the user and to return specific items from the list. To return the items, the indexers specify the name of each column whose value is returned. In this case all the field names pertain to a common Events list.

You can also use one of the GetItems methods of the SPList class to return a subset of items from a list. The following example returns only Title column values where the Stock column value surpasses 100.

[Visual Basic .NET]

Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim list As SPList = mySite.Lists("Books")

Dim query As New SPQuery()
query.Query = "<Where><Gt><FieldRef Name='Stock'/><Value Type='Number'>100</Value></Gt></Where>"

Dim myItems As SPListItemCollection = list.GetItems(query)
Dim item As SPListItem

For Each item In  myItems

    Response.Write(SPEncode.HtmlEncode(item("Title").ToString()) & "<BR>")

Next item
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPList list = mySite.Lists["Books"];

SPQuery query = new SPQuery();
query.Query = "<Where><Gt><FieldRef Name='Stock'/><Value Type='Number'>100</Value></Gt></Where>";

SPListItemCollection myItems = list.GetItems(query);

foreach (SPListItem item in myItems)
{
    Response.Write(SPEncode.HtmlEncode(item["Title"].ToString()) + "<BR>");
}

The previous example uses a constructor to instantiate an SPQuery object, and then assigns to the Query property of the query object a string in Collaborative Application Markup Language (CAML) that specifies the inner XML for the query (in other words, the Where element). Once the Query property is set, the query object is passed through the GetItems method to return and display items.

The previous example requires using directives (Imports in Visual Basic) for the Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces.

The example assumes the existence of a Books list that has a Stock column containing number values.

Adding or Deleting List Items

To add items to a list, use the Add method of the SPListItemCollection class to create an item object, and then use the Update method of the SPListItem class to update the database with the new item.

The following example assumes the existence of five text boxes, one that specifies the name of the list to add to, and four others that are used to specify the values to add. Indexers are used to gather the input from all five sources.

[Visual Basic .NET]
         
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim listItems As SPListItemCollection = mySite.Lists(TextBox1.Text).Items

Dim item As SPListItem = listItems.Add()

item("Title") = TextBox2.Text
item("Stock") = Convert.ToInt32(TextBox3.Text)
item("Return Date") = Convert.ToDateTime(TextBox4.Text)
item("Employee") = TextBox5.Text

item.Update()
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);

SPListItemCollection listItems = mySite.Lists[TextBox1.Text].Items;

SPListItem item = listItems.Add();

item["Title"] = TextBox2.Text;
item["Stock"] = Convert.ToInt32(TextBox3.Text);	
item["Return Date"] = Convert.ToDateTime(TextBox4.Text);
item["Employee"] = TextBox5.Text;

item.Update();
}

The example first creates an SPListItem object through the Add method of the collection. It then assign values to specific fields by using an indexer on the list item. For example, item["Title"] specifies the Title column value for the item. Finally, the example calls the Update method of the list item to effect changes in the database.

To create list items with preserved metadata, you can use the Author, Editor, Created, and Modified fields as indexers, where Author or Editor specify a Windows SharePoint Services user ID. For an example, see the SPListItem class.

To delete items from a list, use the Delete method of the SPListItemCollection class, which takes as its parameter an index into the collection.

[Visual Basic .NET]
         
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim listItems As SPListItemCollection = mySite.Lists(TextBox1.Text).Items
Dim itemCount As Integer = listItems.Count
Dim k As Integer

For k = 0 To itemCount - 1

    Dim item As SPListItem = listItems(k)

    If TextBox2.Text = item("Employee").ToString() Then

        listItems.Delete(k)

    End If

Next k 
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);

SPListItemCollection listItems = mySite.Lists[TextBox1.Text].Items;

int itemCount = listItems.Count;

for (int k=0; k<itemCount; k++)
{
    SPListItem item = listItems[k];

    if (TextBox2.Text==item["Employee"].ToString())
    {
        listItems.Delete(k);
    }
}

Based on input from two text boxes, this example iterates through the collection of items for the specified list and deletes an item if the Employee field value matches the specified value.

Adding a Recurring Event to Lists on Multiple Sites

This programming task shows how to add a recurring event with a Meeting Workspace site to the Events list of every site in a collection of subsites.

 

  1. Create a console application in Microsoft Visual Studio .NET, as described in Creating a Console Application.
  2. Add a using or Imports directive to the opening of the .cs or .vb file for the Microsoft.SharePoint and Microsoft.SharePoint.Meetings namespaces, as follows:
    [Visual Basic .NET]
    
    Imports Microsoft.SharePoint
    Imports Microsoft.SharePoint.Meetings
    [C#]
    
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Meetings;
  3. Use the SPSite constructor to instantiate a specified site collection. This example uses an indexer on the AllWebs property of the SPSite class to return a specific site, and the Webs property of the SPWeb class to return the collection of subsites beneath the site. Set up a foreach loop to iterate through all the subsites and obtain the Events list for each site and the collection of list items in each Events list, as follows:
    [Visual Basic .NET]
    
    Dim evtTitle As String = Console.ReadLine()
    
    Dim siteCollection As New SPSite("Absolute_Url")
    Dim site As SPWeb = siteCollection.AllWebs("Site_Name")
    Dim subSites As SPWebCollection = site.Webs
    Dim subSite As SPWeb
    
    For Each subSite In subSites
    
        Dim list As SPList = subSite.Lists("Events")
        Dim listItems As SPListItemCollection = list.Items
    [C#]
    
    string evtTitle = Console.ReadLine();
    
    SPSite siteCollection = new SPSite("Absolute_Url");
    SPWeb site = siteCollection.AllWebs["Site_Name"];
    SPWebCollection subSites = site.Webs;
    
    foreach (SPWeb subSite in subSites)
    {
        SPList list = subSite.Lists["Events"];
        SPListItemCollection listItems = list.Items;
  4. To create a list item, the example uses the Add method of the SPListItemCollection class to create an unitialized list item, uses indexers to set various properties for the new item, and then uses the Update method to finish creating the item.
    [Visual Basic .NET]
    
    Dim recEvent As SPListItem = listItems.Add()
    
    Dim recdata As String = "<recurrence><rule><firstDayOfWeek>su</firstDayOfWeek>" _ 
        & "<repeat><daily dayFrequency='1' /></repeat>" _ 
        & "<repeatInstances>5</repeatInstances></rule></recurrence>"
    
    recEvent("Title") = evtTitle
    recEvent("RecurrenceData") = recdata
    recEvent("EventType") = 1
    recEvent("EventDate") = New DateTime(2003, 8, 15, 8, 0, 0)
    recEvent("EndDate") = New DateTime(2003, 9, 25, 9, 0, 0)
    recEvent("UID") = Guid.NewGuid()
    recEvent("TimeZone") = 13
    recEvent("Recurrence") = - 1
    recEvent("XMLTZone") = "<timeZoneRule><standardBias>480</standardBias>" _
        & "<additionalDaylightBias>-60</additionalDaylightBias>" _
        & "<standardDate><transitionRule  month='10' day='su' weekdayOfMonth='last' />" _
        & "<transitionTime>2:0:0</transitionTime></standardDate>" _
        & "<daylightDate><transitionRule  month='4' day='su' weekdayOfMonth='first' />" _
        & "<transitionTime>2:0:0</transitionTime></daylightDate></timeZoneRule>"
    
    recEvent.Update()
    [C#]
    
        SPListItem recEvent = listItems.Add();
    
        string recData = "<recurrence><rule><firstDayOfWeek>su</firstDayOfWeek>" +
            "<repeat><daily dayFrequency='1' /></repeat>" +
            "<repeatInstances>5</repeatInstances></rule></recurrence>";
    
        recEvent["Title"] = evtTitle;
        recEvent["RecurrenceData"] = recData;
        recEvent["EventType"] = 1;
        recEvent["EventDate"] = new DateTime(2003,8,15,8,0,0);
        recEvent["EndDate"] = new DateTime(2003,9,25,9,0,0);
        recEvent["UID"] = System.Guid.NewGuid();
        recEvent["TimeZone"] = 13;
        recEvent["Recurrence"] = -1;
        recEvent["XMLTZone"] = "<timeZoneRule><standardBias>480</standardBias>" +
            "<additionalDaylightBias>-60</additionalDaylightBias>" +
            "<standardDate><transitionRule  month='10' day='su' weekdayOfMonth='last' />" +
            "<transitionTime>2:0:0</transitionTime></standardDate>" +
            "<daylightDate><transitionRule  month='4' day='su' weekdayOfMonth='first' />" +
            "<transitionTime>2:0:0</transitionTime></daylightDate></timeZoneRule>";
    
        recEvent.Update();

    The recData variable contains an XML fragment that specifies properties for a recurring event taking place daily for five days, and the XMLTZone indexer is used to assign time zone information for the current site. The XML that defines the recurrence and that specifies the time zone information is contained in the ntext3 and ntext4 columns of the UserData table in the content database.

    The following table shows examples of the different kinds of recurrence that can be used.

    Description Example
    Every other day until a specified end date
    <recurrence><rule>
       <firstDayOfWeek>su</firstDayOfWeek>
       <repeat><daily dayFrequency='2' /></repeat>
       <windowEnd>2003-09-20T09:00:00Z</windowEnd>
    </rule></recurrence>
    Weekly on Monday
    <recurrence><rule>
       <firstDayOfWeek>su</firstDayOfWeek>
       <repeat><weekly mo='TRUE' weekFrequency='1' /></repeat>
       <repeatForever>FALSE</repeatForever>
    </rule></recurrence>
    Every two months on the third day for five sessions
    <recurrence><rule>
       <firstDayOfWeek>su</firstDayOfWeek>
       <repeat><monthly monthFrequency='2' day='3' /></repeat>
       <repeatInstances>5</repeatInstances>
    </rule></recurrence>
    Monthly on the first Tuesday until a specified end date
    <recurrence><rule>
       <firstDayOfWeek>su</firstDayOfWeek>
       <repeat>
          <monthlyByDay tu='TRUE' weekdayOfMonth='first' monthFrequency='1' />
       </repeat>
       <windowEnd>2003-08-02T10:00:00Z</windowEnd>
    </rule></recurrence>
    Yearly on the twentieth day of the ninth month until a specified end date
    <recurrence><rule>
       <firstDayOfWeek>su</firstDayOfWeek>
       <repeat><yearly yearFrequency='1' month='9' day='20' /></repeat>
       <windowEnd>2007-09-20T07:00:00Z</windowEnd>
    </rule></recurrence>
  5. To add a Meeting Workspace site to the recurring event, use one of the Add methods of the SPWebCollection class and the LinkWithEvent method of the SPMeeting class.
    [Visual Basic .NET]
    
        Dim mwsSites As SPWebCollection = subSite.Webs
    
        Dim path As String = recEvent("Title").ToString()
    
        Dim newSite As SPWeb = mwsSites.Add(path, "Workspace_Name", _
            "Description", Convert.ToUInt32(1033), "MPS#0", False, False)
    
        Dim mwsSite As SPMeeting = SPMeeting.GetMeetingInformation(newSite)
    
        Dim guid As String = list.ID.ToString()
        Dim id As Integer = recEvent.ID
    
        Try
    
            mwsSite.LinkWithEvent(subSite, guid, id, "WorkspaceLink", "Workspace")
    
        Catch ex As System.Exception
    
            Console.WriteLine(ex.Message)
    
        End Try
    
    Next subSite
    [C#]
    
        SPWebCollection mwsSites = subSite.Webs;
    
        string path = recEvent["Title"].ToString();
    
        SPWeb newSite = mwsSites.Add(path, "Workspace_Name", "Description", 1033, "MPS#0", false, false);
    
        SPMeeting mwsSite = SPMeeting.GetMeetingInformation(newSite);
    
        string guid = list.ID.ToString();
        int id = recEvent.ID;
    
        try
        {
            mwsSite.LinkWithEvent(subSite, guid, id, "WorkspaceLink", "Workspace");
        }
    
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    After the Meeting Workspace site is created, the GetMeetingInformation method is used to return an SPMeeting object representing the site.

  6. Press F5 to start the Console Application, at the command prompt type a name for the Meeting Workspace site, and then press ENTER to add a recurring event with a Meeting Workspace site to the Events list in all the subsites beneath a site.

Accessing, Copying, and Moving Files

You can use the GetFolder method of the SPWeb class to return a specified folder and then access individual files in the folder. After instantiating an SPWeb object (for example, as mySite), use SPFolder myFolder = mySite.GetFolder("Shared Documents") (in Visual Basic .NET, use Dim myFolder As SPFolder = mySite.GetFolder("Shared Documents")) to return the Shared Documents folder for the site. The following example returns the collection of files in the folder and displays information about the files.

[Visual Basic .NET]
         
Dim myFiles As SPFileCollection = myFolder.Files
Dim file As SPFile

For Each file In  myFiles

    Response.Write(file.Url.ToString() & "<BR>")
    Response.Write(file.Length.ToString() & "<BR>")

Next file 
[C#]

SPFileCollection myFiles = myFolder.Files;

foreach (SPFile file in myFiles)
{
   Response.Write(file.Url.ToString() + "<BR>");
   Response.Write(file.Length.ToString() + "<BR>");
}

The previous example lists the URL and size of every file within the folder.

The example requires using directives (Imports in Visual Basic) for the Microsoft.SharePoint namespace.

To copy files from one location to another, use one of the CopyTo methods of the SPFile class. In the following example, the Page_Load event handler instantiates an SPWeb object for the current site context. The Click event handler iterates through all the files in the folder, listing the name and size (in kilobytes) of each file that surpasses a multiple of the value specified by the user in a text box, before copying the file to a specified folder named Archive.

[Visual Basic .NET]
      
Private mySite As SPWeb

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

    mySite = SPControl.GetContextWeb(Context)

End Sub 'Page_Load

Private Sub Button1_Click(sender As Object, e As System.EventArgs)

    Dim maxSize As Integer = Convert.ToInt32(TextBox1.Text)
    Dim myFolder As SPFolder = mySite.GetFolder("Shared Documents")
    Dim myFiles As SPFileCollection = myFolder.Files
    Dim file As SPFile

    For Each file In  myFiles

        If file.Length > maxSize * 1024 Then

            Response.Write(SPEncode.HtmlEncode(file.Name) & " :: " & file.Length / 1024 & "kb<BR>")
            file.CopyTo("Archive/" & file.Name, True)

        End If

    Next file

End Sub 'Button1_Click
[C#]

private SPWeb mySite;

private void Page_Load(object sender, System.EventArgs e)
{
   mySite = SPControl.GetContextWeb(Context);
}

private void Button1_Click(object sender, System.EventArgs e)
{
   int maxSize = Convert.ToInt32(TextBox1.Text);

   SPFolder myFolder = mySite.GetFolder("Shared Documents");
   SPFileCollection myFiles = myFolder.Files;

   foreach (SPFile file in myFiles)
   {

      if (file.Length>(maxSize*1024))
      {
         Response.Write(SPEncode.HtmlEncode(file.Name) + ": " + file.Length/1024 + "kb<BR>");
         file.CopyTo("Archive/" + file.Name, true);
      }
   }
}

In the example, the CopyTo method uses two parameters, one that specifies the destination URL for the copied file, and the other a Boolean value that specifies whether to overwrite any file of the same name that is located at the destination.

The previous example requires using directives (Imports in Visual Basic) for the Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces.

The following example moves all files from the Shared Documents list of the current site to another folder named StorageFolder, overwriting any file of the same name that may be located there.

[Visual Basic .NET]
      
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim myFolder As SPFolder = mySite.GetFolder("Shared Documents")
Dim myFiles As SPFileCollection = myFolder.Files
Dim i As Integer

For i = myFiles.Count - 1 To 0 Step -1

    myFiles(i).MoveTo("StorageFolder/" & myFiles(i).Name, True)

Next i
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);
SPFolder myFolder = mySite.GetFolder("Shared Documents");
SPFileCollection myFiles = myFolder.Files;

for (int i = myFiles.Count - 1; i > -1; i--)
{
    myFiles[i].MoveTo("StorageFolder/" + myFiles[i].Name, true);
}

As the example illustrates, when collections are modified in the course of code execution by deleting or moving items, the counter for iterating through the collection must decrease in value with each iteration.

The previous example requires using directives (Imports in Visual Basic) for the Microsoft.SharePoint and Microsoft.SharePoint.WebControls namespaces.

Uploading a File to a SharePoint Site from a Local Folder

This programming task shows how to upload a file to a folder on a SharePoint site from a local folder. The task uses the EnsureParentFolder method to ensure that the destination folder exists.

  1. Create a Web application in Visual Studio .NET as described in Creating a Web Application on a SharePoint Site, adding a FormDigest control and a page directive for the Microsoft.SharePoint.WebControls namespace to the .aspx file, as follows:
    <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" 
       Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, 
       PublicKeyToken=71e9bce111e9429c" %>

    Note  You can obtain the PublicKeyToken value for the current Windows SharePoint Services deployment from the default.aspx file in the Local_Drive:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\TEMPLATE\(1033 in English)\STS folder, or from information provided for the Microsoft.SharePoint assembly at Local_Drive:\WINDOWS|WINNT\assembly in Windows Explorer.

  2. Add an HtmlInputFile control, a text box, and a button to the form on the .aspx page:
    <form id="Form1" method="post" runat="server">
       <SharePoint:FormDigest runat="server" />
       <input id="File1" type="file" runat="server" title="upldFileBox">
       <asp:Button id="Button1" runat="server" Text="Upload File"></asp:Button>
       <asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
    </form>
  3. In the .aspx.cs code-behind file, add using directives for the System.IO and Microsoft.SharePoint namespaces, as follows:
    [Visual Basic .NET]
    
    Imports System.IO
    Imports Microsoft.SharePoint
    [C#]
    
    using System.IO;
    using Microsoft.SharePoint;
  4. Add the following code to the Click event for the button:
    [Visual Basic .NET]
    
    If File1.PostedFile Is Nothing Then
    
        Return
    
    End If 
    
    Dim destUrl As String = TextBox1.Text
    
    Dim site As SPWeb = New SPSite(destUrl).OpenWeb()
    
    Dim fStream As Stream = File1.PostedFile.InputStream
    Dim contents(fStream.Length) As Byte
    
    fStream.Read(contents, 0, CInt(fStream.Length))
    fStream.Close()
    
    EnsureParentFolder(site, destUrl)
    
    site.Files.Add(destUrl, contents)
    [C#]
    
    if (File1.PostedFile == null)
        return;
    
    string destUrl = TextBox1.Text;
    
    SPWeb site = new SPSite(destUrl).OpenWeb();
    
    Stream fStream = File1.PostedFile.InputStream;
    byte[] contents = new byte[fStream.Length];
    
    fStream.Read(contents, 0, (int)fStream.Length);
    fStream.Close(); 
    
    EnsureParentFolder(site, destUrl);
    
    site.Files.Add(destUrl, contents);

    The value typed in the text box for the destination must be an absolute URL, including the file name, which is assigned to the destUrl parameter.

    In addition to instantiating an SPWeb object for the parent site, the combined use of the SPSite constructor and OpenWeb method validates the URL and throws an argument exception if the URL is not served by the current Windows SharePoint Services deployment. A System.Web.UI.HtmlControls.HtmlInputFile object is used to read the source file into a byte array for use with the Add method of the SPFileCollection class.

  5. The EnsureParentFolder method ensures that the parent folder in the destination URL exists in the specified site, and it returns the site-relative URL of the parent folder. The EnsureParentFolder method accepts two parameters: an SPWeb object that represents the parent site, and a string that contains the absolute URL that is passed from the UploadFile method. If the parent folder does not exist, the EnsureParentFolder method creates it.
    [Visual Basic .NET]
    
    Public Function EnsureParentFolder(parentSite As SPWeb, destinUrl As String) As String
    
        destinUrl = parentSite.GetFile(destinUrl).Url
    
        Dim index As Integer = destinUrl.LastIndexOf("/")
        Dim parentFolderUrl As String = String.Empty
    
        If index > - 1 Then
    
            parentFolderUrl = destinUrl.Substring(0, index)
    
            Dim parentFolder As SPFolder = parentSite.GetFolder(parentFolderUrl)
    
            If Not parentFolder.Exists Then
    
                Dim currentFolder As SPFolder = parentSite.RootFolder
                Dim folder As String
    
                For Each folder In  parentFolderUrl.Split("/"c)
    
                    currentFolder = currentFolder.SubFolders.Add(folder)
    
                Next folder
    
            End If
    
        End If
    
        Return parentFolderUrl
    
    End Function 'EnsureParentFolder
    [C#]
    
    public string EnsureParentFolder(SPWeb parentSite, string destinUrl)
    {
        destinUrl = parentSite.GetFile(destinUrl).Url;
    
        int index = destinUrl.LastIndexOf("/");
        string parentFolderUrl = string.Empty;
    
        if (index > -1)
        {
            parentFolderUrl = destinUrl.Substring(0, index);
    
            SPFolder parentFolder = parentSite.GetFolder(parentFolderUrl);
    
            if (! parentFolder.Exists)
            {
                SPFolder currentFolder = parentSite.RootFolder;
    
                foreach(string folder in parentFolderUrl.Split('/'))
                {
                    currentFolder = currentFolder.SubFolders.Add(folder);
                }
            }
        }
    
        return parentFolderUrl;
    }

    The GetFile method of the SPWeb class is used in combination with the Url property of the SPFile class to convert the URL to a site-relative URL, throwing an exception if the specified URL is not found within the scope of the site. The URL of the parent folder is calculated by using the String.LastIndexOf method to determine the last appearance of a forward slash (/) within the destination URL. If there is no slash (in other words, the index equals -1), then the destination is the root folder for the site and the parentFolderUrl parameter returns an empty string. Otherwise, the example uses the GetFolder method of the SPWeb class to return the destination parent folder. If the folder does not exist, the example constructs the folder.

To upload a file from a local folder on the same server that is running Windows SharePoint Services, you can instead use a System.IO.FileStream object. In this case, add a using directive for the System.IO namespace, in addition to directives for System and Microsoft.SharePoint . The following example uses the Click event handler to call an UploadFile method, which in turn calls the previously described EnsureParentFolder method:

[Visual Basic .NET]

Public Sub UploadFile(srcUrl As String, destUrl As String)

    If Not File.Exists(srcUrl) Then

        Throw New ArgumentException(String.Format("{0} does not exist", srcUrl), "srcUrl")

    End If

    Dim site As SPWeb = New SPSite(destUrl).OpenWeb()

    Dim fStream As FileStream = File.OpenRead(srcUrl)
    Dim contents(fStream.Length) As Byte
    fStream.Read(contents, 0, CInt(fStream.Length))
    fStream.Close()

    EnsureParentFolder(site, destUrl)

    site.Files.Add(destUrl, contents)

End Sub 'UploadFile
[C#]

public void UploadFile(string srcUrl, string destUrl)
{
    if (! File.Exists(srcUrl))
    {
        throw new ArgumentException(String.Format("{0} does not exist", srcUrl), "srcUrl");
    }

    SPWeb site = new SPSite(destUrl).OpenWeb();

    FileStream fStream = File.OpenRead(srcUrl);
    byte[] contents = new byte[fStream.Length];
    fStream.Read(contents, 0, (int)fStream.Length);
    fStream.Close(); 

    EnsureParentFolder(site, destUrl);
    site.Files.Add(destUrl, contents);
}

The UploadFile method accepts two parameters. The srcUrl parameter specifies the path of the source location in the file system of the local computer, and the destUrl parameter specifies the absolute URL of the destination. A System.IO.FileStream object is used to read the source file into a byte array for use with the Add method of the SPFileCollection class.

Note  The size of the file that is uploaded cannot exceed two gigabytes.

Handling Document Library Events

Microsoft Windows SharePoint Services 2.0 provides document library events that enable developers to build upon the SharePoint platform. Developers can create managed code assemblies that define handlers for these events and then bind the handlers to document libraries. The event handlers can call into the SharePoint object model to access the configuration and content databases directly, or they can invoke external services, using Windows SharePoint Services as a user interface for other systems.

The following table describes the events for document libraries that Windows SharePoint Services provides.

Event Description
Cancel Check Out Changes made to a checked-out document are undone.
Check In A document is checked in to the library.
Check Out A document is checked out from the library.
Copy A document in the library is copied.
Delete A document is deleted from the library.
Insert A new document is saved to the library.
Move or Rename A document is moved or renamed.
Update An existing document or the value of a custom column in the library is edited.

In the context of Windows SharePoint Services, an event handler is a .NET class that implements the IListEventSink interface, whose one method, OnEvent, is used within the handler. The SPListEvent object contains information about an event that occurs, and you can return the type of event through the Type property. Use the Site property to access the object model of the Microsoft.SharePoint namespace within the handler.

You must install the managed assembly that defines an event handler in the Global Assembly Cache (GAC). In a server farm configuration, you must install this managed assembly in the GAC of each front-end Web server.

To deploy an event handler on a server, event handling must be enabled on the Virtual Server General Settings page in SharePoint Central Administration.

Only users with full permissions for a document library can add event handlers.

Event settings

The list metadata for a document library binds the class of an event handler to a library by means of the following properties. The metadata can be set on the Document Library Advanced Settings page for the document library through code that implements the EventSinkAssembly, EventSinkClass, and EventSinkData properties of the SPList class, or through definitions contained in front-end site templates. The following table summarizes the event settings.

Setting Type Description
Assembly Name String The strong name of the event handler assembly file that lives in the GAC.
Class Name String The fully qualified, case-sensitive name of the class within the assembly.
Properties String An arbitrary string of custom properties for use by the event handler whose length cannot exceed 255 characters.

After you install the event handler assembly, on the Document Library Advanced Settings page for the document library, specify the strong name of the assembly in the Assembly Name box, which must be in the format Assembly_Name, Version=Version, Culture=Culture, PublicKeyToken=Public_Key_Token. You can obtain these values by browsing to %windir%\assembly in Windows Explorer. As an example, the strong name for the Windows SharePoint Services assembly looks like Microsoft.SharePoint, Version=11.0.0.0, Culture=Neutral, PublicKeyToken=71e9bce111e9429c.

The value that you specify in the Class Name box must be the full, case-sensitive name of a class defined in the specified assembly that implements the IListEventSink interface. For example, the full name of the class in the following example would be myNamespace.myClass.

[Visual Basic .NET]

Namespace myNamespace

    Public Class myClass

        Inherits Microsoft.SharePoint.IListEventSink

        Public Sub OnEvent(evt As Microsoft.SharePoint.SPListEvent)

            'Add an announcement
            AddAnnouncement(evt)

        End Sub 'OnEvent

        Public Sub AddAnnouncement(evt As Microsoft.SharePoint.SPListEvent)
        .
        .
        .
        End Sub 'AddAnnouncement

    End Class 'myClass

End Namespace 'myNamespace
[C#]

namespace myNamespace
{
    public class myClass : Microsoft.SharePoint.IListEventSink
    {
        public void OnEvent(Microsoft.SharePoint.SPListEvent evt)
        {
            //Add an announcement
            AddAnnouncement(evt);
        }

        public void AddAnnouncement(Microsoft.SharePoint.SPListEvent evt)
        {
            .
            .
            .
        }
    }
}

Typing a value in the Properties box is optional. This value can contain up to 255 characters for use by the event handler.

 

Events in relation to other events

 

  • An event handler running in the context of Windows SharePoint Services cannot generate other events. To program side effects for an event, you must provide the code within the event handler.
  • The event handler is called asynchronously from the actual request.
  • A new instance of an event handler class is created for each event. Consequently, you cannot store state in your event handler class and expect it to persist across multiple events. You can, however, create a base class for an event handler or for multiple event handlers that caches state so that the same sink object can be used for all events on a document library.

 

Caching credentials

Event handlers run in the context of the Internet Information Services (IIS) Application Pool Identity, an account that typically has no permissions in Windows SharePoint Services. If your handler needs to interact with Windows SharePoint Services through the object model, you need to establish and cache credentials through impersonation of a user. For information, see Impersonating and Reverting.

Security context

The event handler thread runs within the same application pool account as the SharePoint virtual server. If, however, the event handler needs to be run in a different account in order to manipulate Windows SharePoint Services or an external service, the developer must maintain his or her own user credentials and manage his or her own security context.

Exceptions and errors

Exceptions for event handlers used in Windows SharePoint Services are thrown in the following conditions, for which a Microsoft Windows NT event log entry is created:

  • The assembly for the handler cannot be loaded.
  • The class defining the handler is not found.
  • The class does not implement the IListEventSink interface.
  • The OnEvent method throws an exception.

Note  When you restart IIS, each IIS worker process terminates only after all its queued work items, including HTTP requests and document library events, complete their tasks.

 

Definitions and templates

Developers can define event handler assemblies within list definitions, which provides a useful means for deploying solutions such as workflow-enabled document libraries in which events are already bound to the appropriate handlers. An event handler can be bound to a document library through the EventSinkAssembly, EventSinkClass, and EventSinkData attributes of the List element in the SCHEMA.XML file for the list type. When an end user creates a library through the UI from a list definition that specifies an event handler, list event settings are automatically set to the values specified in the definition. When an end user saves a document library as a list template, event settings specified through the UI are preserved in the template.

For information about definitions and templates for sites or lists, see Introduction to Templates and Definitions.

Event handler example

The following programming task creates an event handler that deletes the oldest version of a file in a document library when the number of versions for the file reaches a specified number. To establish credentials for the handler, a method is used that returns a token to the event handler for impersonation of a user.

  1. On the File menu in Visual Studio .NET, point to New and then click Project.
  2. In the New Project dialog box, select Visual Basic Projects or Visual C# Projects in the Project Types box.
  3. In the Templates box, select Class Library.
  4. In the Name box, type the name of the project, which in this task is "DocLibHandler".
  5. In the Location box, type the path to where to create the project, and then click OK.
  6. In Solution Explorer, right-click the References node, and click Add Reference on the shortcut menu.
  7. On the .NET tab of the Add Reference dialog box, select Windows SharePoint Services in the list of components, click Select, and then click OK.
  8. Add the following directives to the Class1.cs or Class1.vb file of the DocLibHandler project after the System directive that is included by default.
    [Visual Basic .NET]
    
    Imports System.Security.Principal
    Imports System.Runtime.InteropServices
    Imports Microsoft.SharePoint
    [C#]
    
    using System.Security.Principal;
    using System.Runtime.InteropServices;
    using Microsoft.SharePoint;
  9. Change the namespace and class name in the Class1.cs or Class1.vb file to be DocLibEventHandler and DocVersionHandler, as follows.
    [Visual Basic .NET]
    
    Namespace DocLibEventHandler
       
       Public Class DocVersionHandler
          Implements IListEventSink
    [C#]
    
    namespace DocLibEventHandler
    {
        public class DocVersionHandler : IListEventSink
        {
  10. Add the OnEvent method of the IListEventSink interface to the DocVersionHandler class, as follows.
    [Visual Basic .NET]
    
    Private maxVersions As Integer = 5
    
    Sub IListEventSink.OnEvent(listEvent As Microsoft.SharePoint.SPListEvent)
    
        ' TODO: ***** PROVIDE YOUR IMPLEMENTATION HERE ****
        ' Get the credentials (User_Alias, Domain, Password) that this event sink instance should 
        ' run as and initialize the wic object by calling the CreateIdentity method
    
        Dim wic As WindowsImpersonationContext = CreateIdentity(User_Alias, Domain, Password).Impersonate()
    
        If listEvent.Type = SPListEventType.Update OrElse listEvent.Type = SPListEventType.CheckIn Then
    
            Dim site As SPWeb = listEvent.Site.OpenWeb()
            Dim file As SPFile = site.GetFile(listEvent.UrlAfter)
            Dim nDocVersions As Integer = file.Versions.Count
    
            While maxVersions > 0 AndAlso nDocVersions > maxVersions - 1
    
                file.Versions.Delete(0)
                nDocVersions = file.Versions.Count
    
            End While
    
        End If
    
        wic.Undo()
    
    End Sub 'IListEventSink.OnEvent
    [C#]
    
    private int maxVersions = 5;
    
    void IListEventSink.OnEvent(Microsoft.SharePoint.SPListEvent listEvent)
    {
        /* TODO: ***** PROVIDE YOUR IMPLEMENTATION HERE ****
        Get the credentials (User_Alias, Domain, Password) that this event sink instance should run as
        and initialize the wic object by calling the CreateIdentity method*/
    
        WindowsImpersonationContext wic = CreateIdentity(User_Alias, Domain, Password).Impersonate();
    
        if ((listEvent.Type == SPListEventType.Update) ||
            (listEvent.Type == SPListEventType.CheckIn))
        {
            SPWeb site = listEvent.Site.OpenWeb();
            SPFile file = site.GetFile(listEvent.UrlAfter);
            int nDocVersions = file.Versions.Count;
    
            while ((maxVersions > 0) && (nDocVersions > (maxVersions - 1)))
            {
                file.Versions.Delete(0);
                nDocVersions = file.Versions.Count;
            }
        }
    
        wic.Undo();
    }
  11. The OnEvent method calls the following method to impersonate an account with administrative permissions.

    Important  It is not recommended that you pass credentials in clear-text, because this presents a security risk. To impersonate a user more securely, you can return the information programmatically with functions provided by the operating system for getting secret data from the user, such as the CryptProtectData and CryptUnprotectData functions of the Data Protection API (DPAPI).

    Include the following method within the DocVersionHandler class.

    [Visual Basic .NET]
    
    Protected Shared Function CreateIdentity(User As String, Domain As String, Password As String) As WindowsIdentity
    
        ' The Windows NT user token.
        Dim tokenHandle As New IntPtr(0)
    
        Const LOGON32_PROVIDER_DEFAULT As Integer = 0
        Const LOGON32_LOGON_NETWORK As Integer = 3
    
        tokenHandle = IntPtr.Zero
    
        ' Call LogonUser to obtain a handle to an access token.
        Dim returnValue As Boolean = LogonUser(User, Domain, Password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, tokenHandle)
    
        If False = returnValue Then
    
            Dim ret As Integer = Marshal.GetLastWin32Error()
            Throw New Exception("LogonUser failed with error code: " + ret)
    
        End If
    
        System.Diagnostics.Debug.WriteLine(("Created user token: " + tokenHandle))
    
        'The WindowsIdentity class makes a new copy of the token.
        'It also handles calling CloseHandle for the copy.
        Dim id As New WindowsIdentity(tokenHandle)
        CloseHandle(tokenHandle)
        Return id
    
    End Function 'CreateIdentity
    <DllImport("advapi32.dll", SetLastError := True)>  _
        Private Shared Function LogonUser(lpszUsername As String, lpszDomain As String, _
            lpszPassword As String, dwLogonType As Integer, dwLogonProvider As Integer, _
            ByRef phToken As IntPtr) As Boolean
    
    <DllImport("kernel32.dll", CharSet := CharSet.Auto)>  _
        Private Shared Declare Auto Function CloseHandle Lib "kernel32.dll" (handle As IntPtr) As Boolean
    [C#]
    
    protected static WindowsIdentity CreateIdentity(string User, string Domain, string Password)
    {
        // The Windows NT user token.
        IntPtr tokenHandle = new IntPtr(0);
    
        const int LOGON32_PROVIDER_DEFAULT = 0;
        const int LOGON32_LOGON_NETWORK = 3;
    
        tokenHandle = IntPtr.Zero;
    
        // Call LogonUser to obtain a handle to an access token.
        bool returnValue = LogonUser(User, Domain, Password, 
        LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
        ref tokenHandle);
    
        if (false == returnValue)
        {
            int ret = Marshal.GetLastWin32Error();
            throw new Exception("LogonUser failed with error code: " +  ret);
        }
    
        System.Diagnostics.Debug.WriteLine("Created user token: " + tokenHandle);
    
        //The WindowsIdentity class makes a new copy of the token.
        //It also handles calling CloseHandle for the copy.
        WindowsIdentity id = new WindowsIdentity(tokenHandle);
        CloseHandle(tokenHandle);
        return id;
    }
    
    [DllImport("advapi32.dll", SetLastError=true)]
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
    int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
    
    [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
    private extern static bool CloseHandle(IntPtr handle);
  12. To create a strong name for the assembly, go to the Local_Drive:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin directory (Local_Drive:\Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Bin in Visual Studio .NET Version 7) through a command prompt, and type sn -k Local_Drive:\DocLibHandler.snk, which creates a key file for the assembly.
  13. Add the following attributes for the assembly version and key file to the AssemblyInfo file of the project, replacing the attributes that are provided by default.
    [assembly: AssemblyVersion("1.0.0.0")]
    [assembly: AssemblyKeyFile("Local_Drive:\\DocLibHandler.snk")]
    
  14. Click Build Solution on the Build menu.
  15. To install your solution in the GAC, drag the dynamic-link library (DLL) of your assembly to the Local_Drive:\WINDOWS\assembly directory in Windows Explorer.
  16. On the Virtual Server General Settings page in SharePoint Central Administration, select On in the Event Handlers section to enable use of event handlers on the virtual server.
  17. From a view of the document library to which you want to attach the event handler assembly, click Modify settings and columns, and then click Change advanced settings on the page for customizing the document library.
  18. On the Document Library Advanced Settings page, type the strong name for the assembly in the Assembly Name box. For example, DocLibHandler, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=0fafac2a0cc92888. You can get the values used in the strong name by right-clicking the DLL of your assembly in the Local_Drive:\WINDOWS\assembly directory and then clicking Properties on the shortcut menu.
  19. Type the fully qualified, case-sensitive name of the class in the Class Name box, which in this example is DocLibEventHandler.DocVersionHandler.
  20. Reset IIS by typing iisreset at a command prompt.

To implement the handler in a document library, versioning must be enabled on the Document Library Settings page for the library.

Adding or Removing Users

You can add users to a site group by using one of the AddUser methods of the SPRole class.

For example, after instantiating an SPWeb object, return the Administrator group for the site as follows: SPRole admins = web.Roles["Administrator"] (in Visual Basic .NET, use Dim admins As SPRole = web.Roles("Administrator")). Next, call the AddUser method on the SPRole object as follows:

[Visual Basic .NET]
         
admins.AddUser("Domain_Name\Someone", "someone@example.com", "Someone", "Public relations.") 
[C#]

admins.AddUser("Domain_Name\\Someone","someone@example.com","Someone","Public relations.");

In this example, the logon name, e-mail address, user name, and notes are specified for the AddUser method.

In the following example, user input is gathered from four text boxes to supply parameter values for the AddUser method. If successful, a message is displayed through a label; otherwise, a try catch block traps the exception, whose message is displayed in the label.

The example assumes the existence of a .aspx page that contains a label control.

[Visual Basic .NET]
         
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)

Dim userName As String = TextBox1.Text
Dim displayName As String = TextBox2.Text
Dim email As String = TextBox3.Text
Dim notes As String = TextBox4.Text
Dim admins As SPRole = mySite.Roles("Administrator")

Try

    admins.AddUser(userName, email, displayName, notes)
    Label1.Text = "Successfully added user."

Catch ex As Exception

    Label1.Text = SPEncode.HtmlEncode(ex.ToString())

End Try
[C#]

SPWeb mySite = SPControl.GetContextWeb(Context);

string userName = TextBox1.Text;
string displayName = TextBox2.Text;
string email = TextBox3.Text;
string notes = TextBox4.Text;

SPRole admins = mySite.Roles["Administrator"];

try
{
    admins.AddUser(userName,email,displayName,notes);
    Label1.Text = "Successfully added user.";
}

catch(Exception ex)
{
    Label1.Text = SPEncode.HtmlEncode(ex.ToString());
}

The previous example requires using directives (Imports in Visual Basic) for the Microsoft.SharePoint, Microsoft.SharePoint.Utilities, and Microsoft.SharePoint.WebControls namespaces.

To remove a user from a site group, use the RemoveUser method of the SPRole class. The following example removes the user with the logon name that is typed in a text box and displays the number of users before and after the user is removed. An indexer is used with the Users property of SPRole in order to create a user object for the specified user. For information about indexers, see Programming with the Microsoft.SharePoint and Microsoft.SharePoint.Administration Namespaces.

[Visual Basic .NET]
         
Dim userName As String = TextBox1.Text
Dim mySite As SPWeb = SPControl.GetContextWeb(Context)
Dim adminRole As SPRole = mySite.Roles("Administrator")
Dim userRemove As SPUser = adminRole.Users(userName)

Label1.Text = adminRole.Users.Count.ToString()

adminRole.RemoveUser(userRemove)

Label2.Text = adminRole.Users.Count.ToString() 
[C#]

string userName = TextBox1.Text;

SPWeb mySite = SPControl.GetContextWeb(Context);
SPRole adminRole = mySite.Roles["Administrator"];
SPUser userRemove = adminRole.Users[userName];

Label1.Text = adminRole.Users.Count.ToString();
adminRole.RemoveUser(userRemove);
Label2.Text = adminRole.Users.Count.ToString();

Use one of the AddUser methods or the RemoveUser method of the SPGroup class to add or remove users similarly in a cross-site group. You can also use the AddCollection method of the SPPermissionCollection class to add users, site groups, and cross-site groups to the set of permissions for a list. In addition, you can use the AddCollection method of the SPUserCollection class to add users to the collection of users in a site, site group, or cross-site group.

The previous example requires using directives (Imports in Visual Basic) for the Microsoft.SharePoint and Microsoft.SharePoint.WebControls namespaces.

The example assumes the existence of a .aspx page that contains two label controls.

Note  Microsoft SharePoint Products and Technologies no longer rely on role-based security for assigning rights and permissions to users. Instead, SharePoint Products and Technologies use site groups and cross-site groups to assign rights and permissions to users. Site groups are custom security groups that apply to a specific Web site. Cross-site groups are custom security groups that apply to more than one Web site. For more information, see Microsoft Windows SharePoint Services Help.

Returning Central Administrative Properties

Use classes in the Microsoft.SharePoint.Administration namespace to access global administrative property settings for a deployment of Microsoft Windows SharePoint Services. The top-level class, SPGlobalAdmin, provides accessor properties to various supplementary classes, such as SPVirtualServer, SPGlobalConfig, and SPUsageSettings. Together, these classes provide access to global administrative settings that are maintained within the configuration database. This programming task shows how to create a custom report of administrative settings and usage.

Use the SPGlobalAdmin constructor to create an SPGlobalAdmin object, and then use its properties to return instances of the other classes. The following example shows how to create a global administration object and then use it to return various property settings:

[Visual Basic .NET]
         
Dim globAdmin As New SPGlobalAdmin()

Dim mailFrom As String = globAdmin.MailFromAddress
Dim mailTo As String = globAdmin.MailReplyToAddress
Dim mailCodePg As String = globAdmin.MailCodePage.ToString()

Dim apPools As System.Collections.IDictionary = globAdmin.ApplicationPools
Dim myEntry As DictionaryEntry

For Each myEntry In  apPools

    applicationPools += myEntry.Key + "  " + myEntry.Value + "<BR>"

Next myEntry

 

[C#]

SPGlobalAdmin globAdmin = new SPGlobalAdmin();

string mailFrom = globAdmin.MailFromAddress;
string mailTo = globAdmin.MailReplyToAddress;
string mailCodePg = globAdmin.MailCodePage.ToString();
System.Collections.IDictionary apPools = globAdmin.ApplicationPools;

foreach (DictionaryEntry myEntry in apPools)
{
    applicationPools += myEntry.Key + "  " + myEntry.Value + "<BR>";
}

 

The example iterates through the collection of dictionary key-and-value pairs returned by the ApplicationPools property, which represent the name and type of each application pool currently being used in Internet Information Services (IIS).

In the next example, the Config property of the SPGlobalAdmin class returns an SPGlobalConfig object, which in turn gets the name of the SharePoint Administration group, as well as a list of the file types that cannot be saved or retrieved on the server:

[Visual Basic .NET]
         
Dim globConfig As SPGlobalConfig = globAdmin.Config
Dim admGroup As String = globConfig.AdminGroup
Dim blkdFileTypes As System.Collections.Specialized.StringCollection = globConfig.BlockedFileTypes
Dim i As Integer

For i = 0 To blkdFileTypes.Count - 1

    blockedTypes += blkdFileTypes(i) + "<BR>"

Next i
[C#]

SPGlobalConfig globConfig = globAdmin.Config;
string admGroup = globConfig.AdminGroup;
System.Collections.Specialized.StringCollection blkdFileTypes = globConfig.BlockedFileTypes;
			
for (int i=0; i<blkdFileTypes.Count; i++)
{
    blockedTypes += blkdFileTypes[i] + "<BR>";
}

As in the above example, use the BlockedFileTypes property to return a string collection of the blocked file extensions, and then use an indexer to iterate through the collection and concatenate the strings into a single string.

Use the UsageSettings property of the SPGlobalAdmin class to return an SPUsageSettings object, whose properties define usage analysis settings. In this example, the object is used to report the directory where log files are stored, the number of log files created, and whether logging is enabled, as well as the processing start and end times and whether usage processing is enabled.

[Visual Basic .NET]
         
Dim useSettings As SPUsageSettings = globAdmin.UsageSettings
Dim logFilesDir As String = useSettings.LogFilesDirectory
Dim numberLogFiles As String = useSettings.NumberLogFiles.ToString()

If useSettings.LoggingEnabled = True Then

    logEnab = "Enabled"

Else

    logEnab = "Not enabled"

End If

Dim processEnd As String = useSettings.ProcessingEndTime.ToString()
Dim processStart As String = useSettings.ProcessingStartTime.ToString()

If useSettings.UsageProcessingEnabled = True Then

    useProcEnab = "Enabled"

Else

    useProcEnab = "Not enabled"

End If
[C#]

SPUsageSettings useSettings = globAdmin.UsageSettings;

string logFilesDir = useSettings.LogFilesDirectory;
string numberLogFiles = useSettings.NumberLogFiles.ToString();

if (useSettings.LoggingEnabled == true)
{
    logEnab = "Enabled";
}
else
{
    logEnab = "Not enabled";
}

string processEnd = useSettings.ProcessingEndTime.ToString();
string processStart = useSettings.ProcessingStartTime.ToString();

if (useSettings.UsageProcessingEnabled == true)
{
    useProcEnab = "Enabled";
}
    else
{
    useProcEnab = "Not enabled";
}

The VirtualServers property of the SPGlobalAdmin class returns the collection of all the virtual servers on a server running Windows SharePoint Services. In addition to reporting several administrative settings, the following example iterates through the collection of virtual servers and prints the version number of the installation if the server state (represented by an SPVirtualServerState value) is Ready.

[Visual Basic .NET]
         
Dim serverVersion As String
Dim virtServers As String
Dim vServers As SPVirtualServerCollection = globAdmin.VirtualServers
Dim j As Integer

For j = 0 To vServers.Count - 1

    If vServers(j).State.ToString().Equals("Ready") Then

        serverVersion = vServers(j).Version.ToString()

    Else

        serverVersion = "N/A"

    End If

    virtServers += "Application Pool ID: " _
        & vServers(j).ApplicationPoolId.ToString() _
        & "<BR>Description: " & vServers(j).Description.ToString() _
        & "<BR>Host Name: " & vServers(j).HostName.ToString() _
        & "<BR>IIS Instance ID: " & vServers(j).IISInstanceId.ToString() _
        & "<BR>Port Number: " & vServers(j).Port.ToString() _
        & "<BR>State: " & vServers(j).State.ToString() & "<BR>URL: " _
        & vServers(j).Url.ToString() & "<BR>Version: " & serverVersion _
        & "<BR><BR>"

Next j
[C#]

string serverVersion, virtServers = "";

SPVirtualServerCollection vServers = globAdmin.VirtualServers;

for (int j = 0;j<vServers.Count;j++)
{
    if (vServers[j].State.ToString().Equals("Ready"))
    {
        serverVersion = vServers[j].Version.ToString();
    }
    else
    {
        serverVersion = "N/A";
    }

    virtServers += "Application Pool ID: " + vServers[j].ApplicationPoolId.ToString() +
    "<BR>Description: " + vServers[j].Description.ToString() + 
    "<BR>Host Name: " + vServers[j].HostName.ToString() + 
    "<BR>IIS Instance ID: " + vServers[j].IISInstanceId.ToString() + 
    "<BR>Port Number: " + vServers[j].Port.ToString() + 
    "<BR>State: " + vServers[j].State.ToString() + 
    "<BR>URL: " + vServers[j].Url.ToString() + 
    "<BR>Version: " + serverVersion + "<BR><BR>";
}

Setting the Administrative Port Identity

When a configuration database is created, the current application pool identity for SharePoint Central Administration is stored in the configuration database in the format DOMAIN\Account_Name. When a new computer is connected to the configuration database, Microsoft Windows SharePoint Services 2.0 verifies that the new application pool identity matches the identity stored in the configuration database. If the identities do not match, the operation to connect the new computer does not succeed.

To connect a new computer to the configuration database after changing the application pool identity, the identity that is stored in the configuration database must be set to the new identity. The following code example shows how to set the application pool identity by using the Properties property of the SPGlobalConfig class.

[Visual Basic .NET]

Dim spGlobalAdmin As New SPGlobalAdmin()

spGlobalAdmin.Config.Properties("AdminPortIdentity") = "Identity"

spGlobalAdmin.Config.Properties.Update()

spGlobalAdmin.Close()
[C#]

SPGlobalAdmin spGlobalAdmin = new SPGlobalAdmin();

spGlobalAdmin.Config.Properties["AdminPortIdentity"] = "Identity";

spGlobalAdmin.Config.Properties.Update();

spGlobalAdmin.Close();

The global string AdminPortIdentity is used as an indexer on the Properties property, which returns an SPPropertyBag object representing properties of the configuration database. The Update method must be used for changes to take effect in the database, and the Close method is used to release the resources consumed by the SPGlobalAdmin object.

In the context of a server farm, create separate instances of the SPGlobalAdmin class to modify the administrative port identity and to refresh the configuration cache, as in the following example.

[Visual Basic .NET]

Dim globalAdmin1 As SPGlobalAdmin = Nothing
Dim globalAdmin2 As SPGlobalAdmin = Nothing

Try

    globalAdmin1 = New SPGlobalAdmin()
    globalAdmin1.RefreshConfigCache()

    globalAdmin2 = New SPGlobalAdmin()
    globalAdmin2.Config.Properties("AdminPortIdentity") = "Identity"
    globalAdmin2.Config.Properties.Update()

Finally

    If Nothing <> globalAdmin1 Then

        globalAdmin1.Close()

    End If

    If Nothing <> globalAdmin2 Then

        globalAdmin2.Close()

    End If

End Try
[C#]

SPGlobalAdmin globalAdmin1 = null;
SPGlobalAdmin globalAdmin2 = null;

try
{
    globalAdmin1 = new SPGlobalAdmin();
    globalAdmin1.RefreshConfigCache();

    globalAdmin2 = new SPGlobalAdmin();
    globalAdmin2.Config.Properties["AdminPortIdentity"] = "Identity";
    globalAdmin2.Config.Properties.Update();
}

finally
{
    if (null != globalAdmin1)
    {
        globalAdmin1.Close();
    }

    if (null != globalAdmin2)
    {
        globalAdmin2.Close();
    }
}