czwartek, 14 marca 2013

Powershell a sharepoint

System Windows, podobnie jak system Linux posiada własny odpowiednik konsoli (terminala) administratora, w którym można uruchamiać polecenia oraz skrypty, za pomocą których administrator posiada pełną władzę nad systemem. W systemie Windows, interpreter poleceń wykorzystywany przez konsolę, oraz powiązany z nim język nazywa się Windows_PowerShell.

W teorii "Powershell" zapewnia administratorowi wszystkie dostępne opcje administracyjne, które może on wykonać zarówno z poziomu linii komend, jak i poprzez przygotowane wcześniej skrypty. Pełny i praktyczny poradnik, od czego warto zacząć podczas nauki obsługi "Powershella", można znaleźć jako odpowiedź na jedno z pytań, zamieszczonych na forum stackoverflow.com.

Podczas pisania skryptów, dobrze jest mieć "kolorowanie składni", co zapewni nam Powergui.

Skoro już mamy za sobą wstęp teoretyczny, narzędzie do kolorowania składni (aczkolwiek same skrypty zawsze możemy pisać w notatniku), oraz info, gdzie możemy zdobyć więcej praktycznych informacji o samym PowerShellu możemy przejść do analizowania interesującego nas zagadnienia czyli modyfikacja witryny sharepoint za pomocą skryptu powershell.
Utwórzmy wiec skrypt, który będzie pobierał 3 parametry (adres witryny, nazwę tabeli, nazwę pola), a nast. zmieńmy jedno z jego właściwości, np. wymagalność tego pola.

param
(
      [string] $portalURL = $(Throw "Missing 'portalURL' parameter"), #required parameter
      [string] $listName = $(Throw "Missing 'listName' parameter"), #required parameter
      [string] $fieldName = $(Throw "Missing 'fieldName' parameter") #required parameter
)

#komentarze pisze się z haszem na początku

$web = Get-SPWeb $portalURL;
$list = $web.Lists[$listName];
$field = $list.Fields.GetFieldByInternalName($fieldName);
[bool]$fvalue = $field.Required;

if ($fvalue) {
      $field.Required = 0;
      $field.Update();
      $list.Update();
} else {
      $field.Required = 1;
      $field.Update();
      $list.Update();
}
$web.Dispose();
 Jak widać, skrypt jest bardzo prosty. Na samym początku podajemy parametry, wykorzystywane przez skrypt  oraz określamy ich typ (sekcja 'param'). Nast. pobieramy SpWeba, listę SpList i pole SpField, po czym sprawdzamy jego wartość, a nast. zmieniamy jego wartości i wykonujemy update. Na sam koniec pobranego SPWeb'a musimy disposować. Dla programisty sharepoint ten kod wyda się dziwnie znajomy (tylko delikatnie nieco inna składnia).
To co jest WAŻNE, to aby zapisać skrypt w pliku tekstowym z rozszerzeniem *.ps1.

Wywołanie tego kodu, nast. poprzez: "Start->Microsoft Sharepoint 2010 Products -> Sharepoint 2010 Managment Shell"






A nast. w konsoli odpalamy utworzony przez nas skrypt wg. schematu: .\nazwaSkryptu.ps1 -parametrNr1 "ParametrNr1" -ParametrNr2 "ParametrNr2 -ParametrNr3 "ParametrNr3"

W przypadku większej ilości parametrów, zamiast podawać wszystkie parametry z konsoli, lepiej jest utworzyć osobny plik .csv z parametrami i umieścić go w tym samym katalogu co skrypt, a nast. wczytać jego zawartość wewnątrz skryptu.

P.S. Inny, bardziej zaawansowany przykład wykorzystujący power shell w kontekście sharepointa.






czwartek, 7 marca 2013

Build Version Increment

Jednym z bardzo prostych, a zarazem przydatnych pluginów do Visual Studio jest dostępny za darmo Build version increment. Plug in służy do automatycznego zwięszania nr. wersji znajdującego się w pliku AssemblyInfo.cs.

Ważne, aby w rozwiązaniach typu sharepoint inkrementować tylko i wyłącznie "AssemblyFileVersion" (natomiast "AssemblyVersion" musi pozostać nie zmienione). W przypadku normalnych rozwiązań asp.net wolno nam modyfikować oba parametry.

Po zainstalowaniu plug-ina, uruchamiamy go z opcji dostępnych w Visual Studio. Zakładka "Tools"->"Build Version Increment Settings", a nast. w popupie wybieramy interesujący nas projekt, w którym ustawiamy zasady inkrementowania. Osobiście preferuję ustawić opcję inkrementowania w oparciu o build, a numer rewizji w oparciu o "rok, nr. dnia w roku".
Przykładowe skonfigurowane opcje wyglądają tak:




piątek, 1 marca 2013

Pinterest / Blocksit layout

Jednym z najnowszych "krzyków mody", jest wyświetlanie newsów na stronie internetowej w "pseudo-tabelaryczny" sposób. Jest to sposób, który na pierwszy rzut oka przypomina nieco tabelę, ale nią nie jest, czyli dane ustawione są w kolumny, ale wysokość wierszy jest różna i zależna od ilości contentu (wysokość zdjęcia, ilość i długość komentarzy do zdjęcia itp.). Dodatkowo, resizując stronę (zmniejszając lub zwiększając okno przeglądarki) newsy się przestawiają w swojej "pseudo tabeli". Jako pierwsze (ale mogę się mylić), taki layout graficzny zastosowało na swojej stronie https://pinterest.com/, dlatego nazwałem ten layout "pinterest layout".

Teoretycznie, można by było zalogować się na stronę https://pinterest.com/ i spróbować przekopiować ich layout, ale takie rozwiązanie nie było by ani zbyt grzeczne, ani zbyt moralnie poprawne. Na szczęście dzięki www.google.com udało mi się znaleźć stronę, która zagregowała 'know how", czyli link do wtfdiary.com, na którym jest 6 'know how to do pinterest loyout'.

Mi osobiście najbardziej przypadł do gustu BlocksIt.js dlatego w dalszej części skupię się właśnie na tym rozwiązaniu. Jego zalety:
- to łatwość i prostota obsługi,
- ładny wygląd zewnętrzny,
- przystępny tutorial (zawierający 2 projekty demo)
- licencja  GNU GPL 2.0

Samo rozwiązanie nie jest niczym innym, jak wykorzystaniem biblioteki jQuery oraz dołączeniem do niego odpowiedniego jQuery plugin. Do tego dochodzą nam style CSS (ostylowanie naszego contentu) oraz kilka prostych skrytpów javascript (m.in. wykorzystywanych podczas resizowania strony).

To co potrzebujemy to pobrać najnowszą wersję biblioteki query oraz plik zip z demami blocksit

Moje rozwiązanie, które tutaj przedstawię, w dużej mierze opiera się na demie, które można pobrać z linku powyżej i jest to jedynie dostosowanie tego dema do aplikacji typu .net (asp.net / sharepoint).

Aby wykorzystać 'Blocksit' tworzymy nową stronę .aspx (może to być kontrolka .ascx), następnie do projektu dodajemy odpowiednie pliki:
- jquery-1.9.1.min (najnowsza wersja jquery w dniu 2013-03-01)
- blocksit.min (znajduje się w pliku z demem blocksit  - \blocksit-js\blocksit\demo2)
- style.css (znajduje się w pliku z demem blocksit - \blocksit-js\blocksit\demo2)
- zchpitblocksitdemo.js  (nasz plik ze skryptami, jakie będziemy utuchamiać na stronie)

Standardowo te skrypty były na stronie z demem, ale ja wolałem je przenieść do osobnego pliku .js i wyglądają one następująco:

$(document).ready(function () {
    //vendor script
    $('#header')
    .css({ 'top': -50 })
    .delay(1000)
    .animate({ 'top': 0 }, 800);

    $('#footer')
    .css({ 'bottom': -15 })
    .delay(1000)
    .animate({ 'bottom': 0 }, 800);

    //blocksit define
    $(window).load(function () {
        $('#container').BlocksIt({
            numOfCol: 5,
            offsetX: 8,
            offsetY: 8,
            blockElement: '.grid'
        });
    });

    //window resize
    var currentWidth = 1100;
    $(window).resize(function () {
        var winWidth = $(window).width();
        var conWidth;
        if (winWidth < 660) {
            conWidth = 440;
            col = 2
        } else if (winWidth < 880) {
            conWidth = 660;
            col = 3
        } else if (winWidth < 1100) {
            conWidth = 880;
            col = 4;
        } else {
            conWidth = 1100;
            col = 5;
        }

        if (conWidth != currentWidth) {
            currentWidth = conWidth;
            $('#container').width(conWidth);
            $('#container').BlocksIt({
                numOfCol: col,
                offsetX: 8,
                offsetY: 8
            });
        }
    });
});
 Ok. Przejdźmy zatem do omówienia najważniejszej części, czyli kodu strony .aspx / kontrolki .ascx:

Aby uzyskać ten layout, teoretycznie nie potrzebujemy żadnego 'code behind' i wystarczy nam czysty html, który docelowo powinien wyglądać podobnie jak na stronie z dema, czyli mniej więcej tak:

<link rel="stylesheet" href="/_layouts/style.css" type="text/css" />
<script src="/_layouts/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="/_layouts/blocksit.min.js" type="text/javascript"></script>
<script src="/_layouts//zchpitblocksitdemo.js" type="text/javascript"></script>
<div id="container">
    <div class="grid">
        <div class="imgholder">
            <img src="http://www.inwebson.com/demo/blocksit-js/demo2/images/img26.jpg" />
        </div>
        <strong>Bridge to Heaven</strong>
        <p>Where is the bridge lead to?</p>
        <div class="meta">by SigitEko</div>
    </div>
    <div class="grid">
        <div class="imgholder">
            <img src="http://www.inwebson.com/demo/blocksit-js/demo2/images/img15.jpg" />
        </div>
        <strong>Autumn</strong>
        <p>The fall of the tree...</p>
        <div class="meta">by Lars van de Goor</div>
    </div>
</div>
Aby jednak uzyskać, w pełni dynamicznie generowany przez nas layout, skorzystamy z kontrolki literala, czyli nasz kod html będzie wyglądał tak:

<link rel="stylesheet" href="/_layouts/style.css" type="text/css" />
<script src="/_layouts/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="/_layouts/blocksit.min.js" type="text/javascript"></script>
<script src="/_layouts//zchpitblocksitdemo.js" type="text/javascript"></script>

<div id="container">
    <asp:Literal runat="server" ID="ltrGrid" ></asp:Literal>
</div>
W tym przypadku, będziemy potrzebowali stworzyć 'code behind', który w najprostszym możliwym przypadku będzie wyglądał tak:

        protected void Page_Load(object sender, EventArgs e)
        {
            SetLiteralGrid();
        }
        private void SetLiteralGrid()
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("<div class='grid'>");
            sb.AppendLine("<div class='imgholder'>");
            sb.AppendLine("<img src='http://www.inwebson.com/demo/blocksit-js/demo2/images/img27.jpg' />");
            sb.AppendLine("</div>");
            sb.AppendLine("<strong>Sunset Lake</strong>");
            sb.AppendLine("<p>A peaceful sunset view...</p>");
            sb.AppendLine("<div class='meta'>by j osborn</div>");
            sb.AppendLine("</div>");

            ltrGrid.Text = sb.ToString();
        }
 Oczywiście w realnych scenariuszach interesuje nas wypełnienie contentem pełnej strony (a nie tylko pojedyńczego newsa), ale wtedy w 'code behind' wystarczy zwyczajnie wcześniej pobrać potrzebne dane i wrzucić je do StringBuildera za pomocą pętli.



niedziela, 24 lutego 2013

SPMonitoredScope, czyli sprawdzanie wydajności w aplikacjach sharepoint

Tematem aktualnego wpisu jest sposób, na sprawdzenie wydajności naszej aplikacji sharepoint, a dokładniej czasu jaki jest potrzebny, aby wyświetlić naszą aplikację w przeglądarce internetowej. Ponieważ temat wydajności w sharpoint jest bardzo obszerny, a z problemem zwiększania wydajności aplikacji sharepoint spotkał się niemal każdy doświadczony programista, dobrze jest mieć jakieś narzędzie, które zautomatyzuje proces sprawdzania wyników. Narzędzie, dzięki któremu będziemy wiedzieli, jaki dokładnie wpływ na wydajność mają zmiany w kodzie,  które wprowadzamy podczas procesu optymalizacji.

Tutaj z pomocą przychodzi nam SPMonitoredScope, które jest darmowym narzędziem służącym do lokalizacji wydajnościowego "wąskiego gardła". Jedynym ograniczeniem, jakie posiada SPMonitoredScope są rozwiązania typu "sandbox" ("piaskownica"), w których SPMonitoredScope nie działa.

Sposób wykorzystania SPMonitoredScope jest bardzo prosty:
Najpierw odpalamy konsolę (Start -> wyszukaj programy -> cmd.exe). W konsoli natomiast uruchamiamy program stsadm (ja uruchamiałem go z roota, do którego przechodzimy za pomocą komendy "cd..").  Dostępne komendy, możemy znaleźć na MSDN pod tym linkiem.  Osobiście preferuję opcję "on demand", czyli:

stsadm -o setproperty -pn developer-dashboard -pv ondemand 
Wyłączenie SPMonitoredScope następuje poprzez wpisanie w konsoli:

stsadm -o setproperty -pn developer-dashboard -pv off

Sprawdzanie konkretnych, wybranych partii kodu, pod kątem wydajności następuje, poprzez wykonanie naszego kodu wewnątrz "using-a".

using (new SPMonitoredScope("CallMethod1 Monitored Scope"))
{
    //TODO: tutaj będzie kod, który chcemy przetestować.
}
 
Wyniki sprawdzamy w przeglądarce, w nowej zakładce, która się pojawi, gdy tylko będziemy mieli aktywny SPMonitoredScope. Co do samych wyników, to dobrze jest stronę załadować przynajmniej kilka razy i nast. wyciągnąć średnią.

P.S. Link do bloga Tobiasa Zimmergrena, którego wpis stał stał się inspiracją dla mojego wpisu.

wtorek, 15 stycznia 2013

jQuery w Web Partach - zagrożenie wielokrotnego importu pliku jQuery

Jak każdy wie, aby móc wykorzystać bibliotekę jQuery w aplikachach webowych opartych o technologię .NET najpierw trzeba poinformować kompilator, że zamierzamy wykorzystać tą bibliotekę. Podobnie jak innymi plikami .js (javascript) przed pierwszym wykorzystaniem należy podać jej nazwę i miejce w którym się znajduje. Lokalizacja może być lokalna (zazwyczaj) lub zewnętrzna (np. do serwera projektu jQuery).

Zazwyczaj taka informacja znajduje się w nagłówku strony aspx (ewentualnie kontrolki ascx) na stronie z częścią HTML i wygląda następująco:
<script src="/_layouts/Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>
Aby biblioteka jQuery działa poprawnie, na jednej stronie, może znajdować się tylko jedna deklaracja importująca plik z biblioteką jQuery. O ile w przypadku standardowych stron ASP.NET taka, pojedyncza deklaracja jest standardem, o tyle w przypadku Web Partów, które same w sobie są oddzielnymi aplikacjami, umieszczanymi niezależnie od siebie często występują konflikty importu. Każdy z web partów samodzielnie dodaje jQuery do strony, co w przypadku umieszczenia kilku takich web partów z deklaracjami importu na jednej stronie powoduje błędy w działaniu javascriptu na tej stronie.

Rozwiązanie polega na tym, aby plik z biblioteką jQuery wczytywać po stronie serwera w instrukcji warunkowej:

        protected void Page_Init(object sender, EventArgs e)
        {
            var cs = Page.ClientScript;

            if (!cs.IsClientScriptIncludeRegistered("jquery-1.8.2.min.js"))
                cs.RegisterClientScriptInclude("jquery-1.8.2.min.js",
                "/_layouts/Scripts/jquery-1.8.2.min.js");
        }
W podobny sposób możemy wczytać bibliotekę jQuery, gdy nie jest wczytana w postaci kodu javascript umieszczonego na stronie html:


<script type="text/javascript">

       var jQueryScriptOutputted = false;
       function initJQuery() {

             //if the jQuery object isn't available
             if (typeof (jQuery) == 'undefined') {

                    if (!jQueryScriptOutputted) {
                           //only output the script once..
                           jQueryScriptOutputted = true;

                           //output the script
                           document.write("<scr" + "ipt type=\"text/javascript\" src=\"/_layouts/Scripts/jquery-1.8.2.min.js\"></scr" + "ipt>");
                    }
                    setTimeout("initJQuery()", 50);
             }

       }
       initJQuery();

</script>

Takie  rozwiązanie pozwala nam na sytuację, aby wszystkie web party na stronie zaimportowały plik z biblioteką jQuery w wersji 1.8.2 tylko raz. Takie rozwiązanie nie jest jednak do końca idealne, ponieważ wymaga od nas, stosowania biblioteki w jednej i tej samej (najnowszej?) wersji we wszystkich web partach, a w przypadku umieszczenia na stronie web parta wymagającego nowszej wersji biblioteki jQuery przekompilowania i zaktualizowania wersji biblioteki w już istniejących web partach. Gdy tylko poznam sposób, w jaki można obejść te niedogodności postaram się tą informację tutaj umieścić.

niedziela, 25 listopada 2012

Metoda jQuery.ajax()

Jedną z największych zalet jQuery, jakie do tej pory miałem okazję wykorzystać, jest asynchroniczne odwołanie się kodu napisanego w javascript do metod, napisanych w C#. W najprostszej postaci (metoda javascript -> metoda c#) służy do tego jQuery.ajax.

Jak to działa?
Na stronie c# piszemy statyczną funkcję, którą oznaczamy atrybutem "Web Method", ktora w najprostszej postaci będzie wyglądać tak:

    public partial class WebMethodCommonHelper : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        [WebMethod]
        public static string GetActualDateTime()
        {
            return DateTime.Now.ToShortTimeString();
        }
    }

Odwołanie się do tej funkcji za pomocą javascriptu będzie natomiast wyglądało w ten sposób:

function GetDateTimeFromPage() {
  $.ajax({
                        type: 'POST',
                        url: 'WebMethodCommonHelper.aspx/GetActualDateTime',
                        data: JSON.stringify({ }),
                        contentType: 'application/json; charset=utf-8',
                        dataType: 'json',
                        success: function (data) {
                            var dateTimeFromPage =  data.d.Value
                            setDateTime(dateTimeFromPage);
                        }
                    });
}

function setDateTime(dateTimeToSet)
{
//TODO: tutaj wykorzystujemy date, pobrana ze strony
}

Krótki opis, kodu, który widzimy powyżej:
a) Tworzymy stronę aspx, na której umieszamy statyczną web methodę z atrybutem [Web Method]. To ta metoda jest odpowiedzialna za "część serwerową".
b) po stronie javascriptu tworzmy 2 metody, o nazwach "GetDateTimeFromPage()" oraz "setDateTime". Jedna będzie odpowiedzialna, za pobranie danych z metody c# o nazwie "GetActualDateTime", natomiast druga będzie wykorzystywała te dane bezpośrednio na stronie ( "setDateTime").
 Metoda $.ajax w najprostszej formie, pobiera 4 parametry:
- type: 'POST' -> tryb pracy protokołu http (POST lub GET)
- url - adres naszej web methody, poprzedzony adresem do strony aspx na której się znajduje (jeżeli strona jest w odpowiednim katalogu, jak to często bywa np. w aplikacjach sharpoint, to wtedy adres może wyglądać np tak: '/_layouts/Branding/Common/WebMethodCommonHelper.aspx/GetActualDateTime'
- data - parametry, jakie przekazujemy do web methody z poziomu javascriptu (zostaną opisane później przy bardziej zaawansowanym przypadku)
-contentType: 'application/json; charset=utf-8' - kodowanie (tego zazwyczaj nie zmieniamy)
- dataType: 'json' - rodzaj danych (tego zazwyczaj nie zmieniamy)
- success: function (data) {
                           var dateTimeFromPage =  data.d;
                            setDateTime(dateTimeFromPage);
                        }
- fragment kodu, odpowiedzialny, za to, co powinno się zadziać, w przypadku, gdy metoda wykona się poprawnie. W naszym przypadku, tworzymy zmienną  'dateTimeFromPage' i przypisujemy do niej wartości, jakie zwróciła nam nasza 'Web Method', a nast. przekazujemy tą wartość do metody pomocniczej, która wykorzysta ją dalej w naszym kodzie.
Co ważne, dane które dostajemy z powrotem to: "data.d". Dla typów wbudowanych, np. 'int32', 'string' itp. dane zwracane są jako "data.d". Dla klas, należy się odwołać to zmiennych wewnątrz klasy (jeżeli klasa, którą zwracamy ma publiczną własciwość o nazie "wartosc" to odwołamy się do niej poprzez var wartosc = data.d.wartosc").

Ok, skoro najprostszy przykład mamy już za sobą, to teraz spróbujmy jakiś bardziej zaawansowany przykład, np. z wykorzystaniem sharepointa:
a) kod javasctipt

function getCurrency()
{
                    var urlLink = window.location.protocol + "//" + window.location.host + _spPageContextInfo.siteServerRelativeUrl; //_spPageContextInfo.webServerRelativeUrl;
                    $.ajax({
                        type: 'POST',
                        url: '/_layouts/Branding/Common/WebMethodCommonHelper.aspx/GetCurrency',
                        data: JSON.stringify({ url: urlLink }),
                        contentType: 'application/json; charset=utf-8',
                        dataType: 'json',
                        success: function (data) {
                            var currency = parseFloat(data.d.Value);
                            setCurrency(currency);
                        }
                    });
}
function setCurrency(currency)
{
 //TODO: tutaj ustawimy przelicznik
}

b) kod c#
     public partial class WebMethodCommonHelper : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        [WebMethod]
        public static CurrencyHelper GetCurrency(string url)
        {
            using (SPSite oSiteCollection = new SPSite(url))
            {
                using (SPWeb web = oSiteCollection.OpenWeb())
                {
                    double rate = 4.56; //CurrencyHelper.GetRate(web);
                    CurrencyHelper lineHelper = new CurrencyHelper() { Value = rate, HfName = "Rate" };
                    return lineHelper;
                }
            }
        }
        [Serializable]
        public class CurrencyHelper
        {
            public string HfName { get; set; }
            public double Value { get; set; }
        }
}

Ok. Przejdźmy do analizy kodu:
Tym razem najpierw tworzymy metodę javascript. Ponieważ będziemy wykorzystywać sharpointa, bedziemy potrzebowali utworzyć obiekty SpSite oraz SpWeb. W tym celu, wykorzystamy zmienne shapointowe dostępne w języku javascript (tylko dla sharepoint 2010 lub nowszego). Mam na myśli:
_spPageContextInfo.siteServerRelativeUrl - zwraca adres SpSite
_spPageContextInfo.webServerRelativeUrl - zwraca adres SpWeb
Z pomocą tych zmiennych tworzymy pełny adres http, strony jaka nas interesuje (w zależności od tego, na której witrynie znajduje się lista do której zamierzamy się odwołać, czy na bierzącej witrynie, czy na 'root webie').
Mają odpowiedni adres http przekazujemy go do metody jQuery.ajax jako parametr url (ważne, aby nazwa parametru w jQuery.ajax oraz metodzie c# były takie same).
Jako rezultat otrzymujemy klasę napisaną przez użytkownika, więc w ceku odczytania wartości odwołujemy się do jej publicznej właściwości (Value), którą nast. przekazujemy do metody docelowej.

W przypadku kodu c#, ponownie tworzymy metodę statyczna z adrybutem "Web Method", oraz parametrem "url". Wykorzystując parametr, otwieramy SpSite oraz SpWeb'a, a nast. wykonujemy na nim interesujące nas operacje. Jako wynik, zwracamy obiekt stworzonej przez nas klasy CurrencyHelper.


p.s. Należy pamiętać, o dołączeniu odpowiednich referencji, tj. pliku z biblioteką "jQuery" po stronie javascriptu, oraz odpowiednich namespece po stronie c#.

sobota, 27 października 2012

Podniesienie uprawnień sharepoint

Bardzo często podczas pisania programów w technologii sharepoint (np. Visual Web Part) zdarza się konieczność czasowego podniesienia uprawnień użytkownika dla wykonania konkretnej czynności. Przykładem, mogą być uprawnienia do listy. Normalny użytkownik posiada uprawnienia tylko do odczytu elementów listy (elementy listy sharpoint są podobne do rekordów w bazie danych), a co za tym idzie nie posiada uprawnień do tworzenia/modyfikowania elementów listy. Aby taki użytkownik mógł utworzyć/zmodyfikować element na takiej liście za pomocą napisanej przez nas aplikacji (np. mógł utworzyć nową 'fakturę' za pomocą aplikacji, do zarządzania fakturami, opartej na listach sharepoint), trzeba czasowo podnieść jego uprawnienia. Podniesienie uprawnień w kodzie C# w praktyce oznacza pobranie SPSite z podwyższonymi uprawnieniami (tzw. SuperSite).
Przykład:



SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite
superSite = new SPSite(SPContext.Current.Site.ID))
    {
        using (SPWeb
superWeb = superSite.OpenWeb(SPContext.Current.Web.ID))
        {
            // Your code here
        }
    }
});
 
Podczas pobierania SuperSite lepiej jest jednak wykorzystać wrapper, w postaci klasy SPSecurityHelper, zademonstrowanej przez Dana Larsona na jego tech-blogu
Klasa SPSecurityHelper:

using Microsoft.SharePoint;


    /// <summary>A class for working with elevated privilege</summary>
    public static class SPSecurityHelper
    {
        /// <summary>Returns an elevated site</summary>
        /// <param name="theSite">
        /// The site that you want an elevated instance of.
        /// You must dispose of this object unless it is part of SPContext.Current.
        /// </param>
        /// <returns>An elevated site context.</returns>
        /// <remarks>Be sure to dispose of objects created from this method.</remarks>
        public static SPSite GetElevatedSite(SPSite theSite)
        {
            var sysToken = GetSystemToken(theSite);
            return new SPSite(theSite.ID, sysToken);
        }

        /// <summary>Gets a UserToken for the system account.</summary>
        /// <param name="site"></param>
        /// <returns>A usertoken for the system account user./returns>
        /// <remarks>Use this token to impersonate the system account</remarks>
        public static SPUserToken GetSystemToken(SPSite site)
        {
            site.
CatchAccessDeniedException = false;
            try
            {
                return site.SystemAccount.UserToken;
            }
            catch (UnauthorizedAccessException)
            {
                SPUserToken sysToken = null;

                // Only use runwithelevated to grab the system user token.
                SPSecurity.RunWithElevatedPrivileges(
                    delegate()
                    {
                        using (SPSite lolcatKiller = new SPSite(site.ID))
                        {
                            sysToken = lolcatKiller.SystemAccount.UserToken;
                        }
                    }
                );
                return sysToken;
            }
        }
    }
 Wykorzystanie klasy SPSecurityHelper:

 using (SPSite superSite = SPSecurityHelper.GetElevatedSite(SPContext.Current.Site))
{
    using (SPWeb superWeb = superSite.OpenWeb(SPContext.Current.Web.ID))
    {
               // Your code here
    }
}

 Sposób wykorzystania jest bardzo prosty, tzn. do klasy SPSecurityHelper przekazujemy obiekt zwykłego SpSite, natomiast z powrotem dostajemy obiekt tego samego SpSite z podwyższonymi uprawnieniami. Dzięki wykorzystaniu klasy SPSecurityHelper kod jest krótszy oraz lepszy jakościowo.