Tuesday 18 October 2011

Navigation for sharepoint 2010 Top menu and flyout left navigation menu

<SharePoint:AspMenu
   ID="TopNavigationMenuV4"
   BackColor="Black"
   Runat="server"
   EnableViewState="false"
   DataSourceID="GlobalNavDataSource"
   AccessKey="<%$Resources:wss,navigation_accesskey%>"
   UseSimpleRendering="true"
   UseSeparateCss="true"
   Orientation="Horizontal"
   StaticDisplayLevels="1"
   MaximumDynamicDisplayLevels="2"
   BorderWidth="10px"
   BorderStyle="Solid"
   BorderColor="White"   
   SkipLinkText=""  
ItemWrap="true"
   CssClass="s4-tn_CMR"/>
  
   <PublishingNavigation:PortalSiteMapDataSource
    ID="GlobalNavDataSource"
    Runat="server"
    SiteMapProvider="CombinedNavSiteMapProvider" 
    StartFromCurrentNode="true" 
    StartingNodeOffset="0"
    ShowStartingNode="false"
    TreatStartingNodeAsCurrent="true"
    TrimNonCurrentTypes="Heading"/>
 <%@ register tagprefix="PublishingNavigation" namespace="Microsoft.SharePoint.Publishing.Navigation"
    assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Reference: http://msdn.microsoft.com/en-us/library/ms466994.aspx
http://sharepoint.microsoft.com/blogs/GetThePoint/Lists/Posts/Post.aspx?ID=114
msdn.microsoft.com


Flyout left navigation:

You can modify the appearance of Quick Launch by setting attributes on the AspMenu control that displays its navigational nodes. For example, you can set attributes that collapse the view of the menu to headings alone and add flyout menus for displaying subordinate menu levels.
The menu control is defined in the default master page for the website. To change characteristics of the menu, you must either customize the originally installed default master page or create a custom master page and set it as the default.

To display flyout menus by modifying the default master page

  1. Open your browser and navigate to the website that you want to customize.
  2. Click Site Actions, and then click Site Settings.
  3. In the Galleries section, click Master pages.
  4. Select v4.master. Then click Edit Document on the ribbon.
    The master page opens in the default editor. If Microsoft SharePoint Designer 2010 is installed on your computer, the file opens in SharePoint Designer.
  5. Close your browser.
    Note Note
    You might not be allowed to save changes to the site's default master page if a site-mapped page is open.
  6. Locate the Quick Launch menu control. You can find the control in code view by searching on the following string: <SharePoint:AspMenu id="V4QuickLaunchMenu"
  7. Set the value of the StaticDisplayLevels attribute and the MaximumDynamicDisplayLevels attribute to 1, as follows.
    <SharePoint:AspMenu id="V4QuickLaunchMenu" runat="server" 
        EnableViewState="false" DataSourceId="QuickLaunchSiteMap" 
        UseSimpleRendering="true" UseSeparateCss="false" Orientation="Vertical"
        StaticDisplayLevels="1" MaximumDynamicDisplayLevels="1" 
        SkipLinkText="" CssClass="s4-ql" />
    
    By default, the StaticDisplayLevels attribute is set to 2. This means that when the page is rendered, the Quick Launch area of the left navigation bar has two menu levels: a series of headings and, below each heading, a set of child links. Changing the value to 1 means that only headings are shown.
    The default value of the MaximumDynamicDisplayLevels attribute is 0. This disables flyout menus. Setting the value to 1 means that the first menu level below the last level on the static menu appears in a flyout menu. In this case, flyoutmenus appear for the first level below the headings.
  8. Save the file and open a page in the website to see the result of your changes.

To display flyout menus by creating a custom master page

  1. In SharePoint Designer 2010, open the website that you want to customize.
  2. In the Navigation pane, select Master Pages.
  3. Right-click v4.master, and then click Copy.
  4. Right-click an empty area of the Master Pages pane, and then click Paste.
    The file v4_copy(1).master is created.
  5. Right-click v4_copy(1).master, click Rename, and type a new name, such as my.master.
  6. Open the new file for editing.
  7. Locate the Quick Launch menu control. You can find the control in code view by searching on the following string: <SharePoint:AspMenu id="V4QuickLaunchMenu"
  8. Set the value of the StaticDisplayLevels attribute and the MaximumDynamicDisplayLevels attribute to 1, as follows.
    <SharePoint:AspMenu id="V4QuickLaunchMenu" runat="server" 
        EnableViewState="false" DataSourceId="QuickLaunchSiteMap" 
        UseSimpleRendering="true" UseSeparateCss="false" Orientation="Vertical"
        StaticDisplayLevels="1" MaximumDynamicDisplayLevels="1" 
        SkipLinkText="" CssClass="s4-ql" />
    
  9. On the File menu, click Save.
    Note Note
    You might not be allowed to save changes to the site's default master page if a site-mapped page is open in the browser. If this occurs, close the browser and try again.
  10. In the Navigation pane, select Master Pages.
  11. Right-click the name of your master page, and then click Set as Default Master Page.
    Note Note
    You can also set a custom master page as the default master by writing code that sets the value of the SPWeb.MasterUrl property.
  12. Open a page in the website to see the result of your changes.
You can replace the AspMenu control with another control, such as the SPTreeView control that displays a tree of nodes that collapse and expand.

To replace the Menu control with a TreeView control

  1. In SharePoint Designer 2010, open the website that you want to customize.
  2. In the Navigation pane, select Master Pages.
  3. Right-click v4.master, and then click Copy.
  4. Right-click an empty area of the Master Pages pane, and then click Paste.
    The file v4_copy(1).master is created.
  5. Right-click v4_copy(1).master, click Rename, and type a new name, such as my.master.
  6. Open the new file for editing.
  7. Locate the Quick Launch menu control. You can find the control in code view by searching on the following string: <SharePoint:AspMenu id="V4QuickLaunchMenu"
  8. Right click V4QuickLaunchMenu, select Select Tag, and then press the Delete key.
  9. Replace the deleted markup with markup for three new controls, an SPHierarchyDataSourceControl and an SPRememberScroll control that contains an SPTreeView control.
    <SharePoint:SPHierarchyDataSourceControl
          id="MyTreeViewDataSource"
          runat="server" RootContextObject="Web"
          IncludeDiscussionFolders="true" />
    <SharePoint:SPRememberScroll
          id="MyTreeViewRememberScroll"
          runat="server" onscroll="javascript:_spRecordScrollPositions(this);"
          Style="overflow: auto;height: 400px;width: 150px; ">
      <SharePoint:SPTreeView
            id="MyWebTreeView"
            runat="server"
            ShowLines="true"
            DataSourceId="MyTreeViewDataSource"
            ExpandDepth="3"
            SelectedNodeStyle-CssClass="ms-tvselected"
            NodeStyle-CssClass="ms-navitem"
            NodeStyle-HorizontalPadding="2"
            NodeStyle-VerticalPadding="5"
            SkipLinkText=""
            NodeIndent="20"
            ExpandImageUrl="/_layouts/images/tvplus.gif"
            CollapseImageUrl="/_layouts/images/tvminus.gif"
            NoExpandImageUrl="/_layouts/images/tvblank.gif" />
    </SharePoint:SPRememberScroll>
    
    
    This markup expands the top three nodes by default, specifies lines drawn between nodes, and specifies values for vertical padding and indentation.
  10. On the File menu, click Save.
    Note Note
    You might not be allowed to save changes to the site's default master page if a site-mapped page is open in the browser. If this occurs, close the browser and try again.
  11. In the Navigation pane, select Master Pages. Right-click the name of your master page, and then click Set as Default Master Page.
  12. Open a page in the website to see the result of your changes.

Wednesday 28 September 2011

Adding Properties to Visual Web Parts and maintains its value while iisreset

Adding Properties to Visual Web Parts

Visual Studio 2010 introduces a new feature called “Visual Web Parts”, which allows a developer to create a web part by using a user control as a base. SharePoint 2007 developers will find this very familiar, as they’ll see that Visual Studio 2010 simply does what we had done in the past, which is to create a web part to host the user control. So a Visual Web Part is a user control inside a web part.
VisualWebPartStructure
Let’s walk through creating a Visual Web Part and allow user customization of it. We’ll start by adding a Visual Web Part to a SharePoint project. After you add the Visual Web Part to your SharePoint project, you’ll notice Visual Studio adds many items to support the new web part.
VisualWebPartParts
There are three main items in here of interest:
  • HelloVisualWebPart.cs -This is the actual web part. The class contained in this code file inherits from WebPart and overrides CreateChildControls.
  • HelloVisualWebPartUserControl.ascx - This is the user control that will make up the interface for the web part.
  • HelloVisualWebPartUserControl.ascx.cs - This is the code behind for the user control. This is where any event handlers and other code to add functionality to the web part will be placed.
If you view the code in the HelloVisualWebPart.cs file, you’ll notice it simply loads the user control and places it inside the web part. Again – a Visual Web Part is simply a user control hosted in a web part.
// Code from HelloVisualWebPart.cs private const string _ascxPath = @"<<really long string omitted>>";
protected override void CreateChildControls()
{
    Control control = Page.LoadControl(_ascxPath);
    Controls.Add(control);
}

When creating a web part, one of the most common requirements is to allow the end user to customize it. Typically this is done by adding properties to the web part and using those properties to customize the display. This is where things change for a Visual Web Part.
Remember there are two moving parts making the magic happen here – the web part class, which SharePoint will see, and the user control, which houses the UI. If we add the property to the web part class, the user control won’t be able to access it. If we add the property to the user control, SharePoint won’t see it.
The solution is to add the property to the web part, and to add an instance of the web part to the user control. By adding the property to the web part, SharePoint can then prompt the user for a value. By passing the web part into the user control, you can then access these properties.
The first step, adding the property to the web part, is done as normal for a web part property.
// Added to HelloVisualWebPart.cs
[WebBrowsable(true)]
[WebDisplayName("Message")]
[WebDescription("Message to display to users")]
[Personalizable(PersonalizationScope.User)]
[Category("Message Configuration")]
public string Message
{
    get; set;
}

The second step, passing the web part into the user control takes just a little more work. First, we need somewhere to store the web part. We’ll accomplish this by adding a property to the user control of the web part type.
// Added to HelloVisualWebPartUserControl.ascx.cs
public HelloVisualWebPart
ParentWebPart
{
    get; set;
}

Then we need to change the code in the web part that’s adding the user control. The problem is it’s adding a normal user control, and not our specific user control. We need our specific user control as that’s the one with the property. We also then need to pass the web part into the user control.
// Modified in HelloVisualWebPart.cs
protected override void
CreateChildControls()
{
    HelloVisualWebPartUserControl control =
         (HelloVisualWebPartUserControl) Page.LoadControl(_ascxPath);

    control.ParentWebPart = this;
    Controls.Add(control);
}

Finally, we can now access the properties from the web part in the user control. In my little example, I’m just going to add that in as a label.
<%—Added to HelloVisualWebPartUserControl—%>
<asp:Label runat=”server” ID=”lblMessage” />

//Added to HelloVisualWebPartUserControl.ascx.cs protected void Page_Load(object sender, EventArgs e) {
    lblMessage.Text = ParentWebPart.Message;
}

After deploying the web part and adding it to a page, we then get the normal interface in SharePoint.
VisualWebPartFinal
So when we create a Visual Web Part we actually get two moving parts – the web part and a user control. If we want to add properties to the Visual Web Part, we need to add the property to the web part, and then pass an instance of the web part into the user control so the user control can access the values.

Webpart Properties

Visual Studio 2010 has a new template allowing you to create Visual Web Parts. One advantage of Visual Web Part as opposed to a regular web part is the ability to add user controls and markup of the web part right in the visual mode without having to provision it in your code-behind file.
If you developed web parts before, you know that hardly ever your web part will not need to accept properties. Usually the whole purpose of creating one is to allow your users or administrators to customize the properties.
When you create a new Visual WebPart (say call it SampleWP), among other files you will see the following key files:
1. SampleWP.CS
2. SampleWPUserControl.ascx
3. SampleWPUserControl.ascx.cs
In traditional web part you would define your properties in the file that inherits from WebPart class. In our case it’s SampleWP.CS. However, your entire logic is happening in your user control code behind file and therefore you need to reference web part properties in there.
Here is how to define properties that will be used in your code user control behind file.
1. In your SampleWP.CS set the following value of class identifier [ToolboxItemAttribute(true)]
2. In your class define the property that will be displayed to a user:
[WebBrowsable(true),
Category("Configuration"),
Personalizable(PersonalizationScope.Shared),
DefaultValue(""),
WebDisplayName("Property Title"),
WebDescription("Property Description")]
public string MyProperty
{
get { return myprop; }
set { myprop = value; }
}
public static string myprop;
Above, the ‘myprop’ static variable is the variable that will be referenced in your user control code behind class. like this:
someLabelOnForm.Text = SampleWP.myprop;
As you can see we can assign the value of our property from SampleWP.CS that will be collected from a user to be used in our user control.

Tuesday 6 September 2011

Lists: Retriveing datas from lists

 protected override void CreateChildControls()
        {
            if (!_error)
            {
              
                SPWeb web = SPContext.Current.Site.OpenWeb();
           
                try
                {
                    base.CreateChildControls();
                    // Your code here...
             
       
                    SPList li = web.Lists["123"];
                    SPQuery query = new SPQuery();
                    query.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>aaa</Value></Eq></Where>";
                    SPListItemCollection collist = li.GetItems(query);
                    foreach (SPListItem i in collist)
                    {
                        Label l = new Label();
                        l.ID = i.ID.ToString();
                        l.Text = i.Title.ToString();
                       
                        this.Controls.Add(l);
                    }
                   
                }

                catch (Exception ex)
                {
                    HandleException(ex);
                }
                finally
                {
                    web.Dispose();
                }
            }
        }


Creating Lists Programatically:

 public void createList()
        {
            // choose your site
            SPSite site = new SPSite("http://merdev-moss:5050");
            SPWeb web = site.OpenWeb();
            SPListCollection lists = web.Lists;

            // create new Generic list called "My List"
            lists.Add("My List", "My list Description", SPListTemplateType.GenericList);

            SPList list = web.Lists["My List"];

            // create Text type new column called "My Column"
            list.Fields.Add("My Column", SPFieldType.Text, true);

            // make new column visible in default view
            SPView view = list.DefaultView;
            view.ViewFields.Add("My Column");
            view.Update();
        }



Creating and retrieving listsin c# webpart

 protected override void CreateChildControls()
        {
            if (!_error)
            {
              
                SPWeb web = SPContext.Current.Site.OpenWeb();
           
                try
                {
                  
                    base.CreateChildControls();
                     web.AllowUnsafeUpdates = true;
                    // creating list
                    SPListCollection newlist = web.Lists;
                    newlist.Add("2", "asd", SPListTemplateType.GenericList);
                    SPList li = web.Lists["2"];
                    li.Fields.Add("Title", SPFieldType.Text,true);
                    SPListItemCollection listitemcol= web.Lists["2"].Items;
                    SPListItem item = listitemcol.Add();
                    item["Title"] = "aa9a";
                  
                    item.Update();
                    web.AllowUnsafeUpdates = false;
                   // retrieving datas from list
                 //   SPQuery query = new SPQuery();
                //    query.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>{0}</Value></Eq></Where>";
                //    SPListItemCollection collist = li.GetItems(query);
                    SPListItemCollection collist = li.Items;
                    foreach (SPListItem i in collist)
                    {
                        Label l = new Label();
                        l.ID = i.ID.ToString();
                        l.Text = i.Title.ToString();                    
                        this.Controls.Add(l);
                    }
                   
                }

                catch (Exception ex)
                {
                    HandleException(ex);
                }
                finally
                {
                    web.Dispose();
                }
            }
        }

Ajax tool kid in sharepoint

http://weblogs.asp.net/jan/archive/2007/02/26/using-the-ajax-control-toolkit-in-sharepoint.aspx


Actually SharePoint doesn't differ from any other ASP.NET web site to use the Control Toolit, there are only three things that you need to do:

Make sure SharePoint has access to AjaxControlToolkit.dll
You can do this in two ways: either you deploy the assembly to the Global Assembly Cache (GAC) or you put in the \BIN folder of the SharePoint site's folder.
Add an assembly reference in the web.config (note: for the future versions of the Control Tookit, the version number can change!):
<assemblies>
    ...
    <add assembly="AjaxControlToolkit, Version=1.0.10201.0, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"/>
    ....
</assemblies>
Add the tagprefix for the Control Toolkit in the web.config:
<controls>
    ...
    <add namespace="AjaxControlToolkit" assembly="AjaxControlToolkit" tagPrefix="ajaxToolkit"/>
    ....
</controls>

Friday 26 August 2011

sharepoint learning site


http://msdn.microsoft.com/en-us/SP2010DevTrainingCourse.aspx

http://msdn.microsoft.com/en-us/SharePoint

70-573:
http://blog.beckybertram.com/Exams.aspx



Studying for your SharePoint 2010 (70-573) exam.

I have decided to start studying for my first SharePoint 2010 exam. If you are doing the same then these resources may help.

Thursday 25 August 2011

Getting User Profile information

/ get the BadgeNumber for this user from the profile store
string _badgeNumber = string.Empty;
SPSite _SPSite = null;
try
{
    // TODO: move this to a configuration setting somewhere
    // get a reference to the current site
    _SPSite = new SPSite("http://siteurl/");
    // get a reference to the context of the current site
    ServerContext _ServerContext = ServerContext.GetContext(_SPSite);
    // get a UserProfileManager
    UserProfileManager _UserProfileManager = new UserProfileManager(_ServerContext);
    // get the UserProfile of the logged on user
    UserProfile _CurrentUserUserProfile = _UserProfileManager.GetUserProfile(System.Web.HttpContext.Current.User.Identity.Name);
    _badgeNumber = (string)_CurrentUserUserProfile["badgeNumber "].Value;  // NOT ["Badge Number"], that was my initial mistake, using display name instead of name :)
}
finally
{
    _SPSite.RootWeb.Dispose();
    _SPSite.Dispose();
}

(or)

 object user = null;
            _SPSite = new SPSite("http://vodafonedev:24/");
            string siteURL = SPContext.Current.Site.Url;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(siteURL))
                {
                    ServerContext serverContext = ServerContext.GetContext(_SPSite);
                    UserProfileManager profileManager = new UserProfileManager(serverContext);
                   // SPUser spUser = site.RootWeb.Users.GetByID(id);
                    UserProfile profile = profileManager.GetUserProfile(SPContext.Current.Web.CurrentUser.LoginName);
                  
                    user = new
                    {
                        Account = profile["AccountName"].Value,
                        Title = profile["Title"].Value,
                        First = profile["FirstName"].Value,
                        Last = profile["LastName"].Value,
                        PreferredName = profile["PreferredName"].Value,
                        WorkPhone = profile["WorkPhone"].Value,
                        Fax = profile["Fax"].Value,
                        WorkEmail = profile["WorkEmail"].Value,
                        Office = profile["Office"].Value,
                        Manager = profile["Manager"].Value
                    };
                }
            });




Sunday 21 August 2011

Adding a value to a user field

Adding a value to a user field



This is the same, but in reverse. We use the same class (SPFieldUserValue ) and give it the values we want for the user.



using (SPSite site = new SPSite("http://portal"))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList list = web.Lists["Example For Users"];
                    SPListItem item = list.Items[0];

                    SPFieldUserValue userValue = new SPFieldUserValue(web, web.CurrentUser.ID, web.CurrentUser.LoginName);
                    item["User Name"] = userValue;
                    item.Update();
                }
            }


The image below shows the list after I updated the list item:

Get a user from a list item:

Get a user from a list item:



To get a user we use the SPFieldUserValue class, which accepts a SPWeb and a string value as parameters. The string value is the value from the list that contains the ID and the account name. Once we have that, we can use the SPFieldUserValue to get information about the user.

Example:

 using (SPSite site = new SPSite("http://portal"))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList list = web.Lists["Example For Users"];
                    SPListItem item = list.Items[0];

                    SPFieldUserValue userValue = new SPFieldUserValue(web, item["User Name"].ToString());
                    if (userValue.User.LoginName == web.CurrentUser.LoginName)
                    {
                        //do something!
                    }
                }
            }

Sunday 31 July 2011

Browser compatability Allignment

For safari
@media screen and (-webkit-min-device-pixel-ratio:0)
{
}

Ie 7
*
Ie 8:
\0/ !important;

Wednesday 27 July 2011

Receiving Page details

Guid currentSiteGuid = SPContext.Current.Site.ID;
using (SPSite site = new SPSite(currentSiteGuid))
{
  using (SPWeb web = site.OpenWeb())
  {
  web.AllowUnsafeUpdates
  PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
  PublishingPageCollection pages = publishingWeb.GetPublishingPages();
  foreach (PublishingPage page in pages)
     {
                        
      SPFile file = web.GetFile(web.Url + "/" + page.Url);
       file.CheckOut();
      if (page.Name == "AdministratorInformation.aspx")
       {
         page.Title = "Administrator Information";
         page.Update();
                          
        }
       else  if (page.Name == "AdministratorPage.aspx")
       {
          page.Title = "Administrator Page";
          page.Update();
        }
  else
         {
            page.Title = "";
         }
                    
         file.CheckIn("pagename");
         file.Publish("Publish");
        file.Approve("Approve");
        file.Update();
        //Including Pages in current Navigation
        publishingWeb.IncludeInNavigation(true, page.ListItem.UniqueId);
        publishingWeb.ExcludeFromNavigation(true, page.ListItem.UniqueId);
      }
      publishingWeb.Update();
       web.Update();
       web.AllowUnsafeUpdates = false;
  }
}

Receiving datas from MasterPage gallary

Guid currentSiteGuid = SPContext.Current.Site.ID;
using (SPSite site = new SPSite(currentSiteGuid))
{
using (SPWeb web = site.OpenWeb())
{
SPQuery query = new SPQuery();
query.Query = "<Where><Eq><FieldRef Name='FileLeafRef' /><Value Type='Text'>Insidedefault.master</Value></Eq></Where>";
Microsoft.SharePoint.SPList gallery1 = site.GetCatalog(Microsoft.SharePoint.SPListTemplateType.MasterPageCatalog);
SPListItemCollection col = gallery1.GetItems(query);
if (col.Count > 0)
{
foreach (SPListItem item in col)
{
//web.AllowUnsafeUpdates = true;
item.Web.AllowUnsafeUpdates = true;
item.File.CheckOut();
item.File.CheckIn("check in");
item.File.Publish("publish");
item.File.Approve("dsf");
web.Update();
// item.Web.AllowUnsafeUpdates = true;
//web.AllowUnsafeUpdates = false;
}
}
}
}

13.SharePoint 2007 Deployment: Using Resources in Features

Why should I use Resources?

In my opinion, you should always use resource files for your features. Why?
  • First, because it’s easy to do even if you only have one language.
  • Second, because if you do, all the objects you are provisioning in SharePoint will be localized and will be displayed in the correct language of the website (provided you have deployed the resource file for that language).
Examples of things that should be placed in resource files:
  • Title and Description of you feature, so that they will be displayed in the language of the website;
  • Site column display name and description;
  • Content type name and description;
  • List template name and description;
  • List instance title and description;
  • Custom action title and description.

How do I use it?

There are three steps to use resources in a feature:
  1. Build the resource (.resx) files;
  2. Place the resource files in the correct folder;
  3. Use the resource strings in the feature manifest and element manifests.
Note: The next sections show how to use feature-specific resources. I’ll briefly discuss shared resources in the end of the post.

Building the resource (.resx) files

The best way to build the resource files is using Visual Studio 2008, but you can do it manually on any text editor since they’re just XML text files.
<?xml version="1.0" encoding="utf-8"?>
<root>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>
      System.Resources.ResXResourceReader, 
      System.Windows.Forms, 
      Version=2.0.0.0, 
      Culture=neutral, 
      PublicKeyToken=b77a5c561934e089
    </value>
  </resheader>
  <resheader name="writer">
    <value>
      System.Resources.ResXResourceWriter, 
      System.Windows.Forms, 
      Version=2.0.0.0, 
      Culture=neutral, 
      PublicKeyToken=b77a5c561934e089
    </value>
  </resheader>
  <data name="MyFeatureName" xml:space="preserve">
    <value>My Feature Name</value>
  </data>
  <data name="MyFieldDisplayName" xml:space="preserve">
    <value>My Field Display Name</value>
  </data>
  <data name="MyFieldChoice1" xml:space="preserve">
    <value>My Choice 1</value>
  </data>
  <data name="MyFieldChoice2" xml:space="preserve">
    <value>My Choice 2</value>
  </data>
</root>
See above an example of a resource (.resx) file. The <data> elements are the ones that hold the localized strings:
  • The name attribute is the key used to retrieve the localized string;
  • The <value> child element is the localized string itself.
Each language must have its own resource file which follows a specific naming convention:
  • The main resource file must be called Resources.resx. This is the culture neutral resource file (or fall back resource file) which will be used by SharePoint whenever there is no resource file for a specific culture.
  • All culture specific resource files must be named Resources.[culture].resx. Some examples:
    • Resources.en-US.resx (english – United States)
    • Resources.pt-PT.resx (portuguese – Portugal)
    • Resources.fr-FR.resx (french – France)
    • Resources.pt-BR.resx (portuguese – Brazil)

Placing the resource files in the correct folder

These files must be placed in a Resources folder inside your feature’s folder. So, if your feature’s folder is C:\…\12\TEMPLATE\FEATURES\MyFeature, the resource files need to be placed in the folder C:\…\12\TEMPLATE\FEATURES\MyFeature\Resources.

Resources and the Feature Manifest

After you have created the resource files and placed the in the correct folder, you can now used them in your feature manifest (feature.xml).
<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
         Id="5DFD12AF-D0AA-4c63-8FB8-C49DB1191083"
         Title="$Resources:MyFeatureName"
         Scope="Site"
         Version="1.0.0.0">
  <ElementManifests>
    <ElementManifest Location="SiteColumns.xml"/>
    <ElementFile Location="Resources\Resources.resx" />
    <ElementFile Location="Resources\Resources.pt-PT.resx" />
    <ElementFile Location="Resources\Resources.es-ES.resx" />
  </ElementManifests>
</Feature>
The sample above, shows a feature manifest that uses resources to specify the feature title. As you can see, the value of the Title attribute is $Resources:MyFeatureName. This tells SharePoint that it should check the resource file for the current website’s culture and retrieve the string that has the key MyFeatureName.
Notice the use of <ElementFile> elements to reference the resource files in the feature. This is required if you are deploying this feature through a solution package (.wsp).
Important: because we are using feature-specific resource files (resource files that are only used for this specific feature), you cannot use the DefaultResourceFile attribute on the <Feature> element. If you do, SharePoint will not look for resource files in the local Resources folder for this feature.

Resources and the Element Manifest

Besides using localized strings to specify the feature title and description, you can (and should) use localized strings for most feature elements.
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <Field Type="Choice"
         DisplayName="$Resources:MyFieldDisplayName"
         Required="FALSE"
         Format="Dropdown"
         FillInChoice="FALSE"
         ID="{485b2176-4cfc-4923-8085-c003b85dab36}"
         StaticName="MyField"
         Name="MyField">
    <Default>$Resources:MyFieldChoice1</Default>
    <CHOICES>
      <CHOICE>$Resources:MyFieldChoice1</CHOICE>
      <CHOICE>$Resources:MyFieldChoice2</CHOICE>
    </CHOICES>
  </Field>
 </Elements>
The sample above specifies a choice field, and uses localized strings for:
  • Field display name
  • Each of the field’s choices
  • The field’s default choice
The theory is exactly the same as it was used for the feature manifest: you use the expression $Resources:[key] whenever you want SharePoint to retrieve a localized string from the resource file of the current website’s culture.

Shared Resource Files

The method shown in the previous sections assumed that each feature has its own resource files. However, that is not always the case and SharePoint itself uses shared resource files. That is, resource files that can be shared by multiple features.
There are only two differences when using shared resource files:
  • The folder where the resource files are placed;
  • The way you reference the localized string in you feature manifest and element manifests.
Other than that, the file format and contents can be exactly the same.

Folder for Shared Resources

Shared resource files must be placed in the folder C:\…\12\Resources instead of the local Resources folder inside the feature folder.

Referencing Shared Resources

Because the shared resources files can have any name you want, you must reference the localized strings in a more specific way, so as to tell SharePoint which resource file holds a particular string.
<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
         Id="5DFD12AF-D0AA-4c63-8FB8-C49DB1191083"
         Title="$Resources:MyResources,MyFeatureName"
         Scope="Site"
         Version="1.0.0.0">
  <ElementManifests>
    <ElementManifest Location="SiteColumns.xml"/>
  </ElementManifests>
</Feature>
As you can see in the above sample, instead of $Resources:MyFeatureName I’m referencing the localized string with $Resources:MyResources,MyFeatureName. This tells SharePoint to look for:
  • A localized string whose key is MyFeatureName
  • In a resource file named MyResources.[Culture].resx
  • In the C:\…\12\Resources folder
If all your strings are in the same shared resource file, then you can specify that file as the default resource file and reference the strings as shown in the first sample.
<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
         Id="5DFD12AF-D0AA-4c63-8FB8-C49DB1191083"
         Title="$Resources:MyFeatureName"
         DefaultResourceFile="MyResources"
         Scope="Site"
         Version="1.0.0.0">
  <ElementManifests>
    <ElementManifest Location="SiteColumns.xml"/>
  </ElementManifests>
</Feature>
The sample above does exactly the same as the previous one. The only difference is that it specifies MyResources.[culture].resx as the default resource file and, because of that, you don’t need to specify it on all references to the localized strings.

Additional Notes

So, how does SharePoint choose which resource file to use when loading the localized strings?
  1. Looks for the resource file of the exact culture of the website. If you have a website based on a portuguese (pt-PT) site template, it will look for the Resources.pt-PT.resx. If it’s there, it loads all the strings from it.
  2. If it’s not there, it looks for any resource files of the same culture, even if it has a different location. So if your website’s language is pt-PT (Portuguese – Portugal) and you don’t have a Resources.pt-PT.resx file, but you have a Resources.pt-BR.resx (Portuguese – Brazil) file, then SharePoint will use it.
  3. If there is no resource file for the website’s culture, SharePoint will use the fall back resource file (Resources.resx).

Samples

You can download samples for:
These samples include:
  • The solution manifest file (manifest.xml).
  • The solution cab structure file (solution.ddf).
  • The feature manifest file (Feature.xml).
  • The element manifest file (SiteColumns.xml).
  • The resource files (.resx)
  • A batch file (build.bat) that creates the solution package
Warning: Do not install both solutions in the same farm, since some of the IDs are the same and the feature has the same name on both solutions. If you want to use it as is, test each solution separately, removing one before installing the other.

12.SharePoint 2007 Deployment: Feature Stapling

Feature Stapling

Feature stapling is the process of associating features to existing site definitions so that, when a new site is provisioned from that definition the associated features are automatically activated.
This means that you need, at least, two features to do this:
  • The feature (or features) you wish to associate (that is, to staple) to a site definition;
  • The feature that performs the association (the stapler).
The first one can be any feature with scope Site or Web. The second is the one I’m presenting in this post.

Allowed Scopes

The scopes to which a feature can be deployed, are dictated by the types of elements included in it. A feature with feature site template association elements can be deployed to Site Collection, Web Application or Farm scopes.

Feature Manifest

I will only present a simple feature manifest, since the additional options were presented in the above mentioned post.
<?xml version="1.0" encoding="utf-8" ?>
<Feature
    xmlns="http://schemas.microsoft.com/sharepoint/"
    Id="{8213A053-46B0-43f9-B00C-B2A8CF7A3355}"
    Title="My Feature Stapling"
    Description="This feature staples other features to a
    site definition."
    Scope="Farm"
    Creator="Create IT"
    Version="1.0.0.0">
  <ElementManifests>
    <ElementManifest Location="Elements.xml"/>
  </ElementManifests>
</Feature>

Notes about this feature manifest:
  • The title of the feature is My Feature Stapling.
  • It will be deployed as a Farm feature, since it's Scope value is Farm. By default, SharePoint automatically activates features of this scope. You can, however, override this behaviour by setting the ActivateOnDefault attribute to false on the Feature element.
  • It references a single element manifest file: Elements.xml.

Element Manifest

The element manifest file can have any name you wish (in this example it's called Elements.xml), but it's root element must be <Elements>. Inside this root element, you can place any number of feature element descriptions. In this example I will present the use of the <FeatureSiteTemplateAssociation> element which is used to associate features to existing site definitions.
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- My Site Columns -->
  <FeatureSiteTemplateAssociation 
    Id="{CC3144A5-E055-4474-928E-5D21CDE53D38}" 
    TemplateName="STS#0" />
  <!-- My Content Types -->
  <FeatureSiteTemplateAssociation 
    Id="{E739683D-ACB8-4187-A764-1323BE76D12D}" 
    TemplateName="STS#0" />
</Elements>
This example associates two features with the Team Site definition. The <FeatureSiteTemplateAssociation> element has no child elements and only two attributes:
  • Id - (required) The GUID of the feature that is to be stapled to the site definition.
  • TemplateName - (required) The name of the site definition including the configuration Id. For SharePoint’s out-of-the-box site definitions, this attribute can be:
    • STS#0 (Team Site)
    • STS#1 (Blank Site)
    • STS#2 (Document Workspace)
    • MPS#0 (Basic Meeting Workspace)
    • MPS#1 (Blank Meeting Workspace)
    • MPS#2 (Decision Meeting Workspace)
    • MPS#3 (Social Meeting Workspace)
    • MPS#4 (Multipage Meeting Workspace)
    • CENTRALADMIN#0 (Central Administration)
    • WIKI#0 (Wiki Site)
    • BLOG#0 (Blog Site)
    • BDR#0 (Document Center)
    • OFFILE#1 (Records Center)
    • SPSMSITEHOST#0 (My Site Host)
    • SPSMSITE#0 (Personalization Site)
    • CMSPUBLISHING#0 (Publishing Site)
    • BLANKINTERNET#2 (Publishing Site with Workflow)
    • BLANKINTERNETCONTAINER#0 (Publishing Portal)
    • SPSPORTAL#0 (Collaboration Portal)
    • SPSNHOME#0 (News Site)
    • SPSITES#0 (Site Directory)
    • SPSREPORTCENTER#0 (Report Center)
    • SRCHCEN#0 (Search Center with Tabs)
    • SRCHCENTERLITE#0 (Search Center)
There can be other site definitions depending on which site templates you have installed on your farm. The best way to check which ones you can use is to go to the folder C:\…\12\TEMPLATE\[LCID]\XML where [LCID] represent the Language ID of the site definition you are looking for, and open each webtemp*.xml file.
Each of these files will have the following structure:
<?xml version="1.0" encoding="utf-8"?>
<!-- _lcid="1033" _version="12.0.4518" _dal="1" -->
<!-- _LocalBinding -->
<Templates xmlns:ows="Microsoft SharePoint">
  <Template Name="STS" ID="1">
    <Configuration ID="0" 
                   Title="Team Site" 
                   Hidden="FALSE" 
                   ImageUrl="/_layouts/images/stsprev.png" 
                   Description="A site for teams to quickly […] 
                   DisplayCategory="Collaboration" >          
    </Configuration>
    <Configuration ID="1" 
                   Title="Blank Site" 
                   Hidden="FALSE" 
                   ImageUrl="/_layouts/images/blankprev.png" 
                   Description="A blank site for you to […] 
                   DisplayCategory="Collaboration" 
                   AllowGlobalFeatureAssociations="False" >      
    </Configuration>
    <Configuration ID="2" 
                   Title="Document Workspace" 
                   Hidden="FALSE" 
                   ImageUrl="/_layouts/images/dwsprev.png" 
                   Description="A site for colleagues to work[…] 
                   DisplayCategory="Collaboration" >          
    </Configuration>
    [...]
  </Template>
</Templates>
In the sample above you can see the description of the three configurations of the STS site template. To build the TemplateName required for the feature site template association, you get the template name (attribute Name of the element Template), which in this case is STS, add a hash sign (#) and complete the string with the configuration ID (attribute ID of the element Configuration), which in this case can be 0, 1 or 2, depending on the chosen configuration.

Sample

You can download this sample here. This sample includes:
  • The solution manifest file (manifest.xml).
  • The solution cab structure file (solution.ddf).
  • The feature manifest file (Feature.xml).
  • The feature site template association element manifest file (Elements.xml).
  • A batch file (build.bat) that creates the solution package (MyFeatureStapling.wsp).