Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc
Titulní Blogy Fotky Soubory

Mazinův blog o SharePointu

  • SharePoint 2016 poodhalen

    Julia White generální manažerka Office Product Management týmu oznámila některé informace o chystané nové verzi SharePointu. Další informace budou oznámeny na Microsoft Ignite 4. - 8. 5. 2015.

    Z uveřejněných informací plyne, že novinky se budou točit kolem SharePointu Online. To je logické, protože do něj investoval Microsoft mnoho energie. Jednak budou posíleny možnosti integrace mezi SharePoint on-premise a SharePoint online pro použití v hybridních scénářích. Toto je v současnosti slabým místem, které určitě potřebuje vylepšit.

    Pokud jde o další vylepšení, půjde vlastně o přenos některých funkcí implementovaných v SharePointu online do on-premise světa. Týká se to:

    1. Vyhledávání a zejména Delve
    2. Práce se soubory -  viz. rozvoj OneDrive, OneDrive for Business
    3. BI – podpora Power BI
    4. Rozšiřování API tak, aby byly nové funkce dostupné a konzumovatelné z mimo SharePoint. Viz. koncept SharePoint Apps.

    Myslím, že se máme na co těšit.

  • Načítání dat ze seznamu do Excelu

    Excel se velmi často používá nejen k práci s tabulkami dat a kreslení grafů, ale mnohdy i k tvorbě “formulářů” pro výpočet případně vyplnění kdečeho. Takový formulář kromě informací zadaných uživatelem zpracovává i informace načtené např. z SharePointu.

    SharePoint umožnuje načítání dat do Excelu pomocí tlačítka v ribbonu. Tento způsob je velmi jednoduchý. Takto můžete načítat data z konkrétního zobrazení seznamu nebo knihovny dokumentů. To znamená, že si můžete definovat podmínku, řazení a vybrat sloupce, které chcete zobrazit. Technicky to pak probíhá tak, že SharePoint sestaví soubor s příponou iqy. Je to definice datového zdroje a přípona je asociována s Excelem. Ten na otevírání takového souboru reaguje tak, že vloží do aktuálně otevřeného XLS souboru nový datový zdroj a na nový nebo existující list zobrazí načtená data. To aby bylo zřejmé, jestli napojení funguje nebo ne. Důležité na tomto způsobu je, že XLS soubor obsahuje kopii dat a současně je v něm uložena i definice datového zdroje. Díku tomu můžete soubor použít offline (bez dostupnosti SharePointu) a pokud je SharePoint jako datový zdroj dostupný můžete provést aktualizaci dat.

    Na druhou stranu má tento jednoduchý scénář i nevýhody. Jednou z nich je, že se do XLS souboru načítají všechna data ze zobrazení a teprve v Excelu se vybírají jen ty, které jsou skutečně potřeba. Například podle uživatelem vyplněných hodnot. Načítání celého zobrazení může někdy představovat mnoho dat, i když je nebudete nikdy potřebovat všechny najednou. Jednak se tím zbytečně zvětšuje excelový soubor, ale narůstá tím i množství přenášených dat při aktualizaci. 

    Praktický příklad:

    Mějme excelový soubor fungující jako formulář, ve kterém zaměstnanci vykazují náklady služebních cest. Služební cesty jako takové se do SharePointu dostanou dříve a mohou procházet i nějakým schvalování. V našem scénáři zaměstnanec vybere služební cestu a zaeviduje výdaje, které mu v jejím rámci vznikly. Můžeme vytvořit zobrazení v seznamu služebních cest, které bude obsahovat jen nevyúčtované služební cesty, ale i to může představovat poměrně dost dat. Ideální by bylo si načíst jen služební cesty aktuálního uživatele za jim zvolený měsíc. Toho ale standardním způsobem nedosáhneme. Naštěstí si můžeme pomoci jinak.

    Dá se využít toho, že SharePoint podporuje REST volání a OData protokol a Excel umožnuje zpracovávat OData datové zdroje. Navíc s datovými zdroji (nejen s OData) umožnuje manipulovat pomocí maker. Takže si můžeme do Excelu dát datový zdroj v podobě http://server/kolekce/web/_api/lists/getlistbyname(‘Seznam’)/Items?rest dotaz. Nechci se teď pouštět do hlubšího rozboru práce s REST rozhraním, ale nedá mi to, abych si nepostesknul: Všimněte si toho getlistbyname. Není možné otevřít seznam podle jeho URL. Smutný obličej Druhou alternativou, kterou podle MSDN máme, je otevření seznamu pomocí jeho ID (GUID).

    V ribbonu Data použijeme volbu Načíst data z externích zdrojů a variantu Z datového kanálu OData.

    V následujícím okně do pole Odkaz nebo soubor vyplníme URL http://server/kolekce/web/_api/lists/getlistbyname(‘Seznam’)/Items. Excel standardně uloží definici datového zdroje do externího souboru. Musíme si ho znovu otevřít a provést jakoukoli změnu, aby ho uložil přímo do XLS souboru. Když se podíváme do definice datového zdroje, najdeme v poli Připojovací řetězec něco podobného:

    Data Source="https://server/_api/web/lists/getByTitle('Seznam')/items";Namespaces to Include=*;Max Received Message Size=4398046511104;Integrated Security=SSPI;Keep Alive=true;Persist Security Info=false;Base Url=https://server/_api/web/lists/getByTitle('seznam')/items

    Naše URL se v něm objevuje 2x. Pro nás je důležitá část Base Url na konci. Jejím měněním se dá ovlivňovat to, co SharePoint bude vracet. Ani tentokrát se nechci věnovat REST dotazům podrobně, na to si nechám samostatný příspěvek. Pro tuto chvíli si řekněme, že na konci adresy se dá pomocí REST syntaxe specifikovat podmínka, kterou musí záznamy splňovat, řazení a další věci obvyklé při dotazování. Detaily najdete na MSDN. Takže není problém načíst jen ty záznamy, které vyhovují nějaké podmínce a klidně tuto podmínku poskládat z informací zadaných uživatel.

    Zde máme příklad, jak můžeme pomocí VBA v Excelu měnit connection string a provést aktualizaci dat:

        Dim mm As String
        mm = ActiveWorkbook.Connections("jméno zdroje").DataFeedConnection.Connection
        ActiveWorkbook.Connections("jméno zdroje").DataFeedConnection.Connection = mm & "?$filter=Type eq 'Test'"
        ActiveWorkbook.Connections("jméno zdroje").Refresh

    Samozřejmě je to velmi zjednodušený příklad. Podmínka je statická, nefungoval by správně při opakovaném provedení a dalších situacích. V tuto chvíli mi jde spíše o demonstraci myšlenky, než kompletní řešení.

  • Provádění dlouhých operací v UI

    I v SharePointu občas dojde k situaci, kdy je potřeba provést delší operaci. Znáte to: vytváření webů,… Při vývoji vlastních řešení na to určitě narazíte také. Pro ASP.NET existuje několik řešení nejčastěji v podobě javascriptů, které na stránce vykreslují točící se kolečko nebo něco podobného, co uživateli říká “ještě vydrž …”.

    SharePoint nám k tomu poskytuje podporu v podobě 2 tříd: SPLongOperation a SPStatefulLongOperation. Na obě se dnes podíváme blíže. Jejich problém spočívá v tom, že jsou mizerně dokumentované v MSDN a na internetu se o nich a jejich použití spoustu zavádějících informací.

    Timeouty

    Jednou z nepřesností je otázka timeoutů. Dočtete se, že tyto třídy umí “obejít” standardní timeouty pro zpracování stránek. Možná to tak v předchozích verzích SharePointu bylo, ale v SharePointu 2013 to bohužel neplatí. Timeouty jsou standardně 110 nebo 360 sekund podle umístění stránky. Nastavují se ve vlastnosti executionTimeout elementu httpRuntime. Pro aplikační stránky platí 360s, který je nastaven ve <SharePoint>\template\layouts\web.config. Když se do něj podíváte, zjistíte, že mnoho systémových stránek má vlastní, delší. Pro ostatní stránky (např. stránky z knihovny stránky webu) se uplatňuje nastavení web.configu příslušné webové aplikace. A protože v něm SharePoint standardně nemá tento atribut nemá (pouze pro některé konkrétní stránky), platí výchozí hodnota ASP.NET, tedy 110s. Bez použití těchto dvou objektů skončí zpracování stránek po vypršení diskutovaných timeoutu vyjímkou.

    Naštěstí se problém timeoutů dá řešit přímo v kódu vaší stránky/webpartu/user controlu nastavením this.Page.ScriptTimeout na hodnotu, kterou považujete pro zpracování vaší operace za dostatečnou (ideálně s nějakou rezervou pro případ většího zatížení serveru). Nedoporučuju to zase přehánět. Připravíte se tak o indikátor toho, že je něco špatně, když váš kód bude trvat výrazně déle, než by měl.

    Nezapomeňte ale, že zpracování klientských požadavků v SharePointu ovlivňuje více timeoutů. Jedním z dalších je i FormDigest timeout. I když by se mohlo na první pohled zdát, že se to týká pouze formulářového přihlašování, není to pravda. FormDigest je bezpečnostním prvkem ve formulářích (odtud to form) ale nejen tam. Ano to je ten, který občas způsobuje chybu: The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.). Kromě jiných vlastností má i dobu platnosti. Standardně 30min. Takže pokud zpracování vaší stránky bude trvat déle než 30 minut, budete muset řešit i tento timeout.

    Použití

    Zahájení

    Oba objekty se používají podobně. Nejprve zavoláte některou z metod Begin. Tím SharePointu řeknete, aby uživateli zobrazil “čekací stránku”, pak provedete to, co dlouho trvá, a na konci uživatele nejčastěji přesměrujete na stránku s výsledkem (může to být samozřejmě i stránka na které uživatel aktuálně je). Variantně na konci můžete uživateli “poslat” javascript, který provede něco spektakulárního.

    SPStatefullLongOperation se od SPLongOperation liší tím, že podporuje aktualizaci stavu operace v jejím průběhu. Můžete tedy uživateli zobrazovat něco jako “už jsem zpracoval 6 položek z 15” a postupně to aktualizovat. Toto se nicméně dá realizovat i vhodným použitím LeadingHTML u SPLongOperation. Například využitím javascriptu, který bude např. volat webovou službu a zjišťovat průběžný stav. Při použití SPStatefullLongOperation se aktualizace děje tak, že s každou aktualizací stavu se do response streamu (tedy na klienta) zapíše váš text (může to být i HTML a javascript).

    Oba objekty využívají stránku <SharePoint>\template\layouts\gear.aspx jako podklad pro zobrazení “točícího se kolečka” a informace, kterou mu dodáte. Uživatel zůstává na vaší stránce, ale po zavolání metody Begin je mu zobrazen obsah gear.aspx a vaše texty. K tomu slouží vlastnosti LeadingHTML a TrailingHTML. Obě vlastnosti slouží především k zobrazení informace o tom, co stránka tak dlouho dělá, např. “Právě vytvářím strukturu webů”.

    Můžete se podívat, jak vypadá základ gear.aspx, do kterého se vaše LeadingHTML a TrailingHTML vyrenderují. Teoreticky je možné změnou tohoto souboru změnit vzhled čekací stránky, ale není to doporučený ani podporovaný scénář. Minimálně se vám může stát, že update SharePointu vám ho přepíše.

    Podporovaným způsobem, jak ovlivnit vzhled a chování čekací stránky jsou zmiňované vlastnosti LeadingHTML a TrailingHTML. Díky tomu, že do nich můžete dát neencodované HTML, lze jejich prostřednictvím do stránky dostat javascript, CSS, HTML, … zkrátka téměř vše, co můžete potřebovat.

    Ukončení

    Po dokončení dlouhé operace zavoláte metodu End (má několik přetížení), nebo EndScript. V konečném důsledku End metody volají EndScript. Na rozdíl od přechozích verzí SharePointu se totiž přesměrování na cílovou stránku v metodách End neděje pomocí metody Response.Redirect, ale klientským javascriptem. Buď tím, který podporuje MDS (Minimal Download Strategy – standardně zapnuto např. na týmových webech), nebo prostým přiřazením window.location.href. Anebo vašim vlastním. To když použijete metodu EndScript.

    Při práci s těmito objekty určitě ošetřujte chyby a provádějte vlastní reakci na ně. Neošetřené vyjímky totiž vedou k tomu, že uživatel vidí často jen prázdnou stránku s titulkem “Chyba”. Když se podíváte do těla stránky tak zjistíte, že v ní to chybové hlášení je. Ale vzhledem k rozpadlému formátování uživatel nic nevidí, nebo vidí jen torzo (podle schopností prohlížeče).

    Příklad na závěr

    Jde o metody z mé testovací stránky. Každá demonstruje použití jednoho z objektů. Obě pracují s textovým polem RunningSeconds, do kterého jsem zadával čas pro otestování chování různě dlouhých operací. Tuto operaci simuluje metoda LongOperation, která simuluje dlouhý běh uspáním vlákna na určenou dobu.

    protected void LongOperation_Click(object sender, EventArgs e)
    {
         int seconds = Int32.Parse(this.RunningSeconds.Text);
         this.Page.Server.ScriptTimeout = seconds * 2;

         using (SPLongOperation longOp = new SPLongOperation(this.Page))
         {
             longOp.LeadingHTML = "LeadingHTML";
             longOp.TrailingHTML = "TrailingHTML";

             longOp.Begin();

             try
             {
                 LongOperation(seconds);
                 longOp.End(HttpContext.Current.Request.UrlReferrer.ToString());
             }
             catch (Exception)
             {
                 longOp.End(HttpContext.Current.Request.UrlReferrer.ToString()+"?Error=1");
             }
         }
    }

    protected void LongStateOperation_Click(object sender, EventArgs e)
    {
         int seconds = Int32.Parse(this.RunningSeconds.Text);
         this.Page.Server.ScriptTimeout = seconds * 2;

         SPStatefulLongOperation.Begin(
             "<span id='leadingSpan'>(0 of 10)</span>",
             "<span id='trailingSpan'>Trailing span</span>",
             (op) =>
             {
                 try
                 {
                     op.Run((opState) =>
                     {
                         for (int i = 0; i < 10; i++)
                         {
                             // Update status.
                             opState.Status = String.Format("<script type='text/javascript'>document.all.item('leadingSpan').innerText = '({0} of {1})';</script>", i + 1, 10);
                             LongOperation(seconds / 10);
                         }
                     });

                     op.End(HttpContext.Current.Request.UrlReferrer.ToString());
                 }
                 catch(Exception)
                 {
                     op.End(HttpContext.Current.Request.UrlReferrer.ToString()+"?Error=1");
                 }
             });
    }

    private void LongOperation(int seconds)
    {
         Thread.Sleep(seconds * 1000);
    }
  • Lokalizace a typy obsahu

    Lokalizace je komplexní téma. Něco o něm už jsem popsal dříve. Dnes se ale podíváme na jednu oblast. Tou je práce s typy obsahu v kódu.

    Na rozdíl od sloupců nemají typy obsahu ID, internal name – interní název typicky používaný v kódu a display name – to vidí koncový uživatel a lokalizuje se. Mají jen ID a name. Jméno se zobrazuje uživateli a současně může sloužit i jako interní identifikátor a protože ho vidí uživatel, lokalizuje se.

    Pokud chcete pracovat s typem obsahu programově, můžete se na něj odkazovat dvěma způsoby:

    1. Pomocí ID
    2. Pomocí jména

    Při použití je ID problém v tom, že content type id je lidsky obtížně čitelný (i pro programátora) a navíc se mění seznam od seznamu. To je proto, že SharePoint při použití typu obsahu webu v seznamu vždy vytvoří jeho potomka a ten má jiné ID než jeho předek (ID předka je prodlouženo). Naproti tomu jméno typu obsahu je stále stejné ať jde o typ obsahu webu, nebo jeho použití na úrovni seznamu. Má to ale jinou potíž. Díky tomu, že jméno typu obsahu je obvykle lokalizováno, mění se podle jazykového prostředí aktuálního uživatele.

    Takže konstrukce item["ContentType"] = "jmeno typu obsahu" nebo list.ContentTypes["jmeno typu obsahu"] si říkají o problém, protože nevíte v jakém jazykovém nastavení (řídí se jazykem uživatele) se bude kód spouštět. Když daný kód poběží v kontextu česky mluvícího uživatele, ale jméno typu obsahu v kódu bude anglickou variantou, první příklad povede k tomu, že položka dostane výchozí typ obsahu seznamu a druhý vrátí null.

    Dá se použít item["ContentType"] = SPUtility.GetLocalizedString("$Resources:resourceKey","Resourcefile",(uint)Thread.CurrentThread.CurrentUICulture.LCID). Tím zajistíte, že se použije vždy správně lokalizované jméno. Bohužel ale tento přístup nemůžete použít vždy. Pokud máte například scénář, kdy jméno typu obsahu zadává uživatel v nějaké konfiguraci, tak obvykle zadá to, co vidí v systému (tedy lokalizované jméno), ne resource key. Uživatel ho nemá jak zjistit, nehledě na to, že mnohdy ani netuší, co to je.

    Pokud tedy máte jméno typu obsahu a nevíte, v jakém je jazyce, musíte vyzkoušet jazyky podporované příslušným webem. Podpora více jazyků je totiž vlastností jednotlivých webů. Můžete měnit vlastnost Thread.CurrentThread.CurrentUICulture a zkoušet, až vám list.ContentTypes["jmeno typu obsahu"] vrátí něco jiného než null. To má ale tu nevýhodu, že nesmíte zapomenout vrátit nastavení CurrentUICulture zpět na původní hodnotu. Jinak se vyrenderuje i zbytek stránky v nově nastaveném jazyce. Alternativou může být následující kus kódu:

    string searchCTName = "Content Type A"; //načteno z konfigurace
    foreach (CultureInfo cultureInfo in web.SupportedUICultures)
    {
          foreach (SPContentType contentType in list.ContentTypes)
          {
              if (string.Compare(searchCTName, contentType.NameResource.GetValueForUICulture(cultureInfo), true) == 0)
              {
                  // to je ten, co hledám
                  break;
              }
          }
    }

    Závěr

    Je doporučeno pracovat s ID typu obsahu. Když to z nějakého důvodu nejde a musíte použít jméno, nic není ztraceno, jen se to při podpoře lokalizace komplikuje.

  • Volání webové služby s klientským certifikátem

    Zabezpečení je tématem dneška a SSL je běžným zabezpečením výměny dat mezi klientem a serverem. Minimálně je k němu nutný serverový certifikát. Čím dál častěji se ale objevuje i používání klientských certifikátů, zejména pro autentizaci.

    O úskalí ověření serverového certifikátu při volání webových služeb přes SSL v SharePointu jsem psal dříve. Nyní se podíváme na komplikaci při použití klientského certifikátu. Ten je uložen nejčastěji v úložišti certifikátů, obvykle v profilu počítače. Odtud ho může používat více aplikací. Alternativou je jeho umístění do úložiště účtu, pod kterým běží proces klienta. Důležité je, že při použití klientského certifikátu musíte mít i odpovídající privátní klíč. Tím prokazujete, že máte kompletní klíč. Stejně tak je důležité, že standardně nemá pool IIS, přístup k privátním klíčům v úložišti certifikátů. To je z důvodů ochrany, aby při hacku IISka nemohlo dojít ke kompromitaci privátních klíčů. V našem scénáři ale přístup potřebujeme udělit. Chyba, se kterou se tato situace projevuje, je:
    System.Net.WebException. The Underlying Connection Was Closed. Could Not Establish Trust Relationship with Remote Server.

    Nebudu zde popisovat, jak nainstalujete certifikát s klíčem (typicky ve formě PFX souboru) do správného úložiště. Předpokládejme, že je máme správně nainstalované v úložišti lokálního počítače. Další důležitou podmínkou je, že musíte mít nainstalované i všechny certifikáty CA až ke kořenovému certifikátu (certifikát CA, vystavený jí samotnou, tzv. self-signed certifikát). Ten musí být nainstalovaný mezí důvěryhodnými kořenovými certifikáty.

    K nastavení práv, ale i k instalaci certifikátu a privátního klíče, slouží nástroj winhttpcertcfg.exe.

    Příklady volání:

    winhttpcertcfg -i PFXFile -c LOCAL_MACHINE\My -a IWAM_TESTMACHINE -p PFXPheslo – instalace certifikátu z PFX souboru

    WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "IssuedToName" -a "uživatelské jméno poolu" – povolení použití privátního klíče certifikátu pro účet.

  • MVP certifikace

    S radostí vám chci napsat, že se mi podařilo dosáhnout MVP certifikace pro oblast SharePointu. Udělám, co budu moci, abych ji udržel. Tedy mimo jiné pokračovat v psaní tohoto blogu. Smile

    Děkuji vám za přízeň.

  • Problematická trojka – workflow, úkol a correlation token

    Před časem jsem psal článek o detailech implementace SharePoint workflow. Dnes se podíváme na praktické důsledky. Jde zejména o práci s úkoly a položkami, nad nimiž běží workflow, a problémy s tím spojenými.

    Zmiňoval jsem se o tom, že pro “publikaci” událostí o změnách nad položkami se používají event receivery. Ty jsou zodpovědné za automatické spouštění workflow a předávání informací o změnách na úkolech a položkách do spuštěných workflow. To ale není vše, co se na pozadí děje. A nutno také říct, že o mnohém z dále uvedeného MSDN mlží, nebo přímo neříká pravdu.

    Práce s úkoly

    Proto, aby si SharePoint udržel přehled o tom, že změna na úkolu byla zpracována workflow, mají workflow úkoly (typy obsahu odvozené od Workflow Task) definovaný sloupec WorkflowVersion. Ten nevyjadřuje verzi workflow, které úkol vygenerovalo, jak se můžete občas na internetu dočíst. Sloupec funguje jako zámek. Jeho výchozí hodnota je 1. Update metody (včetně SystemUpdate) nejprve kontrolují:

    1. jestli daný úkol je součástí běžícího workflow.
    2. jestli není vypnutý EventFiring. Když je vypnutý, že nehrozí, že by na změnu mohlo reagovat workflow (posouvané pomocí event receiverů).

    V případě, že oba testy jsou pozitivní, kontroluje se hodnot sloupce WorkflowVersion. Pokud je vyšší než 1, vyhodí známou vyjímku “This task is currently locked by a running workflow and cannot be edited”. V opačném případě se provede aktualizace úkolu. Na aktualizaci reaguje systémový event receiver a nastaví hodnotu sloupce na 512. Obsluha události ve workflow, tedy  aktivita onWorkflowTaskChanged, nastaví hodnotu sloupce WorkflowVersion opět na 1, tedy uvolní zámek pro další změny úkolu. V ideálním případě se informace o změně úkolu dostane do workflow téměř ihned. Může se ale stát (některé situaci si popíšeme dále), že informace do workflow je doručena jobem. Jeho spouštění je standardně naplánováno v 5 minutových intervalech. A během té doby je úkol uzamčen pro veškeré úpravy. Vhodnější je při úpravách workflow úkolů volat SPWorkflowTask.AlterTask(). Ta sice vnitřně také volá SPListItem.Update(), který může vyvolat vyjímku. Ale na svém začátku volá SPWorkflowTask.SetWorkflowData(), čímž posílá informace o změně přímo do workflow subsystému. Navíc v případě synchronního volání (parametr metody) počká před updatem až 30s na případné uvolnění zámku. Metodu AlterTask volá i editform úkolů.

    Podle MSDN by se měly event receivery pro sběr událostí o úkolech a položkách registrovat až v okamžiku, kdy se začne na tyto události čekat (workflow ve svém běhu dojde do aktivit onWorkflowTaskChanged, onWorkflowItemChanged, …). Naopak by se receivery měly deregistrovat po jejich dokončení, tedy obsluze odpovídajících událostí.

    Bohužel to celé nefunguje úplně dobře. Například když workflow vytvoří úkol a skončí (nebude čekat na změnu), vznikne nepříjemná situace. Úkol můžete editovat. Na tuto změnu zareaguje event receiver a nastaví hodnotu workflowversion na 512. Další pokusy o změnu už skončí neúspěchem. Zafunguje totiž kontrola v SPListItem.Update(). Problém je v tom, že chybí onWorkflowTaskChanged aktivita, která by hodnotu vrátila na 1.

    Correlation tokeny

    Correlation tokeny vytváří vazbu mezi aktivitami, které pracují s úkoly případně s položkou, nad níž workflow běží. Díky tomu může být ve workflow několik aktivit, které vytváří úkoly, mění je, čekají na jejich změnu a to celé souběžně a propleteně. Proto může workflow obsahovat více CreateTask aktivit a po nich několik onWorkflowTaskChanged, které budou reagovat na změnu “toho svého” úkolu. Workflow runtime je používá k určení místa, kam má v běžícím workflow doručit informaci o změně úkolu, nebo položky.

    Důležitou vlastností correlation tokenu je parent activity. Ta definuje rozsah platnosti tokenu, resp. toho, kde se pracuje s úkoly s ním svázanými. Pro práci s položkou (aktivity UpdateItem, onWorkflowItemChanged, …) se používá přímo token workflow, protože jeho parent aktivitou je workflow samotné. Pro práci s úkoly (CreateTask, onWorkflowTaskChanged, …) se definují vlastní tokeny s parent aktivitou zvolenou tak, aby objímala všechny operace, které se s jedním úkolem dějí. Někdy se vkládá do workflow uměle sequence aktivita právě pro definici rozsahu platnosti tokenu.

    A opět musím napsat, že to nefunguje úplně dobře. Correlation tokeny mohou způsobit dead-locky workflow, které workflow zcela zablokují. Nebo se může workflow chovat velmi nečekaně.

    Kombinace práce s úkolem a položkou v 1 workflow

    Člověk by řekl, že na workflow, které čeká na změnu položky, nad níž běží, vytváří úkoly a čeká na jejich dokončení, nemůže být nic dramatického. Zejména proto, že jde o běžný scénář. Pravda je to jen částečně. Změna položky a změna úkolu mohou vést k zámku workflow. To se programově pozná tak, že je nastavena vlastnost SPWorkflow.IsLocked na true. V UI to poznáte tak, že v detailu workflow uvidíte následující hlášku: Z důvodu velkého zatížení byla nejnovější operace pracovního postupu zařazena do fronty. K pokusu o její obnovení dojde později. Tím workflow runtime říká, že má několik konfliktních změn, které není schopen vyřídit live a proto je zařadil do fronty a vyřeší je job posouvající workflow kupředu. Z uživatelského pohledu to znamená, že workflow se zpracuje provedené změny se zpožděním odvislým od toho, jak je naplánovaná perioda toho jobu (standardně 5 min).

    Pojďme si na zjednodušených příkladech ukázat některé problémové situace, a jak se jim případně vyhnout.

    Příklad 1

    Začneme jednoduchým příkladem. Nejprve se čeká na změnu položky. Pak se vytvoří úkol a čeká se na jeho změnu. Tím workflow končí. Prosté a funkční.

    Příklad 2

    Nejprve se vytvoří úkol (CreateTask1), pak se čeká na jeho změnu (onTaskChanged1) a následně na změnu položky, nad níž úkol běží (onWorkflowItemChanged1). Úkolové aktivity mají vlastní token, onWorkflowItemChanged1 používá workflowToken. Jednoduché workflow, na kterém není nic složitého. Ale pozor! Workflow se totiž dokončí i v následujícím scénáři: Nejprve změním položku. Protože se hned na začátku registruje event receiver pro registraci změn položky a současně onWorkflowItemChanged1 používá workflowToken, který je platný od rozběhnutí workflow, tak se informace o změně položky uschová. Pak se vytvoří úkol, počká se na jeho změnu a ihned se z šuplíku vytáhne událost změny položky workflow, obslouží se a workflow skončí.

    Příklad 3

    Využití aktivity InitializeWorkflow a použití stejného correlation tokenu pro ni a aktivitu onWorkflowItemChanged1. Toto workflow už se opět chová očekávaně. Tedy změna položky provedená ještě v době před aktivitou InitializeWorkflow se nebere v úvahu.

    Příklad 4

    Komplikovanější scénář, ale stejný výsledek. Pokud provedete změnu záznamu ještě během úvodního čekání před vytvořením úkolu, listen aktivita proběhne větví s onWorkflowItemChanged1 aktivitou. Takže nestihnete reagovat na změnu úkolu.

    Příklad 5

    Řešení předchozího příkladu. Před listen aktivitu umístíme InitializeWorkflow a použijeme nový (jiný než WorkflowToken) token. Stejný pak použijeme v onWorkflowItemChanged1 aktivitě.

    Příklad 6

    Poslední příklad. Nejsložitější, ale nejreálnější. Čekání na změny je obalenou while aktivitou, která zajistí to, že dojde ke změně (úkolu, nebo položky), na kterou čekáme. Např. to, že úkol je dokončen, nebo že je nastavena požadovaná hodnota v nějakém sloupci. Pokud je registrována jiná změna, smyčka se vrátí zpět a čeká se znovu.

    V tomto případě jsem ještě přidal updatetask1 aktivitu do větve reagující na změnu položky. Po změně položky se tedy provede okamžitě změna úkolu a jde se na čekání na změnu. A dojde k zamknutí workflow. Tzn. další změny řeší job se zpožděním. Ale ať už provedete dále změnu úkolu z UI, nebo změnu položky, průběh workflow bude stejný. Poté, co se spustí workflow job, zpracuje se událost o změně úkolu (tu, kterou provedlo workflow samotné).

    Troubleshooting

    Chyby ve Workflow subsystému se logují do ULS logu v kategorii Workflow Infrastructure.

    Pokud ani to nestačí a potřebujete se podívat problému opravdu na kost. Můžete zapnout logování na úrovni Windows Workflow Runtime, nad kterým jsou SharePoint worklfow postavena. To uděláte úpravou konfigurace. Protože workflow je hostováno do první dehydratace v procesu W3WP.exe a po rehydrataci v procesu OWSTIMER.exe, musíte konfiguraci upravit, jak ve web.configu příslušné aplikace, tak v souboru owstimer.exe.config. Např. následující konfigurace bude do souboru WFtrace.log ukládat logování na úrovni Windows Workflow Foundation.

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <system.diagnostics>
        <sources>
          <source name="System.Workflow.Runtime" >
            <listeners>
              <add name = "System.Workflow"/>
            </listeners>
          </source>
          <source name="System.Workflow.Runtime.Hosting">
            <listeners>
              <add name="System.Workflow"/>
            </listeners>
          </source>
          <source name="System.Workflow.Activities">
            <listeners>
              <add name="System.Workflow"/>
            </listeners>
          </source>
        </sources>
        <sharedListeners>
          <add name="System.Workflow"
               type="System.Diagnostics.TextWriterTraceListener"
               initializeData="c:\WFTrace.log"
               traceOutputOptions="DateTime,ProcessId"/>
        </sharedListeners>
        <switches>
          <add name="System.Workflow.LogToTraceListeners" value="1"/>
          <add name="System.Workflow.Runtime" value="All" />
          <add name="System.Workflow.Runtime.Hosting" value="All" />
          <add name="System.Workflow.Runtime.Tracking" value="All" />
          <add name="System.Workflow.Activities" value="All" />
          <add name="System.Workflow.Activities.Rules" value="All" />
        </switches>
      </system.diagnostics>
    </configuration>

    Závěr

    Workflow ve SharePointu jsou užitečným nástrojem. Je potřeba jim ale věnovat pozornost, protože se může na první pohled chovat “podivně”. Z pohledu kolize změn a zamykání workflow je problematický souběh změn úkolu workflow a položky. Doporučuju předřazovat aktivitu InitializeWokflow všem onWorkflowItemChanged aktivitám, aby se eliminovaly některé z problematických situací. Díky tomu se z uživatelského pohledu budou posouvat workflow kupředu ihned a ne se zpožděním. Stejně tak pro úpravy úkolů doporučuji používat metodu SPWorkflowTask.AlterTask().

  • Centra schůzek a malý trik než úplně vyhynou

    Microsoft centra schůzek postupně odsouval do pozadí, až je nejspíš zařízne úplně. Pracuje na tom už od SharePointu 2010 a zejména Outlooku 2010. V Outlooku 2007 byla ikona pro připojení schůzky k centru schůzek normálně v menu. V Outlooku 2010 tam už nebyla, ale bylo možné ji tam přidat. V Outlooku 2013 už není vůbec. Existují sice komponenty 3. stran, které ji umí nahradit, ale směřování Microsoftu je zřejmé.

    Podobně je to v SharePointu samotném. Do SharePointu 2010 můžete centra normálně vytvářet. Obsahuje hned několik šablon těchto webů. V SharePointu 2013 ty šablony jsou ještě také a použitelné, ale nejsou viditelné a slouží zejména k usnadnění migrace SharePointu 2010 na novou verzi. Funkcionalita center schůzek je označená jako obsolete. Jak to dopadne v další verzi SharePointu je asi jasné, že.

    Microsoftí vysvětlení je založeno na tom, že centra schůzek jsou dnes překonaná. Doporučuje pro podporu spolupráce týmu použít normální týmový web v kombinaci se sdíleným OneNotem a Lyncem. Ideálně v prostředí Office365.

    Pro ty, kterým ale centra schůzek vyhovují, existují klony microsoftích šablon, např. na Codeplexu nebo postupy, jak si vyrobit vlastní šablony webů podobné těm standardním.

    Teď slibovaný trik. Pro mnoho uživatelů je problém připojit organizovanou schůzku k centru schůzek. A to, ať už centrum existuje, nebo si uživatel chce vytvořit nové. Problém je zejména v tom, že musí zadat URL existujícího centra, nebo webu, pod nímž se má centrum vytvořit. Problém je v tom, že obvykle nezná URL centra schůzek. Zejména, pokud k němu zatím žádnou schůzku nepřipojoval. V případě vytváření nového centra je to podobné s webem, kam centrum schůzek umístit. Situaci mu můžete zjednodušit tím, že připravíte centra pro očekávané schůzky (např. víte, že se budou ve firmě pořádat schůzky marketingového týmu). To je ale jen půlka problému. Ta další je v tom, jak uživatelům zjednodušit připojení 1. plánované schůzky v Outlooku k tomuto centru. Outlook si pamatuje, když už to uživatel jednou udělá a nabízí mu seznam. Ten je uložen v registrech, a proto s ním můžete manipulovat. Například pomocí připravených reg souborů, které distribuujete příslušným uživatelům. Ještě lepší je to pomocí doménových politik. Ty můžete cílit na skupiny uživatelů. V našem případě to budou členové marketingového týmu, zejména ti, kteří plánují schůzky. Stejně tak můžete uživateli tento seznam pročistit od už nepoužívaných center.

    Jsou v registrech na cestě HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Meetings\Profile klíč MRUInternal, typ REG_SZ a hodnota http://sp/schuzky|Schůzky|||||http://sp/schuzky/marketing|marketing||||| pro Outlook 2010. V Outlooku 2007 je tam 12.0 Nejprve je URL, pak oddělovač v podobě | , pak jméno centra a nakonec |||||.

  • Hostování workflow v SharePointu 2010 a SharePointu 2013 v modelu 2010

    V tomto článku bych se chtěl podívat blíže na to, jak jsou workflow hostována v SharePointu. Dlouho mi zůstávaly některé věci záhadou. Navíc se o nich různě píše různých místech na internetu a MSDN je na slovo skoupá. Proto jsem strávil několik večerů s iLspy v ruce a výsledky se pokusím shrnout do několika článků. Snad vám to pomůže vysvětlit některé věci a chování, které jsou jinak obtížně uchopitelné.

    Architektura

    SharePoint 2010 hostuje workflow pomocí implementace Windows Workflow Foundation z .NET frameworku 3.5. Tady si Microsoft snědl to, co si sám uvařil. A protože jsem Workflow Runtime implementoval i samostatně, tak si troufnu říct, že docela dobře.

    SharePoint 2013 uvádí jako jednu z novinek podporu Workflow Runtime z .NET frameworku 4.5. Je to řešeno externě pomocí samostatného Workflow Manageru. Bohužel je dostupný pouze v SharePoint Serveru 2013. V SharePoint Foundation 2013 máte smůlu. Nicméně SharePoint 2013 obsahuje i model provozování workflow z SharePointu 2010. Je tam z kompatibilních důvodů, ale v SharePoint Foundation 2013 nemáte ani jinou možnost.

    Tento článek je proto platný i pro SharePoint 2013. Pro SharePoint Foundation 2013 zcela a pro SharePoint Server 2013 pro workflow provozovaná v modelu 2010.

    Z obrázku je vidět, že SharePoint funguje z pohledu Windows Workflow Runtime dvěmi způsoby:

    • Jednak implementuje služby jako PersistenceService, která se stará o dehydrataci (tedy persistenci workflow po dobu, kdy aktivně neběží) a o rehydrataci, tedy o nahrání workflow z úložiště do paměti.
    • A také jako externí služba. Externí služby obecně slouží pro volání externího kódu, který není přímo součástí workflow, ale také pro registraci událostí, které až nastanou, tak se ve workflow obslouží.

    Pro persistenci instance běžícího workflow do databáze (tzv. dehydrataci) se používá XML serializace. Rehydratace odpovídá pro změnu XML deserializaci. Při deserializaci instance workflow z databáze do paměti je nezbytné, aby persistovaný tvar odpovídal tomu, co má SharePoint k dispozici. Jinými slovy XML uložené v databázi musí odpovídat třídě, která reprezentuje workflow v DLL. Může se vám stát, že provedete změny kódu workflow, které povedou k tomu, že SharePoint nedokáže pomocí definice třídy v DLL a XML v databázi znovuvytvořit objekt workflow. V takovém případě workflow zůstane ve stavu Probíhá a už se nikdy nepohne z místa. Situace je o to horší, že se o tom nedozvíte a SharePoint se bude v pravidelných intervalech, bez naděje na úspěch, pokoušet workflow oživovat.

    SharePoint workflow mohou pracovat s daty (vytvářet, měnit a mazat položky a úkoly) v SharePointu a reagovat na události (změna položky, změna úkolu), které se v něm nastanou. Slouží k tomu aktivity:

    • CreateTask, CreateTaskWithContentType, UpdateTask, DeleteTask, UpdateItem, … - pro manipulaci s daty workflow
    • OnWorkflowItemChanged, OnTaskCreated, OnTaskChanged, … - pro obsluhu událostí v SharePointu

    Zmíněné aktivity využívají služeb SPWinOeTaskService a SPWinOeWSSService obě jako potomci třídy ExternalDataExchangeService. Obě komunikují s SPWinOeHostService což je SharePointí interface pro komunikaci s Workflow Runtime.

    Event receivery

    Jako zdroje událostí používá SharePoint event receivery. Stejně tak je využívá pro automatické spouštění workflow při založení nebo změně položky. Když se seznamem asociujete workflow, SharePoint na tomto seznamu registruje SPWorkflowAutostartEventReceiver, který obsluhuje události ItemAdded a ItemUpdated a v nich podle definice prostřednictvím objektu SPWorkflowManager spouští instance workflow. K zachycení událostí o změně úkolů nebo položky, nad níž běží, registruje SharePoint při spuštění workflow SPWinOEItemEventReceiver.

    Proto, aby se nestalo, že při výpadku systému dojde ke ztrátě informací o událostech v SharePointu, jsou informace uloženy v tabulce SheduledWorkitems v obsahové databázi. Po doručení je smažou.

    Joby

    Může se stát, že informaci o události není možné doručit instanci workflow “online”. Pro tyto situace má SharePoint naplánovaný job (SPWorkflowJobDefinition), který frontu událostí zpracovává asynchronně. Tento job je standardně naplánovaný každých 5 minut. Proto může workflow za určitých okolností reagovat na události se zpožděním.

    Dále SharePoint používá SPWorkflowFailOverJobDefinition. Tento job se pokouší rozběhnout instance workflow, které selhaly z “vnějších” příčin. Tedy např. neběžící SQL, síťové problémy a podobně.

    Posledním jobem souvisejícím s workflow je poněkud kontroverzní job SPWorkflowAutoCleanJobDefinition. Cílem tohoto jobu je mazat informace workflow, které byly ukončeny (doběhly, nebo spadly), a uvolnit prostor v databázi. Standardně se tak děje po 60 dnech od ukončení. Nepříjemné na tom je, že jsou smazány informace o běhu workflow, ale i vytvořené úkoly. Pokud chcete po 60 dnech něco z toho dohledat, máte smůlu. Perličkou je, že historie běhu workflow v databázi zůstane, ale už se k ní jinak než v databázi nedostanete. A hromadí se v tabulce alluserdata s ostatními užitečnými položkami. Záznamy historie workflow jsou totiž také položky v seznamu. Sice v trochu speciálním seznamu, ale seznamu.

     

    Zajímavostí pro mě bylo zjištění, že úkoly vytvořené pomocí CreateTaskActivity se fakticky vytvoří až v okamžiku dehydratace workflow.

    Workflow může během svého života vytvořit, měnit a případně reagovat na změnu mnoha úkolů. K tomu, aby si SharePoint udržel vazbu mezi aktivitami, které pracují se stejným úkolem, používá tzv. correlation tokeny. S nimi je spojena celá řada potíží a na ně se, stejně jako na další věci, které se mohou pokazit, podíváme v dalším článku.

  • Různé metody aktualizace položek SharePointu v kódu

    SharePoint nabízí hned několik metod pro aktualizaci záznamů. Pokud se budeme bavit o serverovém objektovém modelu, tak tři. Tedy metody třídy SPListItem:

    • Update()
    • SystemUpdate(bool incrementListItemVersion)
    • UpdateOverwriteVersion()

    Protože se o nich nejen v MSDN píše celá řada různých informací často si protiřečících informací, rozhodl jsem se je prozkoumat a navzájem porovnat jejich chování.

    Můžeme začít pohledem dovnitř:

            public override void Update()
            {
                this.UpdateInternal(false, false, Guid.Empty, false, false, false, false, false, false, false);
            }
            public void SystemUpdate()
            {
                this.UpdateInternal(true, false, Guid.Empty, false, false, false, false, false, false, false);
            }
            public void SystemUpdate(bool incrementListItemVersion)
            {
                this.UpdateInternal(true, !incrementListItemVersion, Guid.Empty, false, false, false, false, false, false, false);
            }
            public void UpdateOverwriteVersion()
            {
                this.UpdateInternal(false, false, Guid.Empty, false, false, true, false, false, false, true);
            }

    Když byste postupovali dále, zjistíte, že i další zanořování je stejné a končí u volání nemanageovaného kódu.

    Zkoumal jsem zmíněné metody z pohledu zvedání verze, změny informace o čase poslední změny a informace o tom, kdo ji provedl. Dále pak, jestli se při použití odešle notifikace, spustí zaregistrovaný event receiver a posune běžící workflow.

    Všechny testy jsem dělal jak nad seznamem, tak nad knihovnou dokumentů, protože jsem se opakovaně přesvědčil, že některé věci na nich fungují různě.

    A zde je výsledek. X znamená, že daná metoda způsobí sledované chování.

      Zvednutí verze Změna modified Odeslání notifikace Posunutí workflow Reakce EventReceiverů
    Update

    X

    X

    X

    X

    X

    SystemUpdate    

    při přidání

    X

    X

    SystemUpdate(true)    

    při přidání

    X

    X

    UpdateOverwriteVersion

     

    X

    X

    X

    X

    EventFiringEnabled = false; a Update()

    X

    X

         

    Zhodnocení

    1. SystemUpdate se chová stejně, ať mu pošlete jakýkoliv parametr. S parametrem true by měl zvednout verzi, ale nedělá to.
    2. Protože posunutí workflow je vnitřně implementováno pomocí event receiverů, mají oba sloupce (Posunutí workflow a Reakce Eventreceiverů) stejné hodnoty v jednotlivých řádcích.
    3. Jako zajímavost hodnotím chování metody SystemUpdate. Neměla by posílat notifikace, ale když ji použijete pro vytvoření položky, notifikace se pošle. Při aktualizaci položky touto metodou se notifikace nepošle.

    Závěr

    Každá metoda se chová trochu jinak a hodí se proto v jiných situacích.

    Z pohledu uživatele je důležité, jestli dostávám notifikace o důležitých změnách. O změnách položek nutných pro běh systému ale mě nepostřehnutelných naopak nechci být informován. Mohou mě to přímo spamovat.

    Také je důležité si při provádění změn rozmyslet, jestli se má jako reakce na změnu posouvat, či spouštět workflow. Pokud ne, je potřeba kód změny zavolat s nastavením EventFiringEnabled na false.

  • Zrušení autohosted módu pro SharePoint apps

    Tohle je téměr měsíc stará informace, která by mohla docela dobře zapadnout. Vzhledem k tomu, že SharePoint 2013 v ČR moc rozšířený zatím není a autohosted mod nebyl nijak rozšířený ani celosvětově, tak se u nás moc "truchlících" asi nenajde.

    Jen pro připomenutí. Autohosted apps byly ty apps, které v sobě obsahovaly kód, který se v rámci nasazení app nasazoval do Azure Web Sites. To s sebou přinášelo dost omezení.

    Pokud se SharePointem 2013 začínáte, tak tuto variantu můžete zatím přeskočit. Zatím píšu záměrně, protože blog Office 365 týmu, který informaci zveřejnil, naznačuje, že to nemusí být navždy. Budou totiž zapracovávat zpětnou vazbu vývojářů a do konce roku slibují něco nového.

    V případě, že nějakou takovou app máte, existuje popis, jak ji přepsat na provider hosted app. To znamená, že dále poběží v Azure, ale do SharePointu se bude instalovat v jiném režimu a její deploy do Azure budete muset řešit samostatně. I v tomto scénáři, tedy provider-hosted app běžící v Azure, slibují další rozvoj a vylepšení. Uvidíme, snad to bude stát za to.

    Běžící autohosted apps zatím nebudou vypínány ani omezovány.

  • Sloupce, vlastnosti a metadata dokumentů

    Tak jsem opět řešil technologickou výzvu SharePointu. Před časem jsem psal článek o procesu mapování sloupců na metadata souborů v SharePointu včetně hodnot. Tentokrát jsem potřeboval vyřešit otázku, jak do SharePointích metadat souboru uložit informace tak, aby neovlivnily obsah souboru. Cílem bylo neporušit elektronické podpisy souborů.

    Je totiž zřejmé, že některé typy sloupců SharePoint “nepropisuje”. Jedná se o typy jako stav workflow (SPFieldWorkflowStatus) a vypočítané sloupce (SPFiedlCalculated). Pokoušel jsem se proto vytvořit sloupce těchto typů, ale první z nich nelze přidat ani programově a do druhého nelze zapisovat hodnoty. Ani vytvoření potomků nepomohlo. U SPFiedlCalculated nelze potomka ani rozmně vytvořit, protože nemá žádný veřejný konstruktor.

    Jako další věc jsem zkoušel zpětně přeložit standardní SPDocumentParser, abych se podíval, čím a jak se řídí. Bohužel je to jen .NET obálka COM objektu a veškerá logika je nedostupná uvnitř COMu. Takže jsem se nic nedozvěděl.

    Použití propertybagu, tedy kolekce Properties taky nevedla k úspěchu ani u Itemu ani u File. V obou případech přidání nového páru klíč-hodnota vedlo k tomu, že pár byl přidán i do metadat souboru, což vedlo ke zneplatnění podpisu.

    Nakonec jsem si ale všiml, že některé vlastnosti z propertybagu mají různé předpony jako “ows_” a “vti_”. Tak jsem to zkusil taky a výsledek se podařil. Při použití prefixu “vti_” v klíči nedojde k přenosu vlastnosti do souboru. Zkusil jsem to i pro název sloupce, ale pokus o přidání sloupce s prefixem “vti_” skončí chybou, že takový sloupec už v seznamu existuje a nelze ho proto přidat. A to i v případě, že za předponou zadáte náhodnou posloupnost znaků, která v knihovně určitě není.

    Je potřeba si ale uvědomit, že jde o chování standardního SPDocumentParseru, který se týká Office dokumentů. Pokud máte v SharePointu registrovaný i jiný document parser, nemusí se chovat stejně. Záleží to na jeho implementaci.

  • Skupiny v SharePointu

    Skupiny mohou pocházet z 3 zdrojů:

    1. SharePointu samotného
    2. Active Directory
    3. Formulářového ověřování – role provider

    Každý z těchto zdrojů má určitá specifika.

    SharePoint skupiny

    Dají se spravovat v SharePointu, tzn., není potřeba práva správce AD. To je někdy výhoda (správci AD klidně spí), někdy nevýhoda. Nemají dosah jinam než v rámci kolekce webů. Pokud je chcete používat v různých kolekcích webů, musíte si je vytvořit několikrát a členy jejich skupin nějak synchronizovat. Časem se může ukázat, že pro vytvořenou skupinu potřebujete navíc nastavit i práva třeba na report serveru nebo disku a to s SP skupinou neuděláte. Můžete si sice vytvořit stejně pojmenovanou v AD, ale nebudou propojené. Skupiny v SP nemohou obsahovat jiné skupiny z SP, mohou ale obsahovat skupiny z AD nebo FBA.

    Active directory skupiny

    Dají se spravovat v AD a používat v několika systémech. Můžete mít jedné skupině udělit práva v SP, použít ji v nějakém procesu a současně jí nastavit práva na Report serveru. AD skupina může obsahovat jinou skupinu. AD skupiny se ještě mohou dělit na:

    • Tzv. security groups – “klasické” skupiny z AD. Primárně slouží k nastavování práv.
    • distribution groups – původně sloužily jako adresáti mailů nějaké skupině adresátů. Maily pak byly doručeny jejím členům. Pochází z Exchange serveru.

    Rozdělení dnes spíše historické, rozdíly mezi nimi se zmenšují. Security skupiny může mít email a sloužit k distribuci emailů a stejně tak dnes můžete distribuční skupině nastavit práva.

    Problém skupin z AD je v tom, že často nejsou v pořádku. Nejsou aktuální, nereflektují strukturu organizace, změny jsou pomalé, … To vede v úvahu spravovat si skupiny samostatně v SP. To ale vede k dalším problémům. Jednak je potřeba udržovat alespoň trochu podobnou strukturu 2x (AD a SP) a druhak se uživatelům nabízí potenciálně 2 stejně nebo podobně pojmenované skupiny. Jedna z AD a druhá z SP. To uživatele pochopitelně mate a zákonem schválnosti si stejně vyberou tu špatnou. Naštěstí se to dá vyřešit omezením nabízených skupin a uživatelů.

    FBA skupiny

    Za jejich správu je zodpovědný RoleProvider. SharePoint se k doménovým a FBA skupinám chová zvláštně. Vidíte je v seznamu skupin (poté, co ji někde v SP použijete), ale když na ni kliknete, zobrazí se vám detail uživatele (stránka /_layouts/userdisp.aspx). Zatímco detaily skupin zobrazuje stránka /_layouts/people.aspx. Souvisí to s tím, že k doménovým a FBA skupinám se SharePoint staví jako k uživatelům. Proto je nenajdete v kolekcích  nebo SPWeb.Groups. Místo toho je najdete v kolekci SPWeb.AllUsers a poznávacím znamením je vlastnost SPUser.IsDomainGroup. A u ní je ale problém v tom, že je true i pro FBA skupiny, takže by se spíše měla jmenovat IsNonSpGroup.

    Zvláštní disciplínou je zjišťování členů skupiny. U SharePoint skupin lze zjistit členy pomocí kolekce SPGroup.Users. Ale i u získaných uživatelů musíte zkontrolovat vlastnost IsDomainGroup, jestli jsou to opravdu uživatelé, nebo “převlečené” AD nebo FBA skupiny. SP skupiny to být naštěstí nemůžou.

    Pro zjišťování členů Active directory skupin a FBA skupin je možné použít metodu

    public static SPPrincipalInfo[] SPUtility.GetPrincipalsInGroup(SPWeb web, string input, int maxCount, out bool reachedMaxCount)
    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

    input parametr je jméno skupiny. U AD skupin stačí zadat jejich jméno. U FBA skupin je potřeba předat v Claims tvaru, tedy: c:0-.f|provider|jménoskupiny, to proto, že z něj SharePoint určí Role providera, u kterého má členy zjistit. Uvedenou metodu lze použít i na SharePoint skupiny. Zmíněnou metodu je nutné volat rekurzivně tak dlouho, až si budete jisti, že vše, co vám vrátila, jsou uživatelé a ne další skupiny.

    Má ale jednu nepříjemnou vlastnost. Jedním z parametrů je maxCount. Tím je možné se bránit tomu, aby rozpad velkých AD skupin netrval nekontrolovaně dlouho. Takže zadáte, kolik jich chcete vrátit maximálně a v posledním out parametru vám SP dá vědět, jestli dosáhl onoho maxima. Bohužel udělá přesně toto. Tzn., pokud jako maxCount zadáte 30 a členů je přesně 30, vrátí vám reachedMaxCount true. Pokud jich bude existovat 31, bude výsledek stejný. Jinými slovy: z hodnoty reachedMaxCount nepoznáte, jestli vám nějaký člen unikl a je potřeba hledat dále, nebo jste je získali všechny a je jich přesně tolik, kolik jste hádali jako maximum. Sad smile

    Na závěr se ještě zmíním o “speciálních” skupinách, které reprezentují:

    • Všechny uživatele SP -
      c:0!.s|true
    • Všechny Windows uživatele -
      c:0!.s|windows
    • Všechny uživatele membership providera (FBA) -
      c:0!.s|forms:membershipprovider

    U nich se členové zmiňovanými způsoby zjišťovat nedají. O to se lze pokusit procházením kolekce SPWeb.AllUsers a testováním tvaru loginu. Jestli obsahuje stejný prefix. Nicméně takto nezjistíte všechny uživatele určitého typu, ale jen ty, kteří byli na webu někdy použiti (ve sloupci typu uživatel nebo mají nastavena práva), nebo na web jako autentizovaní přistoupili.

  • Anonymní přístup do SharePointu

    Anonymní přístup není úplně obvyklý scénář použití SharePointu ve firemním prostředí, ale jsou situace, kdy se bez něj neobejdete. Například v případě, že chcete SharePoint použít jako veřejně dostupný web. Anonymní přístup se dá kombinovat s Windows i formulářovým ověřováním (FBA), včetně jich obou. V takovém případě jste schopni dosáhnout situace, kdy některé části SharePointu jsou dostupné jen Windows ověřeným uživatelům (obvykle interním zaměstnancům), jiné mohou být přístupné uživatelům ověřeným pomocí FBA. A něco můžete zpřístupnit i uživatelům, kteří se nepřihlásí vůbec.

    V tomto článku si ukážeme, jak se anonymní přístup zapíná, konfiguruje a jaké má další vlastnosti.

    Konfigurace

    Zapíná se na úrovni webové aplikace, podobně jako jiná nastavení autentizace.


    Pak je potřeba zapnout přistup na webové aplikaci v Zásadách pro anonymní přístup. Tím se dá umožnit anonymní přístup pouze pro určité zóny. Dá se:

    • žádné - řešit si to budou jednotlivé weby, listy a položky.
    • odepřít zápis – v takovém případě mohou anonymní uživatelé pouze číst. Paušálně pro celou zónu aplikace.
    • odepřít vše - např. chci zakázat anonymní přístup uživatelům intranetu, ale v extranetu povolit.

     

    Nastavování oprávnění

    Na úrovni webů (sekce Oprávnění webů) můžete nastavovat práva jako obvykle.

    Nově ale najdete v ribbonu tlačítko anonymní přístup, které umožní nastavit obecně přístup. Máte následující možnosti:

    • Celý aktuální web – bez přihlášení mohou uživatelé přistupovat jak k seznamům, knihovnám i stránkám. Samozřejmě jen k těm, u kterých to nastavíte v oprávnění.
    • Seznamy a knihovny – anonymní přístup je povolen jen ke knihovnám dokumentů a seznamům. Stejně jako v předchozím bodě se konkrétní přístup nastavuje v oprávněních vybraných seznamů a knihoven.
    • Nic – nepřihlášení uživatelé nemají k této kolekci webů přístup.

    Dokud ho tady nepovolíte, na webech se v nastavení práv nic neobjeví a ani není možnost se na nich nepřihlásit.

     

    Nepřihlášení uživatelé mají v ribbonu nastavování práv seznamů a knihoven dokumentů zvláštní tlačítko Anonymní přístup, podobně jako při nastavování oprávnění webů.

    Na úrovni seznamů se dá nastavovat jen omezený výčet oprávnění:

    • Přidat položky
    • Upravit položky
    • Odstranit položky
    • Zobrazit položky

    Nelze využívat jiných natož vlastních úrovní oprávnění.

    V knihovně lze nastavit jen zobrazení položek.

    Anonymní uživatelé nemohou mít práva na jednotlivé položky. Lze ale využít následujícího triku:
    Anonymní uživatel má přístup na úrovni Omezený přístup. Pokud tedy na seznamu povolíte přístup anonymním uživatelům, ale na konkrétních položkách přerušíte dědění, nebudou mít k těmto položkám anonymní uživatelé přístup.

    Další postřehy:

    • Spuštění WF vyžaduje přihlášení. Jde o to, že stránky ohledně WF vyžadují autentizaci.
    • Anonymní uživatel sice vidí ikonu Otevřít v průzkumníkovi, ale bude ho to nutit přihlásit se.
    • Anonymní uživatel nemůže nastavovat pole uživatel nebo skupina, nemá tam totiž people picker, ale hlášku “Ovládací prvek není k dispozici, protože nemáte příslušná oprávnění”.

    Poznámky z pohledu programátora

    • Dejte si pozor na to, že pokud není uživatel přihlášen, v SPWeb.CurrentUser je null.
    • Jestliže potřebujete vytvořit aplikační stránku, která nebude vyžadovat přihlášení, musíte ji odvozovat od UnsecuredLayoutsBasePage místo LayoutsBasePage a je potřeba přetížit vlastnost AllowAnonymousAccess tak, aby vracela true.
    • Práva anonymním uživatelům se nastavují pomocí AnonymousPermMask64 - to je maska práv. V knihovnách dokumentů platí, že nelze povolit přidávání, editaci a mazáni. I když to v kódu nastavit lze, nebude to fungovat.
    • Vlastnost AnonymousPermMask64 je dostupná pouze na třídách SPWeb a SPList, viz informace o tom, že nelze nastavovat práva na jednotlivých položkách.
    • Pomocí SPList.AnonymousPermMask64 = SPBasePermissions.EmptyMask; odstraníte veškerá práva nepřihlášených uživatelů k objektu.
    • Použití <UserID>, tedy odkaz na aktuálního uživatele, v CAML dotazu způsobí výzvu k přihlášení uživatele.
    • Ve sloupcích Author a Editor jsou hodnoty "-1;#" ze které nevyrobíte objekt typu SPUser.
  • SharePoint 2013 ServicePack 1

    Před časem vyšel service pack pro Office 2013. V rámci balíku service packů vyšel i service pack 1 pro SharePoint.

    Stáhnout jej můžete z této stránky, kde najdete service packy pro jednotlivé verze:

    • SharePoint Foundation
    • SharePoint Server
    • Project Server
    • Office Web Apps

    Upřímně řečeno jsem docela zklamaný z toho, co obsahují. Pročítal jsem k němu KBčka, zkoušel jsem ho, ale nic zásadního z pohledu nových funkcí jsem nenašel. V podstatě jde o:

    • lepší podporu IE 11
    • propojení účtů uživatelů onpremise a OneDrive for Business
    • možnost instalace na Windows 2012 R2. To je ale zatím jen teoretická šance, protože jde o SP1. Takže byste museli nejprve nainstalovat SharePoint na Windows 2012 R2 bez SP, což se vám nepodaří. A pak na něj nainstalovat SP1. Dokud nebude dostupná instalace včetně SP1, není tato novinka použitelná. EDIT – tak instalace včetně SP1 jsou už dostupné viz komentáře. Díky za upozornění.

    Jinak jde vlastně o souhrn všech předchozích kumulativních updatů, tedy opravy chyb. Nicméně i za to jsem rád. Vzhledem ke svým špatným zkušenostem s instalací kumulativních updatů dávám přednost instalaci SP. Detailní popis změn (nejen SharePointu, ale i Office) najdete v tomto excelu.

    Protože už uplynulo několik týdnů od vydání, zdá se, že to dobře otestovali a že se nedočkáme opětovného vydání, případně stažení a opětovného vydání, jako se to stává u kumulativních updatů.

    Instalace sama je rychlá a nesetkal jsem se s žádnými potížemi.

    Takže zálohujte servery, proveďte instalaci na všech strojich ve farmě a nezapomeňte spustit PSConfig.

Více článků Další stránka »

Syndication

News

  • Web Developer
  • Enterprise Application Developer

  • Microsoft Office SharePoint Server 2007, Application Development
  • Microsoft Windows SharePoint Services 3.0, Application Development
  • Microsoft Office SharePoint Server 2007, Configuration
  • Microsoft Windows SharePoint Services 3.0, Configuration
  • .Net Framework 2.0, Distributed Applications
  • .Net Framework 2.0, Web Applications
  • .Net Framework 2.0, Windows Applications
Powered by Community Server (Personal Edition), by Telligent Systems