Monday 26 December 2011

Run code with elevated privileges in SharePoint

RWEP (Run With Elevated Privileges) method will execute code to supply a delegate that runs a set of code in the context of an the Application Pool identity  account ( which has site collection administrator privileges on all site collections hosted by that application pool ) instead of the logged in user, essentially giving that user Administrator Level Permissions in a confined space.

Basically the code executed inside this method has "System Account" privileges in addition to the current user privileges or in a better way - we can tell that this method runs under the Application Pool identity, which has site collection administrator privileges on all site collections hosted by that application pool.

But sometimes we used to get "Access denied" even if we use code within RWEP method,looks strange but there are fact under which RWEP will work perfectly and the criteria's are


You should not use old references to SPWeb or SPSite instances inside your delegate, since these objects will hold the permissions of currently signed user, So you need to create new SPSite and SPWeb instances using the Ids of the sites and webs you already have a created, like this:

private void CustomFunction()
{
            // Non-Elevated Permission Code Goes Here

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                         SPSite site = SPContext.Current.Site;   
                         SPWeb web = SPContext.Current.Web;
                          //New SPSite object.
                         using (SPSite newsite = new SPSite(Site.ID))
                         {
                                      //New SPWeb object.
                                     using (SPWeb newWeb = newSite.OpenWeb(web.ID))
                                     {
                                    //Do things by assuming the permission of the "system account".
                                      }
                        }
            });  // Note the Brackets used while creating delegate
}

Example:

private void CustomFunction()
{
      SPSite site = SPContext.Current.Site;
      SPWeb web = SPContext.Current.Web;

      SPSecurity.RunWithElevatedPrivileges(delegate()
      {
            using (SPSite newSite = new SPSite(site.ID))
            {
                  using (SPWeb newWeb = newSite.OpenWeb(web.ID))
                  {
                        list = newWeb.Lists["ElevatedListTest"];
                        SPListItem newItem = list.Items.Add();
                       
                        // Do stuff to create the list item
 
                        newWeb.AllowUnsafeUpdates = true;
                        newItem["Title"] = "Testing Title";
                        newItem.Update();
                                          list.Update();
                        newWeb.AllowUnsafeUpdates = false;
                  }
            }
       });
}

Delegate Control

SharePoint Delegate control is a mechanism that we can insert a code or control to the SharePoint Master page(and Page Layout) without touching any of code in the SharePoint Master page(and in Page Layout) and also it is a container type control which can holds child controls on it 

The Search bar is located at the top of all the pages in a site, and the master page uses a delegate control in a placeholder to determine what to render at runtime. Here is the markup for the delegate control:


<SharePoint:DelegateControl runat=”server” ControlId=”SamllSearchInputBox”/>

Note that the ControlId value determines what delegate control is needed to be added in the respective place.

Importance:
·         Using the delegate control a developer can customize the SharePoint site controls without editing the code master page (After inserting the Delegate).
·         Suppose if you want add a counter for no.of.vistors to the site. We created a control for displaying the total count in the master page. If we want to keep this control in the master page we need to edit that master page and add all the controls over here. At any time if any mistake happen then whole master page will be changed knowingly or unknowingly. To avoid this we have delegate controls.

AdditionalPageHead
Top most delegate control in the master page allows multiple controls. You can use this delegate to inject JavaScript, custom logic, etc. to the master page. You can specify a control which only has a code to do whatever you need in onLoad event.
<Control Id="AdditionalPageHead" Sequence="90"             
           ControlSrc="~/_CONTROLTEMPLATES/a/test1.ascx" />

<Control Id="AdditionalPageHead" Sequence="91"             
           ControlSrc="~/_CONTROLTEMPLATES/b/ test1.ascx" />
Sequence controls the order if more than one control



Scenario 1 (Creating Delegate Within Master Page Itself)

You can create new simple delegate within the master page itself.





Scenario 2 (Creating Custom delegate control using Visual Studio)
Steps:
1.       Open Visual Studio 2010 and create a new Empty SharePoint project.
2.       Map a new folder to the CONTROLTEMPLATES directory in the SharePoint root (the 14 hive).
3.       Add a new item visual web part and empty element like below image.


4.       Design the logic inside the Visual Web part or add an div element with sample text for testing  and finally edit the Element.xml file like below

<?xml version="1.0" encoding="utf-8"?>


<Control Id="MyControl" Sequence="20" ControlSrc="~/controltemplates/TestTemp.ascx" />

</Elements>
5.       Save the changes and deploy into the site.
6.       Now we created a delegate control and want to add it to our site. Now add the following code to our master page anywhere you want.

<SharePoint:DelegateControl ControlId=" MyControl " AllowMultipleControls="true" runat="server">
</SharePoint:DelegateControl>





SpListItem.Update and SpListItem.SystemUpdate and SpListItem.UpdateOverwriteVersion

1.     Update(): With this method you can update the list item. But it will change values  in 'Modified By' to the SHAREPOINT\system account and sets the Modified column to the current date time. If versioning is enabled, the version is increased.

2.     SystemUpdate(): This method also updates the list item but it will not change the values in the Modified By and the Modified column. This method comes with two overloads. You can also specify a Boolean value to indicate if you want to increase the version number or not ( By default it will be fasle, so that the version will not be updated).

3.     UpdateOverwriteVersion(): This method updates the list item without changing the version number. 

Example:

 using (SPSite site = new SPSite("http://testsite"))
 {
        using (SPWeb web = site.OpenWeb())
        {
            SPList list = web.Lists["Test List"];
            SPListItem item = list.Items[1];
            item["Title"] = "Sample Update";
            item.Update(); // update version,modified and modified column
           //item.SystemUpdate(); // update version number
          //item. UpdateOverwriteVersion(); // update version number.
           list.Update();
         }

  }

SQL Joins


The SQL JOIN refers to using the JOIN keyword in a SQL statement in order to query data from two tables.

When you perform a SQL join, you specify one column from each table to join on. These two columns contain data that is shared across both tables.

Join Types

Depending on your requirements, you can do an "inner" join or an "outer" join. These are different in a subtle way
  • INNER JOIN (or JOIN) : This will only return rows when there is at least one row in both tables that match the join condition.
  • LEFT OUTER JOIN (or LEFT JOIN): This will return rows that have data in the left table (left of the JOIN keyword), even if there's no matching rows in the right table.
  • RIGHT OUTER JOIN (or RIGHT JOIN): This will return rows that have data in the right table (right of the JOIN keyword), even if there's no matching rows in the left table.
  • FULL OUTER JOIN (or FULL JOIN): This will return all rows, as long as there's matching data in one of the tables.
Syntax:

SELECT * FROM table_name1 Join_Name(INNER JOIN,LEFT JOIN,RIGHT JOIN,FULL JOIN) table_name2 ON table_name1.column_name = table_name2.column_name

Examples:

Source Tables


Left Table(Individual)
IdFirstNameLastNameUserName
1FredFlinstonefreddo
2HomerSimpsonhomey
3HomerBrownnotsofamous
4OzzyOzzbournesabbath
5HomerGainnoplacelike


Right Table(Publisher)
IndividualIdAccessLevel
1Administrator
2Contributor
3Contributor
4Contributor
10Administrator

1) Inner Join

SELECT * FROM Individual
INNER JOIN Publisher
ON Individual.IndividualId = Publisher.IndividualId
WHERE Individual.IndividualId = '2'

Result
IndividualId|FirstName|LastName|UserName|IndividualId|AccessLevel
2HomerSimpsonhomey2Contributor
2) Outer Join

     a)Left Outer Join
           
            SELECT * FROM Individual AS Ind
     LEFT JOIN Publisher AS Pub
     ON Ind.IndividualId = Pub.IndividualId

Result

IndividualId|FirstName|LastName|UserName|IndividualId|AccessLevel
1FredFlinstonefreddo1Administrator
2HomerSimpsonhomey2Contributor
3HomerBrownnotsofamous3Contributor
4OzzyOsbournesabbath4Contributor
5HomerGainnoplacelikeNULLNULL
   b)Right Outer Join
    SELECT * FROM Individual AS Ind
    RIGHT JOIN Publisher AS Pub 
    ON Ind.IndividualId = Pub.IndividualId

Result
IndividualId|FirstName|LastName|UserName|IndividualId|AccessLevel
1FredFlinstonefreddo1Administrator
2HomerSimpsonhomey2Contributor
3HomerBrownnotsofamous3Contributor
4OzzyOsbournesabbath4Contributor
NULLNULLNULLNULL10Administrator
3)Full Outer Join
SELECT * FROM Individual AS Ind
FULL JOIN Publisher AS Pub
ON Ind.IndividualId = Pub.IndividualId

Result

IndividualId|FirstName|LastName|UserName|IndividualId|AccessLevel
1FredFlinstonefreddo1Administrator
2HomerSimpsonhomey2Contributor
3HomerBrownnotsofamous3Contributor
4OzzyOsbournesabbath4Contributor
5HomerGainnoplacelikeNULLNULL
NULLNULLNULLNULL10Administrator

Thursday 22 December 2011


SharePoint 2010 Object Model

Microsoft has replaced the "12 hive" structure that we had in SharePoint 2007 with "14 Hive" structure in 2010.

It has apparently added four new folders to its hive.

The Folders are :
* Policy
* UserCode
* WebClients
* WebServices

See the Details at : 14 hive Directory structure



Some of the folders in 14 hive are :

Program Files\Common files\Microsoft Shared\Web Server Extensions\14 -
This directory is the installation directory for core SharePoint Server files.

Program Files\Common files\Microsoft Shared\Web Server Extensions\14\ADMISAPI -
This directory contains the soap services for Central Administration. If this directory is altered, remote site creation and other methods exposed in the service will not function correctly.

Program Files\Common files\Microsoft Shared\Web Server Extensions\14\CONFIG -
This directory contains files used to extend IIS Web sites with SharePoint Server. If this directory or its contents are altered, Web application provisioning will not function correctly.

Program Files\Common files\Microsoft Shared\Web Server Extensions\14\LOGS -
This directory contains setup and run-time tracing logs.

Other newly added folders are :

Program Files\Common files\Microsoft Shared\Web Server Extensions\Policy -


Program Files\Common files\Microsoft Shared\Web Server Extensions\UserCode -
This directory contains files used to support your sandboxed solutions.

Program Files\Common files\Microsoft Shared\Web Server Extensions\WebClients -
This directory contains files related to the new Client Object Model.

Program Files\Common files\Microsoft Shared\Web Server Extensions\WebServices -
This directory contains new wcf or .svc related files.

Note : You should rewrite and recompile any code that refers to files and resources in "12" Hive structure.For example, if you have redeployed all of your files into the "14" folder and emptied your "12" folder, any references to files under the "12" folder will not work.

In Sharepoint 2010 This is a step-by-step tutorial to learn using sharepoint 2010′s Server and client object model.-


Client Object Model is introduced in SharePoint 2010 which helps to developers to make things easier to develop the client side applications for SharePoint 2010. Client Object Model can run on the client machines (Where SharePoint is not installed) and communicate with the SharePoint server remotely. This is the great advantage for the SharePoint devs as they don't have to install SharePoint for development any more.


When we want to start coding with the Client OM there is a little difference between the server-side object model programming, as the class names are very similar to those used in classes so far (not a clear rule, but in general have been removed the letters “SP” from the names of classes in the client-side API). Some differences are visible in this table.



Server Object ModelClient Object Model
SPContextClientContext
SPWebWeb
SPListList
SPListCollectionListCollection
SPListItemListItem
SPFieldField

Assemblies to use in .NET client object model.
Custom .NET applications will need to add references to two assemblies in order to use the client object model. These two assemblies are found on the SharePoint server: c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI:
  • Microsoft.SharePoint.Client.dll (contains the client object model)
  • Microsoft.SharePoint.Client.Runtime.dll (handles all communication between the client and SharePoint server)
And the using statement will look like this:
  • using Microsoft.SharePoint.Client;
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Net;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Animation;  
using System.Windows.Shapes;  
using Microsoft.SharePoint.Client;  
  
namespace SP2010Silverlight_HelloWorld{  
    public partial class MainPage : UserControl  
    {  
        public MainPage()  
        {  
            InitializeComponent();  
        }  
  
        private ClientContext context = null;  
        private Web web = null;  
        private delegate void UpdateUIMethod();  
  
        private void btnLoadSite_Click(object sender, RoutedEventArgs e)  
        {  
            context = ClientContext.Current;  
            web = context.Web;  
            context.Load(web, w => w.Title, w => w.Description, w => w.ServerRelativeUrl);  
            context.ExecuteQueryAsync(OnSiteLoadSuccess, OnSiteLoadFailure);  
        }  
  
        private void OnSiteLoadSuccess(object sender, ClientRequestSucceededEventArgs e)  
        {  
            UpdateUIMethod updateUI = LoadSiteData;  
            this.Dispatcher.BeginInvoke(updateUI);  
        }  
        private void OnSiteLoadFailure(object sender, ClientRequestFailedEventArgs e)  
        {  
            MessageBox.Show("Request Failed: " + e.Message + ", Stack Trace:" + e.StackTrace);  
        }  
  
        private void LoadSiteData()  
        {  
            canvasLabels.Visibility = System.Windows.Visibility.Visible;  
            label2.Content = web.Title;  
            label4.Content = web.ServerRelativeUrl;  
            label6.Content = web.Description;  
        }  
    }  
}  



Server Object Model

Here we will look at how to use SharePoint API’s, LINQ, REST and SharePoint web service to extract data from sharepoint server.

Lets Start with using the API’s in Microsoft.SharePoint and Microsoft.SharePoint.Utilities namespaces.

Firstly, to work with SharePoint 2010 components, your code must first establish the site context or site collection context for requests that are made to the server.

Please Note : In SharePoint, the SPsite object also refered to as Site is actually a “Site Collection” object, not a website
and the SPweb object also refered to as “web” is a single site in the site collection.(It can be a top-level site collection site).
also, object of type SPWebApplication is a big boss object which has reference to the web applictaion that contains the site collection.

To get the reference to site context in your code use the recommended Microsoft.SharePoint.SPContext class and its members.

Lets look at how it is used

To get a reference to the site collection -

SPSite oSiteCollection = SPContext.Current.Site;

To get a reference to the current web site or web in the site collection -

SPWeb oWebSite = SPContext.Current.Web;

or

SPWeb oWebSite = SPControl.GetContextWeb(Context);

Note : if your are using Microsoft.SharePoint.SPContext class, you should not dispose any SPSite or SPWeb object obtained
by any of the above methods. The SharePoint Foundation runtime will dispose of them after page completion.

To get a reference to all the webs or sites in a site collection -

SPWeb oWebSite = SPContext.Current.Site.AllWebs["mySite1"];

oWebSite.Dispose();

Note : You should explicitly dispose of references to objects that are obtained through the AllWebs() or Openweb() property. You can also use using clause
like below to avoid calling the dispose off method and let sharepoint do this for you.

using can be something like

using (SPWeb oWebSite = SPContext.Current.Site.AllWebs["mySite1"]);
{

}

You can also use the Openweb() as below

using (SPWeb oWebSite = mySiteCollection.OpenWeb(“mySite1″))
{

}

Lets look at some other components of the SharePoint farm that you can get using SPContext

To get a reference to the current top-level server farm object -

SPFarm myFarm = SPContext.Current.Site.WebApplication.Farm;

To get a reference to the site collection database -

SPSite oSiteCollection = SPContext.Current.Site.CurrentDatabase

Lets look at some of the general code snippets

To return the collection of site collections in a SharePoint Web application -

SPWebApplication webApplication = SPContext.Current.Site.WebApplication;

using (SPSiteCollection siteCollections = webApplication.Sites)
{

foreach (SPSite siteCollection in siteCollections)
{
Label1.Text += siteCollection.Url + “
”;

siteCollection.Close();
}

}

Note : To runthe above code reference the Microsoft.SharePoint.Administration.SPWebApplication assembly in your code.

To return the collection of The all the Webs or sites within a site collection, including the top-level site and all subsites.

SPSite oSiteCollection = SPContext.Current.Site;
using(SPWebCollection collWebsite = oSiteCollection.AllWebs);
{

for (int i = 0; i < collWebsite.Count; i++)
{
using (SPWeb oWebsite = collWebsite[i])
{
SPListCollection collList = oWebsite.Lists;

for (int j = 0; j < collList.Count; j++)
{
Label1.Text += SPEncode.HtmlEncode(collWebsite[i].Title) + ” ”
+ SPEncode.HtmlEncode(collList[j].Title) + “
”;
}
}}}

To return the all the subsites and lists of the current site

using (SPWeb oWebSite = mySiteCollection.OpenWeb())
{

using(SPWebCollection subSites = oWebsite.Webs)
{

foreach (SPWeb subSite in subSites)
{
Label1.Text += SPEncode.HtmlEncode(subSite.Title) + “
”;

SPListCollection collList = subSite.Lists;

foreach (SPList oList in collList)
{
Label1.Text += SPEncode.HtmlEncode(oList.Title) + ” ” +
oList.ItemCount.ToString() + “
”;

}subSite.Close();
}
}}