Ten konkretny wpis, to zwykły link do innego bloga, ale zostawiam to tutaj, ponieważ ten blog jest również moim prywatnym notatnikiem.
heblobfarm.wordpress.com <-> sharepoint-2013-ui-log-in-as-a-different-user/
Pokazywanie postów oznaczonych etykietą sharepoint. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą sharepoint. Pokaż wszystkie posty
niedziela, 28 lipca 2013
Layouts folder location in sharepoint 2010/2013
No i stało. Oficjalnie wyszedł długo oczekiwany następca sharepointa 2010, czyli sharepoint 2013. Zapewne posiada wiele ciekawych funkcji i udogodnień, natomiast pierwszą rzeczą, która rzuca się w oczy, to fakt, że projekty napisane w sharepoint 2010, które planujemy wdrożyć dla sharepointa 2013 powinny być skonwertowane na typ projektu 'sharepoint 2013'. Projekt po takiej konwersji nie może zostać użyty w 'sharepoint 2010'. W praktyce jesteśmy więc zmuszeni do stworzenia dwóch projektów obok siebie i wymuszenia, aby oba projekty posiadały wspólne pliki .cs (niestety, ale inne pliki, czyli aspx, ascx, css, js, xml, png, i cała reszta plików umieszczana zazwyczaj w 'layouts' musi być zdublowana i znajdować się w obu projektach).
Gdyby jednak tego było mało, to folder layouts w nowym sharepoincie nie nazywa się 'layouts/' (tak jak to było w sharepoint 2010), tylko... 'layouts/15/".
Na szczęście jest sposób, aby można było wykorzystywać te same pliki .cs w obu projektach. Oto on, czyli klasa UrlHelper:
W praktyce, wszędzie, gdzie odwołujemy się do katalogów związanych z 'layouts', zamiast wpisywać stringi, powinniśmy wykorzystać metodę klasy UrlHelper.
Gdyby jednak tego było mało, to folder layouts w nowym sharepoincie nie nazywa się 'layouts/' (tak jak to było w sharepoint 2010), tylko... 'layouts/15/".
Na szczęście jest sposób, aby można było wykorzystywać te same pliki .cs w obu projektach. Oto on, czyli klasa UrlHelper:
public class UrlHelper
{
public static string LayoutsUrl
{
get
{
PropertyInfo pi = typeof(SPUtility).GetProperty(
"ContextLayoutsFolder", BindingFlags.Public | BindingFlags.Static);
if (pi == null)
return "/_layouts/";
else
return String.Format("/{0}/", pi.GetValue(null, null).ToString());
}
}
public static string ImagesUrl
{
get
{
PropertyInfo pi = typeof(SPUtility).GetProperty("ContextImagesRoot", BindingFlags.Public | BindingFlags.Static);
if (pi == null)
return "/_layouts/images/";
else
return String.Format("{0}", pi.GetValue(null, null).ToString());
}
}
public static string ControlTemplatesUrl
{
get
{
PropertyInfo pi = typeof(SPUtility).GetProperty(" ContextControlTemplatesFolder" , BindingFlags.Public | BindingFlags.Static);
if (pi == null)
return "/_CONTROLTEMPLATES/";
else
return String.Format("/{0}/", pi.GetValue(null, null).ToString());
}
}
}
W praktyce, wszędzie, gdzie odwołujemy się do katalogów związanych z 'layouts', zamiast wpisywać stringi, powinniśmy wykorzystać metodę klasy UrlHelper.
sobota, 6 lipca 2013
LoggingService, czyli logowanie błędów w Sharepoint 2010
W pracy programisty bardzo ważne jest logowanie błędów. Gorsze od nie
logowania błędów jest tylko błędne logowanie błędów (np. poprzez
napisanie własnego logera, co niestety miałem już okazję widzieć w
praktyce). Aby poprawnie logować błędy, najlepiej użyć jakiegoś gotowego
rozwiązania.
W przypadku aplikacji typu sharepoint nie powinniśmy używać zewnętrznych bibliotek. Jak opisuje to avishnyakov za pomocą spdevlab.com:
Dlatego w rozwiązaniach typu sharepoint 2010 dużo lepszym rozwiązaniem jest napisanie/skopiowanie klasy LoggingService dziedziczącej po SPDiagnosticsServiceBase.
Takie rozwiązanie znajdziemy w wielu miejscach w sieci, więc wydaje się ono być najlepsze.
Sama klasa, wygląda następująco:
Przydatne linki:
wpis Avishnyakov'a na spdevlab.com
wpis na blogu Waldka Mastykarza
wpis na blogu Jurgena Baurle
W przypadku aplikacji typu sharepoint nie powinniśmy używać zewnętrznych bibliotek. Jak opisuje to avishnyakov za pomocą spdevlab.com:
Suggestion #0 – Do not use 3rd part logging framework
Even if you stick to log4net, NLog, EventLog or System.Diagnostic.Trace, or trying to invent your own wheel, then DO NOT EVER USE THAT STUFF AGAIN.
SharePoint has its own logging system called “Unified Logging System (ULS)“. If you still wonder why would you use ULS instead your lovely logging framework, then consider the following facts:
- ULS is used by SharePoint, so if you used 3rd part logging, you would need to consolidate logs from few different sources
- ULS can be easily configured from Central Administration as well as by PowerShell
- ULS can write to Windows Event Log without elevated privileges (!)
- ULS shrinks text log files on the hard drives (!)
- ULS does not require web.config changes/modifications (!). That’s quite important concern for multi-server farm
- SharePoint can aggregate ULS log (and not just logs..) from multiple servers to the logging data base (Usage and Health Data Collection Service Application)
Dlatego w rozwiązaniach typu sharepoint 2010 dużo lepszym rozwiązaniem jest napisanie/skopiowanie klasy LoggingService dziedziczącej po SPDiagnosticsServiceBase.
Takie rozwiązanie znajdziemy w wielu miejscach w sieci, więc wydaje się ono być najlepsze.
Sama klasa, wygląda następująco:
natomiast jej użycie wygląda tak:publicclassLoggingService : SPDiagnosticsServiceBase{publicstaticstringDiagnosticAreaName ="My";privatestaticLoggingService _Current;publicstaticLoggingService Current{get{if(_Current ==null){_Current =newLoggingService();}return_Current;}}privateLoggingService():base("My Logging Service", SPFarm.Local){}protectedoverrideIEnumerable<SPDiagnosticsArea> ProvideAreas(){List<SPDiagnosticsArea> areas =newList<SPDiagnosticsArea>{newSPDiagnosticsArea(DiagnosticAreaName,newList<SPDiagnosticsCategory>{newSPDiagnosticsCategory("WebParts", TraceSeverity.Unexpected, EventSeverity.Error)})};returnareas;}publicstaticvoidLogError(stringcategoryName,stringerrorMessage){SPDiagnosticsCategory category = LoggingService.Current.Areas[DiagnosticAreaName].Categories[categoryName];LoggingService.Current.WriteTrace(0, category, TraceSeverity.Unexpected, errorMessage);}}
Do przeglądania logów polecam program ULSViewer dostępny na mocy licencji MICROSOFT PUBLIC LICENSE (Ms-PL)LoggingService.LogError("WebParts", ex.ToString);
Przydatne linki:
wpis Avishnyakov'a na spdevlab.com
wpis na blogu Waldka Mastykarza
wpis na blogu Jurgena Baurle
poniedziałek, 10 czerwca 2013
Wstep do kontrolek DevExpress
Jak zapewne wielu programistów wie, jedną z najgorszych rzeczy, jakie można robić będąc programistą, to wymyślanie koła od nowa. Aby tego nie robić, powstały frameworki (np. .NET Framework), wzorce projektowe, rozszerzalne biblioteki (np. jQuery, pdf-libraries) i wiele, wiele innych. Część udostępnianych na darmowych licencjach (np. Licencja X11 (MIT)), a część na licencjach komercyjnych.
Takim przykładem komercyjnego oprogramowania, a dokładniej kontrolek wykorzystywanych w środowisku '.NET' są kontrolki firmy DevExpress. Kontrolki, które nie są tanie (link do cennika) i kupowane są 'per developer'. Tak, moi mili. Te ceny, które są tam umieszczone dotyczą ceny, za możliwość wykorzystywania oprogramowania przez pojedyńczego programistę i kształtują się od $900 za najmniejszy pakiet (np. dla programisty asp.net) do pakietu full ($2199 per programista).
Co za tą cenę dostajemy?
Hmmm, chyba najlepsze kontrolki programistyczne, jakie można dostać w .net ;)
Programując z ich wykorzystaniem programista naprawdę zyskuję sporą przewagę nad rozwiązaniami darmowymi, a co za tym idzie programowanie idzie szybciej, sprawniej, jest ładniejsze i zawiera mniej błędów. Przede wszystkim uzyskujemy kod wykorzystywany i sprawdzony przez miliony ludzi. Firma devExpress wygrywała ze swoimi kontrolkami wiele międzynarodowych konkursów, przez co jej popularność rosła, a wraz z nią ilość ludzi którzy bezpośrednio (developerzy) oraz pośrednio (użytkownicy ich programów) z nich korzystali na co dzień. Jedną z największych zalet wynikających z tych kontrolek jest właśnie to, że jak coś się miało popsuć, lub 'nie wyjść' to bardzo prawdopodobne, że wcześniej popsuło się komuś innemu i ekipa z devxpressa już ten problem rozwiązała, lub właśnie nad nim pracuje ;)
Oczywiście, nie ma róży bez kolców, ale o tym nieco później.
Najpierw jednak przyjrzyjmy się tym kontrolkom nieco bliżej. Jak przykład użyję kontrolek asp.net, jako, że są to kontrolki webowe i istnieje całkiem niezłe 'on-line' demo. Jedną z najlepszych, a zarazem najczęściej używanych jest DevExpressowy odpowiednik AspxGridView.
Zalecam zapoznanie się z demem tego grida, ponieważ posiada naprawdę potężne możliwości (np. utworzenie rozwiązania, wyświetlającego 300.000 rekordów w kilka min. z rewalacyjną, jak na taką ilość danych szybkością wyświetlania, sortowania, filtrowania itp.).
Do tego dochodzą wszelakie możliwości kontrolek DevExpressa, czyli multum opcji i pełna konfigurowalność (a w pakiecie ultimate również kody źródłowe kontrolek). Po tym, jak programista zobaczy, ile jest opcji konfiguracyjnych dla danej kontrolki by deafult (a drugie tyle w tutorialach i Q&A na forum wsparcia) to później zwykłe .net-owe kontrolki wyglądają mega blado.
Tak jak już zostało wspomniane, aspxGridView nie jest jedyną kontrolką, jaka isntieje w pakiecie. Generalnie zasada jest taka, że każda kontrolka wystepująca w standardowym GUI .NET Framework ma tutaj swoje devExpressowego odpowiednika. Do tego dochodzą jeszcze inne, mniej lub bardziej przydatne kontrolki standardowo nie występujące we frameworku.
Ale nie ma róży bez kolców. Oto kilka mniej przyjemnych aspektów, które należy wziąć pod uwagę w momencie, gdy nastąpi już pierwszy 'efekt wow'.
Więc po kolei:
- cena, która jest dosyć spora, bo liczona per programista
- problemy z instalacją w środowisku sharepoint - zapewne będzie to temat jednego z przyszłych wpisów. Generalnie udało nam się to zwalczyć własnymi siłami dla pojedyńczego serwera, za pomocą ręcznego instalowania paczek '.wsp' oraz ręcznych wpisów do web.config (automaty dostarczane przez producenta nie zadziałały, a wsparcie techniczne nie było nam w stanie pomóc), aczkolwiek syt. 'farmy serwerów', w której mamy dostęp do pliku web.config tylko jednego serwera nadal jest dla nas problematyczna.
- na słabszych sprzętowo maszynach, obciążenie procesora/pamięci ram powodowało randomowe błędy krytyczne visual studio powodujące jego zamknięcie w trybie awaryjnym, w momencie włączania debuggera. O dziwo, problem ten występował tylko i wyłącznie dla aplikacji typu sharepoint.
- takie sobie wsparcie techniczne, które stara się pomóc, jednak z własnego doświadczenia wiem, że iż mimo, że jest całkiem miłe, to działa średnio sprawnie.
Generalnie temat warty rozważenia, aczkolwiek w przypadku firm typowo sharepointowych mocno wątpliwy, z uwagi na dodatkowe, mało znane producentowi problemy związane z developowaniem tych kontrolek w środowisku sharepoint.
Takim przykładem komercyjnego oprogramowania, a dokładniej kontrolek wykorzystywanych w środowisku '.NET' są kontrolki firmy DevExpress. Kontrolki, które nie są tanie (link do cennika) i kupowane są 'per developer'. Tak, moi mili. Te ceny, które są tam umieszczone dotyczą ceny, za możliwość wykorzystywania oprogramowania przez pojedyńczego programistę i kształtują się od $900 za najmniejszy pakiet (np. dla programisty asp.net) do pakietu full ($2199 per programista).
Co za tą cenę dostajemy?
Hmmm, chyba najlepsze kontrolki programistyczne, jakie można dostać w .net ;)
Programując z ich wykorzystaniem programista naprawdę zyskuję sporą przewagę nad rozwiązaniami darmowymi, a co za tym idzie programowanie idzie szybciej, sprawniej, jest ładniejsze i zawiera mniej błędów. Przede wszystkim uzyskujemy kod wykorzystywany i sprawdzony przez miliony ludzi. Firma devExpress wygrywała ze swoimi kontrolkami wiele międzynarodowych konkursów, przez co jej popularność rosła, a wraz z nią ilość ludzi którzy bezpośrednio (developerzy) oraz pośrednio (użytkownicy ich programów) z nich korzystali na co dzień. Jedną z największych zalet wynikających z tych kontrolek jest właśnie to, że jak coś się miało popsuć, lub 'nie wyjść' to bardzo prawdopodobne, że wcześniej popsuło się komuś innemu i ekipa z devxpressa już ten problem rozwiązała, lub właśnie nad nim pracuje ;)
Oczywiście, nie ma róży bez kolców, ale o tym nieco później.
Najpierw jednak przyjrzyjmy się tym kontrolkom nieco bliżej. Jak przykład użyję kontrolek asp.net, jako, że są to kontrolki webowe i istnieje całkiem niezłe 'on-line' demo. Jedną z najlepszych, a zarazem najczęściej używanych jest DevExpressowy odpowiednik AspxGridView.
Zalecam zapoznanie się z demem tego grida, ponieważ posiada naprawdę potężne możliwości (np. utworzenie rozwiązania, wyświetlającego 300.000 rekordów w kilka min. z rewalacyjną, jak na taką ilość danych szybkością wyświetlania, sortowania, filtrowania itp.).
Do tego dochodzą wszelakie możliwości kontrolek DevExpressa, czyli multum opcji i pełna konfigurowalność (a w pakiecie ultimate również kody źródłowe kontrolek). Po tym, jak programista zobaczy, ile jest opcji konfiguracyjnych dla danej kontrolki by deafult (a drugie tyle w tutorialach i Q&A na forum wsparcia) to później zwykłe .net-owe kontrolki wyglądają mega blado.
Tak jak już zostało wspomniane, aspxGridView nie jest jedyną kontrolką, jaka isntieje w pakiecie. Generalnie zasada jest taka, że każda kontrolka wystepująca w standardowym GUI .NET Framework ma tutaj swoje devExpressowego odpowiednika. Do tego dochodzą jeszcze inne, mniej lub bardziej przydatne kontrolki standardowo nie występujące we frameworku.
Ale nie ma róży bez kolców. Oto kilka mniej przyjemnych aspektów, które należy wziąć pod uwagę w momencie, gdy nastąpi już pierwszy 'efekt wow'.
Więc po kolei:
- cena, która jest dosyć spora, bo liczona per programista
- problemy z instalacją w środowisku sharepoint - zapewne będzie to temat jednego z przyszłych wpisów. Generalnie udało nam się to zwalczyć własnymi siłami dla pojedyńczego serwera, za pomocą ręcznego instalowania paczek '.wsp' oraz ręcznych wpisów do web.config (automaty dostarczane przez producenta nie zadziałały, a wsparcie techniczne nie było nam w stanie pomóc), aczkolwiek syt. 'farmy serwerów', w której mamy dostęp do pliku web.config tylko jednego serwera nadal jest dla nas problematyczna.
- na słabszych sprzętowo maszynach, obciążenie procesora/pamięci ram powodowało randomowe błędy krytyczne visual studio powodujące jego zamknięcie w trybie awaryjnym, w momencie włączania debuggera. O dziwo, problem ten występował tylko i wyłącznie dla aplikacji typu sharepoint.
- takie sobie wsparcie techniczne, które stara się pomóc, jednak z własnego doświadczenia wiem, że iż mimo, że jest całkiem miłe, to działa średnio sprawnie.
Generalnie temat warty rozważenia, aczkolwiek w przypadku firm typowo sharepointowych mocno wątpliwy, z uwagi na dodatkowe, mało znane producentowi problemy związane z developowaniem tych kontrolek w środowisku sharepoint.
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.
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.
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.
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).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();
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.
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:
Sprawdzanie konkretnych, wybranych partii kodu, pod kątem wydajności następuje, poprzez wykonanie naszego kodu wewnątrz "using-a".
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.
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 ondemandWyłą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:
Rozwiązanie polega na tym, aby plik z biblioteką jQuery wczytywać po stronie serwera w instrukcji warunkowej:
</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ć.
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/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.Scripts/ jquery-1.8.2.min.js" type="text/javascript"></scrip t>
Rozwiązanie polega na tym, aby plik z biblioteką jQuery wczytywać po stronie serwera w instrukcji warunkowej:
W podobny sposób możemy wczytać bibliotekę jQuery, gdy nie jest wczytana w postaci kodu javascript umieszczonego na stronie html:protected void Page_Init(object sender, EventArgs e){var cs = Page.ClientScript;if (!cs.IsClientScriptIncludeRegistere d("jquery-1.8.2.min.js")) cs.RegisterClientScriptInclude(" jquery-1.8.2.min.js", "/_layouts/}Scripts/ jquery-1.8.2.min.js");
<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();
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#.
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:
Podczas pobierania SuperSite lepiej jest jednak wykorzystać wrapper, w postaci klasy SPSecurityHelper, zademonstrowanej przez Dana Larsona na jego tech-blogu
Klasa SPSecurityHelper:
Przykład:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSitesuperSite = new SPSite(SPContext.Current.Site.ID))
{
using (SPWebsuperWeb =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;Wykorzystanie klasy SPSecurityHelper:
/// <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;
}
}
}
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.
sobota, 22 września 2012
Podlgądanie zawartości pliku *.wsp
W aplikacji sharepoint, skompilowane rozwiązania (solucje) kompilowane są do plików z rozszerzeniem *.wsp. Pliki, te są paczkami, zawierającymi pliki, jakie nast. zostaną wgrane na serwer podczas instalacji pliku .wsp. Jeżeli chcemy podejrzeć zawartość pliku wsp, aby np. mieć pewność, czy pliki z obrazkami (*.png) poprawnie załączyły się podczas kompilacji, możemy to zrobić, zmieniając rozszerzenie pliku z '*.wsp", na "*.cab", a nast. przejrzeć plik "*.cab" za pomocą eksploratora plików systemu windows. Przykład:
MojaSolucja.wsp -> MojaSolucja.cab
MojaSolucja.wsp -> MojaSolucja.cab
środa, 12 września 2012
Wyzerowanie (czyszczenie) witryny sharepoint
Czyli... coś czego... niemal nigdy nie powinno się robić, jednak moja wyobraźnia jest na tyle pojęta, że... jednak jestem w stanie sobie wyobrazić syt. w której trzeba programistycznie wyczyścić całą witrynę sharepoint. Można to zrobić za pomocą przedstawionej poniżej metody, którą można podpiąć pod kod deaktywujący feature.
Uwaga: ta metoda jest niczym "broń atomowa" dla witryny sharepoint, więc jej ewentualne użycie powinno być wcześniej 10-krotnie przemyślane.
int listIndex = 0;
while (web.Lists.Count > listIndex)
{
try
{
web.Lists[listIndex].Delete();
}
catch (Exception ex) { listIndex++; };
}
while (web.ContentTypes.Count > 0)
{
int errorCount = 0;
while (web.ContentTypes[0]. FieldLinks.Count > errorCount)
{
try
{
web.ContentTypes[0].FieldLinks
.Delete(web.ContentTypes[0]. FieldLinks[errorCount].Id);
}
catch (Exception ex)
{
errorCount++;
}
}
web.ContentTypes[0].Delete();
}
while (web.Fields.Count > 0)
{
while (fieldIndex < web.Fields.Count)
{
try
{
}
catch (Exception ex) {
fieldIndex++;
}
}
web.Update();
web.ResetRoleInheritance();
if (Helpers.checkGroup(SolutionRe sourcesAccessor. RMUAHRGroupName, web.SiteGroups))
web.SiteGroups.Remove(Solution ResourcesAccessor. RMUAHRGroupName);
if (Helpers.checkGroup(SolutionRe sourcesAccessor. RMUAUsersGroupName, web.SiteGroups))
web.SiteGroups.Remove(Solution ResourcesAccessor. RMUAUsersGroupName);
if (Helpers.checkGroup(SolutionRe sourcesAccessor. RMUAAdminGroupName, web.SiteGroups))
web.SiteGroups.Remove(Solution ResourcesAccessor. RMUAAdminGroupName);
while (web.Navigation.QuickLaunch. Count > 0)
{
web.Navigation.QuickLaunch. Delete(web.Navigation. QuickLaunch[0]);
web.Update();
}
while (web.Navigation. TopNavigationBar.Count > 0)
{
web.Navigation. TopNavigationBar.Delete(web. Navigation.TopNavigationBar[0] );
web.Update();
}
web.GetLimitedWebPartManager(S PUrlUtility.CombineUrl(web. Url, "default.aspx")
, System.Web.UI.WebControls. WebParts.PersonalizationScope. Shared);
mainLWPM.DeleteWebPart( mainLWPM.WebParts[0]);
}
Uwaga: ta metoda jest niczym "broń atomowa" dla witryny sharepoint, więc jej ewentualne użycie powinno być wcześniej 10-krotnie przemyślane.
private void ClearAll(SPFeatureReceiverProp erties properties)
{
SPWeb baseWeb = (SPWeb)properties.Feature. Parent;
Guid siteId = baseWeb.Site.ID;
Guid webId = baseWeb.ID;
SPSecurity. RunWithElevatedPrivileges(
delegate()
{
using (SPSite adminSite = new SPSite(siteId))
{
try
{
SPWeb web = adminSite.AllWebs[webId];
if (web.Exists)
{
int fieldIndex = 0;
web.Fields. Delete(web.Fields[fieldIndex]. InternalName);
};
}
SPLimitedWebPartManager mainLWPM =
while (mainLWPM.WebParts.Count != 0)
web.ResetRoleInheritance();
}
catch (Exception ex)
{
}
}
}
);
Subskrybuj:
Posty (Atom)
