Knihovna NETGeniumConnection.dll určená pro .NET Framework 4.7.2 | .NET 9 | .NET 10

1. Základní informace

  • Externí funkce slouží k volání vlastního programového kódu v jazyce C# na straně serveru. Výsledkem volání externí funkce je vždy hodnota vyjádřená textovým řetězcem.
  • Externí funkce se používají zejména v případech, kdy:
    • není možné nebo vhodné zajistit požadovanou funkcionalitu prostřednictvím skriptu na straně serveru,
    • je nutné volat serverový kód z JavaScriptu, typicky formou AJAXového požadavku.
  • Pro volání externích funkcí slouží serverová funkce „ngef(string id, string arg0, string arg1, string arg2, ...)“.
    • Povinný parametr „id“ určuje identifikátor externí funkce.
    • Další parametry jsou volitelné a jsou do externí funkce předány jako pole „string[] args“ ve stejném pořadí, v jakém jsou uvedeny při volání.
  • Externí funkce mohou při návrhu aplikací používat pouze administrátoři. Běžný uživatel nemá z uživatelského rozhraní aplikace přímý přístup k jejich volání a externí funkce jsou vždy spouštěny pouze zprostředkovaně prostřednictvím aplikací navržených administrátory.
  • Během provádění externí funkce může dojít k chybě nebo k přerušení jejího běhu. Chování systému v takovém případě závisí na kontextu, ze kterého byla externí funkce vyvolána:
    • Externí funkce spuštěné ze skriptu při chybě nebo přerušení ukončí provádění skriptu. Systém se vrátí do editačního formuláře nebo na nahlížecí stránku, odkud byl skript vyvolán, a uživateli zobrazí chybové hlášení. U skriptů „OnBeforeSave“ a „OnBeforeDelete“ znamená takové přerušení zamezení plánovaného uložení, resp. smazání databázového záznamu.
    • Externí funkce spuštěné z ovládacích prvků „HTML“ nebo „JavaScript“ při chybě nebo přerušení ukončí načítání editačního formuláře nebo nahlížecí stránky a zobrazí chybové hlášení uživateli.
    • Externí funkce spuštěné z ostatních ovládacích prvků při chybě nebo přerušení ukončí pouze načítání dat do daného ovládacího prvku. Chybové hlášení je zobrazeno přímo v tomto ovládacím prvku a načítání ostatních ovládacích prvků není ovlivněno.
  • Externí funkce nejsou dostupné v cloudové variantě NET Genium Online — vlastní knihovnu „ngef.dll“ nelze do cloudu nahrát. Návrhář databázových dotazů proto nenabízí pole „ngef(NETGenium.DataTable)“ a Nastavení NET Genia nezobrazuje seznam veřejných externích funkcí.

2. Knihovna „ngef.dll“

  • Externí funkce jsou součástí knihovny „ngef.dll“ umístěné v adresáři „NETGenium\bin“. Čistá instalace NET Genia má v adresáři „bin“ připravenou výchozí knihovnu „ngef.dll“, která je výsledkem kompilace výchozího zdrojového kódu umístěného v souboru „NETGenium\bin\ngef.cs“.
using System;

namespace NETGenium
{
public class ExternalFunctions
{
public static string ngef(string id, string[] args, bool test, DbCommand cmd, DbConnection conn)
{
if (test) return "";

switch (id)
{
// case "MyFirstFunction": return MyFirstFunction();
default: return conn == null ? "" : conn.ExternalFunctionNotFound(id, cmd);
}
}
}
}
  • Zdrojové kódy externích funkcí využívají objekty a metody z knihovny „NETGeniumConnection.dll“, kterou lze stáhnout z odkazů na začátku této příručky. „NETGeniumConnection.dll“ je knihovna se základními funkcemi pro práci s databází a se souborovými přílohami.
  • Úpravy knihovny „ngef.dll“ je možné provádět pouze prostřednictvím samostatného projektu v aplikaci „Visual Studio 2015“ a vyšší, resp. programováním zdrojových kódů tohoto projektu, a následnou kompilací projektu do knihovny „ngef.dll“.
  • Čistá instalace NET Genia projekt se zdrojovými kódy externích funkcí neobsahuje. Před zahájením programování externích funkcí je nutné vytvořit nový projekt knihovny ve Visual Studiu pomocí následujících kroků, a přidat referenci na knihovnu „NETGeniumConnection.dll“:
    • Spustit Visual Studio
    • Z menu na hlavní liště zvolit „File / New / Project...“ (Ctrl+Shift+N)
      • Project type: Class Library (.NET Framework)
      • Project name: ngef
      • Location: volitelné umístění projektu
      • Solution: Create new solution
      • Place solution and project in the same directory: Ano
      • Create directory for solution: Ne (Visual Studio 2015)
      • Framework: .NET Framework 4.7.2
    • Kliknout pravým tlačítkem na soubor „Class1.cs“, a zvolit „Delete“
    • Kliknout pravým tlačítkem na název projektu „ngef“, zvolit „Add“ / „Existing Item...“ (Shift+Alt+A), a vybrat cestu k souboru „NETGenium\bin\ngef.cs“ na disku počítače
    • Kliknout pravým tlačítkem na „References“, zvolit „Add Reference...“, a vybrat cestu k souboru „References\NETGeniumConnection.dll“ na disku počítače
    • Kliknout pravým tlačítkem na „References“ / „NETGeniumConnection“, zvolit „Properties“ (Alt+Enter), a u atributu „Copy Local“ nastavit hodnotu „False“
    • Zvolit režim kompilace „Debug“
      • Režim „Debug“ ve výchozím nastavení generuje soubory „ngef.dll“ a „ngef.pdb“
      • Díky souboru „ngef.pdb“ se snadno odhalují chyby a přerušení v externích funkcích, protože součástí „Stack Trace“ každé chyby je i název souboru a číslo řádky, na které došlo k přerušení
      • Režim „Release“ se doporučuje až pro finální verzi vyladěných zdrojových kódů v knihovně „ngef.dll“. Ve výchozím nastavení režim „Release“ generuje pouze soubor „ngef.dll“, který je pro NET Genium dostačující, avšak při přerušení je dohledání důvodu vzniklé chyby značně komplikované.
    • Zkompilovat projekt – z menu na hlavní liště zvolit „Build“ / „Build Solution“ (Ctrl+Shift+B)
    • Zkopírovat soubory „ngef.dll“ a „ngef.pdb“ z adresáře „bin\Debug“ do adresáře „NETGenium\bin“ v případě kompilace knihovny v režimu „Debug“, nebo souboru „ngef.dll“ z adresáře „bin\Release“ do adresáře „NETGenium\bin“ v případě kompilace knihovny „ngef.dll“ v režimu „Release“. V případě režimu „Release“ je důležité smazat z adresáře „NETGenium\bin“ soubor „ngef.pdb“.
      • Nahrání nové verze knihovny „ngef.dll“ způsobí vždy restart webové aplikace, stejně jako jakékoliv změna v adresáři „NETGenium\bin“.
  • Zdrojový kód externích funkcí může být libovolně upravován, nesmí však dojít ke změně následujících konvencí v souboru „ngef.cs“:
    • namespace NETGenium
    • public class ExternalFunctions
    • public static string ngef(string id, string[] args, bool test, DbCommand cmd, DbConnection conn)
    • if (test) return "";
    • default: return conn == null ? "" : conn.ExternalFunctionNotFound(id, cmd);
  • Řádek „default“ určuje, co se stane při volání identifikátoru, pro který rozcestník nemá „case“: ve skriptu (objekt „cmd“ není „null“) vyvolá výjimku „The external function ... does not exist!“, mimo skript tento text vrátí jako výsledek. Interní externí funkce volané samotným NET Geniem (kapitola 5), které knihovna neimplementuje, proto nemají žádný účinek – vrácený text nezačíná prefixem „OK\r\n“.

3. Parametry funkce „public static string ngef“

  • string id
    • Identifikátor externí funkce, který jednoznačně určuje funkci či programový kód, spuštěný voláním serverové funkce „ngef(id)“.
    • Pro každý identifikátor je nutné vytvořit samostatný „case“ uvnitř příkazu „switch“ v rozcestníku externích funkcí „public static string ngef“.
  • string[] args
    • Parametry externí funkce, které jsou součástí volání serverové funkce „ngef(id, arg0, arg1, arg2, ...)“ na druhé a další pozici v seznamu parametrů.
    • Seznam parametrů „args“ může mít 0 prvků, pokud volání serverové funkce „ngef(id)“ obsahuje pouze identifikátor externí funkce bez dalších parametrů.
    • Identifikátor „id“ součástí pole „args“ není. Pole „args“ má proto vždy o jeden prvek méně, než kolik parametrů má samotné volání serverové funkce „ngef“. Parametr „arg0“ odpovídá prvku „args[0]“, parametr „arg1“ prvku „args[1]“ a tak dále.
    • Všechny parametry jsou předány jako text, a to i tehdy, mají-li podobu čísla nebo data. Vynechaný parametr je předán jako prázdný řetězec a počet prvků pole „args“ tím není dotčen — volání „ngef(id, A, , C)“ předá pole o třech prvcích, jehož druhý prvek je prázdný řetězec.
    • Mezery na začátku a na konci každého parametru se před předáním odstraní. Parametr, který má obsahovat čárku nebo začínat či končit mezerou, je nutné uzavřít do dvojitých uvozovek – detailní popis je uveden v samostatné příručce Serverové funkce.
    • Serverovou funkci „ngef2“ nelze volat obecně ze skriptu ani z prvku HTML. Zapisuje se jako výchozí hodnota ovládacího prvku „TextBox“ nebo „TextArea“ se zaškrtnutými poli „Jen ke čtení“ a „Skryté pole“; při zobrazení záznamu mimo editační formulář (například v nahlížecí tabulce, stromu, kalendáři, výběrovém dialogu, exportu, tiskové šabloně nebo v těle e-mailu; ne však v exportu se zaškrtnutým polem „Zakázat vyhodnocení externích funkcí“ ani v exportu pro zpětný import z Excelu) se hodnota ve tvaru „ngef2(...)“ přepíše na volání „ngef“, jehož posledním prvkem pole „args“ je ID zobrazovaného záznamu (viz kapitola 10.1). Prázdná hodnota v databázi se výchozí hodnotou nahradí jen při zaškrtnutém poli „Vyplnit výchozí hodnotu při každém otevření editačního formuláře“ a jen tehdy, když výchozí hodnota neobsahuje proměnnou (znak „#“).
  • bool test
    • Logická hodnota „test“ určuje, zda je externí funkce volána z návrháře skriptů pomocí tlačítka „Spustit skript“, nebo při zobrazení či uložení dotazu otevřeného v návrháři databázových dotazů z editačního formuláře – skriptového dotazu formuláře i dotazu ovládacího prvku formuláře. Dotazy ovládacích prvků nahlížecí stránky, včetně skriptového dotazu tlačítka, a podmínky ovládacího prvku „AutoSum“ se při zobrazení a uložení vyhodnocují s hodnotou „false“.
    • Výchozí zdrojový kód externích funkcí obsahuje na prvním řádku funkce „public static string ngef“ příkaz „if (test) return "";“, který zajistí, že nedojde k nechtěnému spuštění externí funkce z návrháře skriptů při ladění skriptu.
    • Při testovacím spuštění skriptu z návrháře skriptů (tlačítko „Spustit skript“) je objekt „cmd“ nastavený na hodnotu „null“ a funkce běží mimo transakci skriptu. Funkce, která objekt „cmd“ používá bez podmínky na parametr „test“, proto v testovacím spuštění skončí chybou.
    • Při zobrazení a uložení dotazu otevřeného v návrháři databázových dotazů z editačního formuláře má parametr „test“ hodnotu „true“ a objekt „cmd“ hodnotu různou od „null“ – jde o databázový příkaz návrháře bez transakce skriptu. Podmínka na parametr „test“ na začátku funkce „public static string ngef“ proto musí zůstat zachovaná.
  • DbCommand cmd
    • Objekt „cmd“ určuje databázový objekt typu „DbCommand“, který slouží pro zápis dat do databáze.
    • Externí funkce spuštěné ze skriptu pomocí serverové funkce „ngef“ používají spolu s ostatními příkazy skriptu jednotný databázový objekt „cmd“, který slouží pro zápis nebo mazání dat z databáze v rámci jedné transakce typu „IsolationLevel.ReadCommitted“.
    • Objekt „cmd“ zapisuje prostřednictvím databázového připojení „cmd.Connection“, kterým je primární připojení skriptu s otevřenou transakcí. Nejde tedy o totéž připojení, jaké je externí funkci předané v parametru „conn“ – to je samostatné připojení bez transakce.
    • Databázové operace provedené prostřednictvím objektu „cmd“ se v databázi projeví až po commitování transakce. K tomu dochází automaticky na konci každého úspěšně provedeného skriptu, nebo zavoláním serverové funkce „COMMIT()“. Ve skriptech „OnBeforeSave“ a „OnBeforeDelete“ se tyto operace potvrdí až na konci transakce, ve které se záznam ukládá, resp. maže – chyba samotného uložení nebo smazání záznamu proto vrátí zpět i zápisy prostřednictvím objektu „cmd“, které nepotvrdila funkce „COMMIT()“, přestože skript doběhl bez chyby. Detailní popis je uveden v samostatné příručce Editační formulář – ActionButtons.
    • Jakákoliv chyba nebo přerušení během vykonávání externí funkce či samotného skriptu zajistí „rollback“ všech databázových operací provedených prostřednictvím objektu „cmd“, které dosud nepotvrdila serverová funkce „COMMIT()“.
    • Ukončí-li externí funkce volaná ze skriptu odpověď sama (vyvoláním EndResponseException), skript skončí bez chybového hlášení, ale jeho transakce se nepotvrdí: databázové operace provedené prostřednictvím objektu „cmd“ a zapisující příkazy skriptu, které dosud nepotvrdila serverová funkce „COMMIT()“, se vrátí zpět, ve skriptu „OnBeforeSave“ se záznam neuloží a ve skriptu „OnBeforeDelete“ se nesmaže.
    • Používání objektu „cmd“ se nehodí v případech hromadných importů dat, nebo obecně v případech, kdy není vyžadovaný zápis dat v rámci transakce. Obvyklé změny dat prostřednictvím objektu „cmd“ obsahují maximálně jednotky příkazů zápisů nebo mazání záznamů.
    • Používání objektu „cmd“ může způsobit „deadlock“ databáze. Během práce s objektem je důležité vždy nejdříve všechno potřebné z databáze načíst, a teprve potom do databáze zapisovat. Deadlock vzniká v situacích, kdy programátor nejdříve zapíše data do databázové tabulky, a následně se snaží z té samé databázové tabulky číst.
      • Dokud není transakce potvrzena, drží zapsané záznamy zamčené, a ostatní databázová připojení na tento zámek narazí. Jak se to projeví, závisí na databázovém serveru, jeho verzi a nastavení, i na verzi klientské knihovny – čtení nebo zápis může čekat, dokud transakce neskončí, může skončit chybou o konfliktu, nebo může proběhnout a vrátit poslední potvrzená data, tedy stav před zápisem. Stejně tak se liší rozsah zámku, od jednotlivého záznamu až po celou databázovou tabulku.
      • Na žádnou z těchto variant se nelze spoléhat, a nelze je ani odvodit z chování ověřeného na jedné konkrétní instalaci – jiná verze databázového serveru se zachová jinak. Jedinou spolehlivou obranou je pořadí „nejdříve načíst, potom zapisovat“.
      • Ve skriptu „OnBeforeSave“ trvá zámek zápisu prostřednictvím objektu „cmd“ až do uložení záznamu. Má-li editační formulář textové pole typu Integer nebo Long s výchozí hodnotou „Max + 1“ (v kterékoli variantě), čte NET Genium při uložení nového záznamu (u existujícího záznamu jen se zaškrtnutým vyplňováním výchozí hodnoty při každém otevření formuláře nebo před každým uložením) po skončení skriptu tabulku ukládaného formuláře samostatným připojením mimo transakci, aby určilo další číslo řady, a na zámek může narazit. Externí funkce ve skriptu „OnBeforeSave“ proto nemá do tabulky ukládaného formuláře zapisovat prostřednictvím objektu „cmd“; je-li zápis nutný, pomůže volání funkce „COMMIT()“ hned za externí funkcí, nebo zápis mimo transakci skriptu.
    • Kdykoliv není nutný zápis do databáze v rámci jednotné transakce spolu se skriptem, doporučuje se používat vlastní objekt „cmd“ – například pomocí příkazu „using (DbCommand cmd = new DbCommand(conn)) {}“.
    • Externí funkce spuštěná z jiného místa než ze skriptu, má objekt „cmd“ nastavený na hodnotu „null“; výjimkou je zobrazení a uložení dotazu otevřeného v návrháři databázových dotazů z editačního formuláře popsané u parametru „test“.
  • DbConnection conn
    • Objekt „conn“ určuje databázový objekt typu „DbConnection“, který reprezentuje připojení do databáze NET Genia, a slouží pro čtení nebo zápis dat do databáze.
    • Externí funkce spuštěné ze skriptu mají v objektu „conn“ samostatné databázové připojení bez transakce, které NET Genium používá po celou dobu běhu skriptu pro čtení dat. Zápisy prováděné v rámci transakce skriptu jdou naproti tomu přes připojení „cmd.Connection“ – viz popis parametru „cmd“.
    • Rozdělení rolí obou objektů je proto jednoznačné – prostřednictvím objektu „conn“ se čte, a prostřednictvím objektu „cmd“ se zapisuje v rámci transakce skriptu. Obě připojení jsou z pohledu databáze dva různí klienti, takže zámky držené nepotvrzeným zápisem prostřednictvím objektu „cmd“ blokují čtení prostřednictvím objektu „conn“. Vždy je tedy nutné nejdříve načíst všechna potřebná data, a teprve potom zapisovat.
    • Externí funkce spuštěná z jiného místa než ze skriptu má v objektu „conn“ připojení volajícího kontextu a objekt „cmd“ nastavený na hodnotu „null“ – čtení i případný zápis prostřednictvím vlastního objektu „cmd“ tedy probíhají přes totéž připojení „conn“.
    • Interní externí funkce „NETGenium.CSS“ a „NETGenium.Log“ dostávají objekt „conn“ s hodnotou „null“.

4. Ladění externích funkcí v konzolové aplikaci

  • Nejpohodlnějším způsobem psaní externích funkcí je návrh prototypu externí funkce v konzolové aplikaci, a následné zkopírování vyladěného zdrojového kódu do projektu knihovny „ngef.dll“.
  • Kompilace a spuštění konzolové aplikace jsou velmi rychlé, a umožňují snadné ladění a trasování buď pomocí „breakpointů“, nebo pomocí vypisování informací do konzole příkazem „Console.WriteLine()“.
  • Při návrhu externí funkce je důležité zvolit deklaraci nové externí funkce tak, aby se výsledný zdrojový kód dal snadno přenést pomocí „Ctrl+C“ a „Ctrl+V“ do projektu knihovny „ngef.dll“.

4.1. Vytvoření konzolové aplikace

  • V prvním kroku je nutné vytvořit nový projekt konzolové aplikace ve Visual Studiu pomocí následujících kroků, a přidat referenci na knihovnu „NETGeniumConnection.dll“:
    • Spustit Visual Studio
    • Z menu na hlavní liště zvolit „File / New / Project...“ (Ctrl+Shift+N)
      • Framework: .NET Framework 4.7.2
      • Project Type: Console Application
      • Name: ConsoleApp1
      • Location: volitelné umístění projektu
      • Solution: Create new solution
      • Create directory for solution: Ne
      • Add to Source Control: Ne
    • Kliknout pravým tlačítkem na „References“, zvolit „Add Reference...“, a vybrat cestu k souboru „References\NETGeniumConnection.dll“ na disku počítače
    • Zvolit režim kompilace „Debug“
    • Spustit projekt – z menu na hlavní liště zvolit „Debug“ / „Start Debugging“ (F5)

4.2. Simulace prostředí NET Genia

  • Ve druhém kroku je nutné upravit výchozí zdrojový kód v souboru „Program.cs“ tak, aby konzolová aplikace simulovala prostředí NET Genia, které spouští externí funkce voláním „public static string ngef“ s parametry „args“, „cmd“ a „conn“.
using NETGenium;
using System;

namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
NETGeniumConsole console = new NETGeniumConsole();

using (DbConnection conn = new DbConnection(@"driver=firebird;datasource=localhost;user=SYSDBA;password=masterkey;database=C:\Firebird\netgenium.fdb;charset=WIN1250;collation=WIN_CZ"))
// using (DbConnection conn = new DbConnection("server=(local);Trusted_Connection=true;database=netgenium"))
using (DbCommand cmd = new DbCommand(conn))
{
conn.Open();
conn.RootPath = "C:\\inetpub\\wwwroot\\netgenium";
console.WriteLine(MyFirstFunction(new string[] { "a", "b", "c" }, cmd, conn));
}

console.Exit();
}

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
return "Hello World! args: " + string.Join(";", args);
}
}
}

4.3. Psaní zdrojového kódu externí funkce

  • Ve třetím kroku je pak možné psát již samotný zdrojový kód externí funkce „MyFirstFunction“.

4.4. Volání externí funkce přes webové služby

  • Aplikace připojená do NET Genia přes webové služby (objekt „NETGeniumConnection“) může zavolat externí funkci metodou „ngef(string id, string[] args)“; metoda vrací návratovou hodnotu externí funkce.
  • Externí funkce se spustí jen tehdy, je-li zařazená do seznamu veřejných externích funkcí v Nastavení NET Genia, nebo povolí-li její volání externí funkce NETGenium.RegisterExternalFunction návratovou hodnotou s prefixem OK\r\n (kapitola 5.34). Jinak volání skončí chybou.
  • Externí funkce běží pod uživatelem přihlášeným přes webové služby; nelze-li uživatele podle přihlášení určit, běží pod anonymním uživatelem.
  • Externí funkce se volá s parametrem „test“ s hodnotou „false“ a objektem „cmd“ s hodnotou „null“. Parametry se předávají tak, jak je poslal klient, bez ořezání mezer.
  • Cloudová varianta NET Genium Online webové služby nepodporuje.

5. Interní externí funkce volané samotným NET Geniem

  • Následující externí funkce nevolá uživatelský skript, ale přímo framework NET Genium.
  • Jsou volány automaticky v přesně definovaných situacích.
  • Externí funkce mohou vracet řetězec. Pokud má být návratová hodnota zpracována, musí začínat prefixem: OK\r\n
  • Za tímto prefixem následuje vlastní obsah (HTML, JavaScript, CSS, barva, hodnota, cesta k souboru apod.). Výjimky z tohoto pravidla jsou uvedeny u příslušné funkce.
  • Interní externí funkce se volají vždy s objektem „cmd“ nastaveným na hodnotu „null“, tedy mimo transakci.

5.1. NETGenium.Campaigns.Image

  • Spustí se při zobrazení stránky Campaigns/Image.aspx?guid, ke kterému dojde při pokusu o přečtení emailu díky obrázku, který se odkazuje právě na Image.aspx
  • Obrázek vkládá do e-mailu implementace, která e-maily kampaně odesílá, například:
    • string image = "<img src=\"" + url + "/Image.aspx?" + guid + "\">";
  • Stránka je přístupná bez přihlášení. Funkce běží pod uživatelem, který je v daném prohlížeči přihlášený do NET Genia, jinak pod uživatelem bez účtu (ID 0, prázdné přihlašovací jméno, výchozí jazyk).
  • args = new string[] { queryString }
  • Parametr args[0] obsahuje celý query string stránky (text za otazníkem) bez dekódování. Poslat ho může kdokoli, proto je nutné s ním zacházet jako s nedůvěryhodným vstupem – do SQL dotazu ho vkládat jen přes conn.Format(...). Je-li query string prázdný, funkce se nevolá.
  • Výjimka ve funkci ukončí zobrazení stránky chybou.
  • Návratová hodnota funkce se nepoužívá; stránka vždy vrátí průhledný obrázek o rozměru 1×1 px.

5.2. NETGenium.Campaigns.Unsubscribe

  • Spustí se při zobrazení stránky Campaigns/Unsubscribe.aspx?guid, ke kterému dojde při kliknutí uživatele na odkaz v emailu
  • Odkaz vkládá do e-mailu implementace, která e-maily kampaně odesílá, například:
    • string link = "<a href=\"" + url + "/Unsubscribe.aspx?" + guid + "\">Odhlásit</a> se z těchto emailů...";
  • Stránka je přístupná bez přihlášení; uživatel, pod kterým funkce běží, a obsah args[0] jsou stejné jako u funkce NETGenium.Campaigns.Image (kapitola 5.1). Výjimka ve funkci ukončí zobrazení stránky chybou.
  • Funkce se zavolá při každém otevření odkazu, bez potvrzení. Odhlášení z odběru proto proběhne i tehdy, když odkaz otevře bezpečnostní skener pošty nebo náhled zprávy.
  • args = new string[] { queryString }
  • Funkce může vracet html, které se zobrazí přes celou stránku, řetězec musí začínat OK\r\n

5.3. NETGenium.Campaigns.View

  • Spustí se při zobrazení stránky Campaigns/View.aspx?guid, ke kterému dojde při kliknutí uživatele na odkaz v emailu
  • Odkaz vkládá do e-mailu implementace, která e-maily kampaně odesílá, například:
    • string link = "<a href=\"" + url + "/View.aspx?" + guid + "\">Zobrazit ve webovém prohlížeči...</a>";
  • Stránka je přístupná bez přihlášení; uživatel, pod kterým funkce běží, a obsah args[0] jsou stejné jako u funkce NETGenium.Campaigns.Image (kapitola 5.1). Výjimka ve funkci ukončí zobrazení stránky chybou.
  • args = new string[] { queryString }
  • Funkce může vracet html, které tvoří celou odpověď stránky, řetězec musí začínat OK\r\n

5.4. NETGenium.Copyright

  • Spustí se v navigátoru (na stránce Apps.aspx nebo App.aspx) při každém zobrazení navigátoru, a umožňuje nahradit copyright za libovolný html kód
  • Funkce musí vracet html, např. OK\r\nhtml

5.5. NETGenium.CSS

  • Spustí se před uložením CSS souboru na disk a při náhledu vzhledu, a to zvlášť pro každý prohlížeč a směr textu
  • args = new string[] { value, browser.ToString() }
    • Druhý argument nese prohlížeč, pro který se CSS sestavuje: Default, IE, CE, IE10, IE11, IE11Mobile, Edge, EdgeMobile, Chrome, ChromeMobile, Firefox, FirefoxMobile, Safari nebo SafariMobile
  • Objekt „conn“ má hodnotu „null“; výjimka se ignoruje
  • Funkce musí vracet změněné CSS, řetězec musí začínat OK\r\n

5.6. NETGenium.DataGrid2Excel

  • Spustí se po exportu dat z datagridu tak, aby bylo možné vyexportovaný soubor otevřít a pozměnit
    • Běžný datagrid – pouze u formátu "xlsx"
    • Statistický datagrid – umožnuje pouze formát "xlsx" bez možnosti volby
  • args = new string[] { excel.path, "Q" + qb.ID, qb.Form.ID.ToString(), qb.date1, qb.date2 }
  • Datumy mohou být prázdné
  • Návratová hodnota funkce se nepoužívá

5.7. NETGenium.DataTable

  • Spustí se při načtení dat z databáze, a umožňuje změnit načtená data těsně před jejich vyrenderováním
  • Spouští se jen u dotazu se zaškrtnutým polem „ngef(NETGenium.DataTable)“, a to u ovládacích prvků, tisku i exportu, které dotaz používají (kromě exportu se zaškrtnutým polem „Zakázat vyhodnocení externích funkcí“ a exportu pro zpětný import z Excelu), a také u dotazů ve skriptu, ve výběrovém dialogu a v adresáři pro výběr příjemců e-mailové zprávy („Vybrat příjemce z adresáře...“)
  • Nespouští se u dotazu hodnot ovládacích prvků „ComboBox“, „ListBox“, „Radio“ a „MultiListBox“ (ani u nabídky hodnot při změně hodnoty v nahlížecí tabulce), u dotazu výchozí hodnoty ovládacího prvku, u dotazu, ze kterého přebírají text ovládací prvky „Title“ a „RichText“, a u dotazu nápovědy ovládacího prvku
  • Funkce se volá s parametrem „test“ s hodnotou „false“, a to i při testovacím spuštění skriptu
  • args = new string[] { "Q" + qb.ID, form.ToString(), date1, date2 } – prvek Planner doplňuje navíc typ zobrazení
  • Načtená data jsou v objektu conn.Container2[args[0]] typu „DataTable“; sloupce běžné nahlížecí tabulky se jmenují „c“ + ID ovládacího prvku, sloupce statistické nahlížecí tabulky „c“ + pořadí sloupce
  • Návratová hodnota funkce se nepoužívá
  • Více v příručce Návrhář databázových dotazů

5.8. NETGenium.Download

  • Spustí se při stažení přílohy
  • args = new string[] { id.ToString(), filename, path }
  • Funkce může vracet výslednou cestu k souboru na disku, který bude použit místo původního souboru, řetězec musí začínat OK\r\n

5.9. NETGenium.Elearning.Test.ERROR

  • Spustí se po vyhodnocení testu, ve kterém alespoň jedna otázka nebyla zodpovězena správně, a to bez ohledu na celkové hodnocení testu (prospěl / neprospěl)
  • args = new string[] { test["id"].ToString(), sb_ok.ToString(), sb_ko.ToString(), sb_db.ToString() }
    • test["id"].ToString() - ID testu
    • sb_ok.ToString() - seznam ID oddělených středníkem správně zodpovězených otázek
    • sb_ko.ToString() - seznam ID oddělených středníkem špatně zodpovězených otázek
    • sb_db.ToString() - HTML testu včetně otázek a odpovědí, který se ukládá do databázové tabulky ng_eltestvysl do sloupce ng_test0
  • Funkce může vracet html, které se zobrazí místo zprávy o výsledku testu, řetězec musí začínat OK\r\n

5.10. NETGenium.Elearning.Test.OK

  • Spustí se po vyhodnocení testu, ve kterém byly všechny otázky zodpovězeny správně
  • args = new string[] { test["id"].ToString(), sb_ok.ToString(), sb_ko.ToString(), sb_db.ToString() }
    • test["id"].ToString() - ID testu
    • sb_ok.ToString() - seznam ID oddělených středníkem správně zodpovězených otázek
    • sb_ko.ToString() - seznam ID oddělených středníkem špatně zodpovězených otázek
    • sb_db.ToString() - HTML testu včetně otázek a odpovědí, který se ukládá do databázové tabulky ng_eltestvysl do sloupce ng_test0
  • Funkce může vracet html, které se zobrazí místo zprávy o výsledku testu, řetězec musí začínat OK\r\n

5.11. NETGenium.ExcelPassword

  • Spustí se před uzamčením listů excelového souboru vytištěného z tiskové šablony se zapnutým uzamčením
  • args = new string[] { }
  • Funkce musí vracet heslo pro uzamčení listů excelového souboru, řetězec musí začínat OK\r\n
  • Jde o ochranu listů proti úpravám, nikoli o zašifrování souboru – soubor lze otevřít bez hesla. Nevrátí-li funkce heslo, použije se výchozí heslo NET Genia, které je stejné ve všech instalacích – uzamčení pak brání jen nechtěné úpravě, ne úpravě úmyslné
  • Šablony ve formátu Word se uzamykají bez hesla a funkci nevolají

5.12. NETGenium.Import

  • Spustí se při zobrazení stránky Import.aspx, a to i pro nepřihlášeného uživatele
  • V demo režimu (konfigurační soubor „Demo.txt“) a v režimu pouze pro čtení v NET Genium Online se funkce nespustí a stránka vrátí prázdnou odpověď
  • args = new string[] { }
  • Funkce může vracet html, které se vloží do response; prefix OK\r\n není potřeba
  • Pokud funkce nic nevrátí, do response se uloží prázdný string

5.13. NETGenium.ImportXml

  • Spustí se při nahrání ZIP souboru na stránku ImportXml.aspx, a to jednou pro první soubor archivu, který musí obsahovat XML dataset pojmenovaný zašifrovaným ID session přihlášeného uživatele; ostatní soubory archivu se ignorují a v jednom požadavku se zpracuje jen první nahraný soubor
  • V demo režimu (konfigurační soubor „Demo.txt“) a v režimu pouze pro čtení v NET Genium Online se funkce nespustí a stránka vrátí prázdnou odpověď
  • Načtený dataset je uložen v objektu conn.Container
  • args = new string[] { }
  • Funkce může vracet html, které se vloží do response; prefix OK\r\n není potřeba
  • Pokud funkce nic nevrátí, do response se uloží prázdný string
  • Skončí-li zpracování výjimkou (i výjimkou vyvolanou funkcí), uloží se do response obecná chybová hláška a výjimka se zapíše do logu chyb; text výjimky se volajícímu nevrací

5.14. NETGenium.LockRecord

  • Spustí se po úspěšném zamknutí databázového záznamu, a znovu při každém obnovení zámku otevřeným editačním formulářem
  • Nespustí se, drží-li zámek jiné okno prohlížeče, a to i okno téhož uživatele, ani pro tichého uživatele. Nespustí se ani při otevření záznamu, jehož zámek už drží session uživatele; spustí se až při obnovení zámku
  • args = new string[] { form.ToString(), id.ToString() }
  • Návratová hodnota funkce se nepoužívá

5.15. NETGenium.Log

  • Spustí se po zápisu systémového logu NET Genia na disk; zápisy metodami L.E, L.W a L.N funkci nespouštějí
  • args = new string[] { filenameWithoutExtension, message, logLevel.ToString(), loginname }
  • Objekt „conn“ má hodnotu „null“; výjimka se ignoruje

5.16. NETGenium.LoginCode

  • Spustí se po nalezení uživatele při každém přihlášení pomocí uživatelského jména a hesla
  • Při přihlášení přes Microsoft, Google, Facebook nebo Apereo, přes Windows, přihlašovacím ticketem ani tokenem přes integrovaný MCP server se funkce nespustí – dvoufaktorové ověření NET Genia se na tato přihlášení neuplatní a u přihlášení přes poskytovatele identity ho musí zajistit poskytovatel
  • args = new string[] { userid.ToString(), loginname }
  • Funkce může zahájit dvoufaktorové ověření – pokud vrátí řetězec, který nezačíná prefixem OK\r\n, dvoufaktorové ověření se přeskočí
  • Při přihlášení přes webové služby knihovny NETGeniumConnection se funkce spustí také; vrátí-li řetězec s prefixem OK\r\n, přihlášení se odmítne, protože tento přístup autentizační kód zadat neumí. Odesílá-li funkce kód sama (SMS, e-mail), odešle ho i při takovém přihlášení – služby a konzolové aplikace proto mají používat účet, u kterého funkce dvoufaktorové ověření nezahájí
  • Při přihlášení stránkou Login.aspx (metoda Uploader.Login_aspx knihovny NETGeniumConnection) se funkce spustí také; vrátí-li řetězec s prefixem OK\r\n, přihlášení se neprovede a stránka místo potvrzení vrátí HTML zprávu funkce, případně výchozí systémovou hlášku, protože ani tento přístup autentizační kód zadat neumí
  • Vrácený řetězec musí začínat OK\r\n, za nímž framework očekává autentizační kód, který automaticky uloží do session
  • Volitelně za dalším \r\n může následovat HTML zpráva zobrazená uživateli (např. instrukce nebo QR kód)
  • Pokud HTML zpráva chybí, zobrazí se výchozí systémová hláška: "Autentizační kód vám bude doručen na váš mobilní telefon."

5.17. NETGenium.ValidateLoginCode

  • Spustí se pro ověření autentizačního kódu zadaného uživatelem v rámci dvoufaktorového přihlášení
  • args = new string[] { secret, code, loginname }
    • secret – kód vrácený funkcí NETGenium.LoginCode (bez prefixu OK\r\n a bez HTML zprávy)
    • code – kód zadaný uživatelem
    • loginname – přihlašovací jméno uživatele
  • OK\r\n – kód je platný, přihlášení pokračuje
  • OK\r\n<chybová hláška> – kód je neplatný, uživateli se zobrazí hláška
  • jakýkoli řetězec bez prefixu OK\r\n (i výsledek neimplementované funkce) – použije se výchozí porovnání (secret == code)
  • Po pátém neplatném kódu se přihlášení vrátí na zadání uživatelského jména a hesla; při dalším přihlášení se funkce NETGenium.LoginCode spustí znovu, pokud přihlašování není zablokované – chybné kódy se započítávají mezi neplatné pokusy o přihlášení

5.18. NETGenium.OnAfterLogout

  • Spustí se po odhlášení uživatele odkazem pro odhlášení v záhlaví nebo v menu a také tlačítkem „Odhlásit“ v dialogu „Změna hesla“, kde se vrácený javascript provede v tomto dialogu a za ním se vždy obnoví okno portálu – text „location“ tam výchozí obnovení nevynechá
  • args = new string[] { }
  • Funkce může vracet javascript, např. OK\r\nalert('Prave se odhlasil uzivatel...'); - řetězec tedy musí začínat OK\r\n
  • Vrácený javascript se po odhlášení provede v prohlížeči. Obsahuje-li odpověď text „location“, výchozí přesměrování na přihlašovací stránku se vynechá a vlastní přesměrování zajistí funkce přiřazením do location; jinak se po provedení javascriptu přesměruje na přihlašovací stránku

5.19. NETGenium.Menu

  • Spustí se v navigátoru (na stránce Apps.aspx nebo App.aspx) při každém zobrazení navigátoru, a umožňuje vložit na začátek stránky libovolný html kód
  • Funkce musí vracet html, např. OK\r\nhtml

5.20. NETGenium.Menu1

  • Spustí se v editačním formuláři, na nahlížecí stránce, v portletech a v dalších stránkách uživatelského režimu, jen pokud portál používá rozvržení bez rámů (NoFrames) a stránka není otevřena ve výběrovém dialogu
  • args = new string[] { }
  • Funkce musí vracet html, které nahradí výchozí menu na začátku stránky, např. OK\r\nhtml

5.21. NETGenium.Menu2

  • Spustí se za stejných podmínek jako NETGenium.Menu1, a to jen tehdy, pokud NETGenium.Menu1 vrátila řetězec s prefixem OK\r\n
  • Spustí se také v navigátoru, kde se výsledek vloží před copyright
  • args = new string[] { }
  • Funkce musí vracet html, které se vloží na konec stránky, např. OK\r\nhtml

5.22. NETGenium.OnAfterLogin

  • Spustí se po úspěšném přihlášení uživatele v prohlížeči – jménem a heslem, přes Active Directory i přes Microsoft, Google, Facebook nebo Apereo; nespustí se pro anonymního uživatele
  • Nespustí se při přihlášení MCP tokenem, přes webové služby knihovny NETGeniumConnection ani přes vlastní API – zamezení přihlášení touto funkcí se proto na tyto přístupy nevztahuje; přístup účtu se tam omezuje jeho uživatelskými skupinami, u webových služeb také blokováním přihlašování po opakovaných neplatných pokusech a u MCP tokenu a vlastního API smazáním nebo vypršením tokenu
  • Umožňuje spustit javascript v prohlížeči klienta pomocí return "OK\r\n", za kterým následuje samotný javascriptový kód např. return "OK\r\nalert('Welcome...');"
  • Při přihlášení přes Microsoft, Google, Facebook nebo Apereo se vrácený javascript spustí na jinak prázdné stránce místo přesměrování do portálu, takže o další navigaci musí rozhodnout javascript sám
  • Spustí se i při přihlášení přihlašovacím ticketem, vrácený javascript se tam ale neprovede. Zamezit přihlášení ticketem jen vráceným javascriptem proto nelze – vzor v kapitole 14.2 navíc ukončí session
  • Spustí se i při přihlášení stránkou Login.aspx (metoda Uploader.Login_aspx knihovny NETGeniumConnection); vrácený javascript se tam neprovede a přihlášení se dokončí, takže mu vráceným javascriptem zamezit nelze
  • Spustí se i při automatickém přihlášení přes Active Directory při otevření nahlížecí stránky nebo stránky Portlets.aspx adresou s parametrem „autologin“; vrácený javascript se tam neprovede a přihlášení se dokončí, takže mu vráceným javascriptem zamezit nelze

5.23. NETGenium.OnAfterPrint

  • Spustí se ihned po tisku do tiskové šablony, a to pro každý vytištěný dokument zvlášť – při tisku z nahlížecí stránky nebo editačního formuláře i při tisku do přílohy ze skriptu – takže je možné soubor pomocí externí funkce ještě zmodifikovat
  • Při tisku záznamu je tištěný záznam zaregistrován v objektu „conn“, takže conn["ng_..."] vrací jeho hodnoty. Při tisku z nahlížecí stránky to platí jen pro šablony ve formátech Wordu a ve formátu „pdf“, u kterých se každý záznam tiskne do samostatného dokumentu; u šablon ve formátech „txt“, „csv“, „htm“, „html“ a u excelových šablon vrací conn["ng_..."] hodnotu null
  • conn.PrintingProcess.FilePath - cesta k souboru, do kterého se tiskne; u formátů „txt“, „csv“, „htm“ a „html“ je null (s výjimkou dokumentu vytvářeného položkou „Nový ze šablony“) a soubor se zapíše až po návratu z funkce z obsahu conn.PrintingProcess.Content
  • conn.PrintingProcess.FileName - název souboru, který bude uživateli nabídnut ke stažení - možno změnit
  • conn.PrintingProcess.Template - název tiskové šablony
  • conn.PrintingProcess.Content - obsah tištěného souboru u šablon ve formátech „txt“, „csv“, „htm“ a „html“ - možno změnit; u ostatních formátů je null
  • conn.PrintingProcess.Form - ID formuláře ze kterého byl tisk spuštěn
  • conn.PrintingProcess.ViewPage - ID nahlížecí stránky, ze které byl tisk spuštěn
  • conn.PrintingProcess.SaveAs - způsob dokončení dokumentu; přiřazením objektu „SaveAsPdf“ se dokument dokončí jako PDF včetně převodu z HTML, podložení hlavičkového papíru, číslování stránek a vložení příloh
  • Návratová hodnota funkce se nepoužívá; výjimka ukončí tisk chybovým hlášením
  • Funkce smí odpověď ukončit sama (např. odesláním vlastního obsahu klientovi a vyvoláním EndResponseException); tisk pak už nepokračuje a framework to nepovažuje za chybu
  • Detailní popis programování tiskových šablon ve formátu „pdf“ je uveden v samostatné příručce Programování tiskových šablon ve formátu PDF.

5.24. NETGenium.OnBeforeLogin

  • Spouští se v následujících situacích:
    • Přihlášení pomocí uživatelského jména a hesla: args = new string[] { "", loginname, password }
      • Externí funkce se spustí těsně před pokusem o autentizaci uživatele (nalezením jeho uživatelského jména v tabulce "susers" ve sloupci "loginname"), a
      • umožňuje zamezit přihlášení uživatele a případně i spustit javascript v prohlížeči klienta pomocí return "OK\r\n", za kterým může následovat samotný javascriptový kód např. return "OK\r\nalert('Sorry...');", nebo
      • umožňuje ovlivnit autorizaci uživatele – funkce může zajistit externí autorizaci uživatele v LDAP, Azure Active Directory apod., a podle výsledku přenastavit seznam jeho uživatelských skupin.
    • Automatické přihlášení díky Active Directory (WindowsAuthentication) a LoginByIdentity.txt: args = new string[] { account }
      • Externí funkce se spustí těsně před přihlášením uživatele po jeho úspěšné autentizaci, a
      • umožňuje ovlivnit autorizaci uživatele – funkce může zajistit externí autorizaci uživatele v LDAP apod., a podle výsledku přenastavit seznam jeho uživatelských skupin.
    • Přihlášení přes Microsoft (LoginByMicrosoft.aspx), Google, Facebook nebo Apereo: args = new string[] { email }
      • U Apereo bez e-mailové adresy obsahuje args[0] identifikátor uživatele „sub“ a uživatel se pak nehledá ve sloupci „email“, ale ve sloupci „account“ (pole „Účet systému Windows“) jako identifikátor „sub“ s předponou „AD\“
      • Externí funkce se spustí po úspěšné autentizaci uživatele u poskytovatele identity, a těsně před pokusem o nalezení jeho emailové adresy v tabulce "susers" ve sloupci "email", a
      • umožňuje zamezit přihlášení uživatele tím, že smaže jeho uživatelský účet v tabulce "susers", nebo
      • umožňuje ovlivnit autorizaci uživatele - funkce může zajistit externí autorizaci uživatele v Azure Active Directory apod., a podle výsledku přenastavit seznam jeho uživatelských skupin.
  • Návratová hodnota s prefixem OK\r\n se vyhodnocuje jen při přihlášení jménem a heslem; při automatickém přihlášení přes Active Directory a přes poskytovatele identity se návratová hodnota nepoužívá.
  • Při přihlášení stránkou Login.aspx (metoda Uploader.Login_aspx knihovny NETGeniumConnection) návratová hodnota s prefixem OK\r\n přihlášení zamezí, vrácený javascript se ale neprovede a stránka vrátí hlášku „Neplatné přihlášení!“.
  • Funkce se nespustí při přihlášení MCP tokenem, přes webové služby knihovny NETGeniumConnection, přes vlastní API ani přihlašovacím ticketem (adresou s ticketem z tabulky „slogintickets“) – externí autorizace uživatele touto funkcí se proto při přihlášení ticketem neprovede.
  • Při přihlášení jménem a heslem se před spuštěním funkce ověřuje limit chybných pokusů o přihlášení. Je-li pro dané uživatelské jméno překročený, přihlášení se odmítne a funkce se nespustí.
  • Při dvoufaktorovém ověření (NETGenium.LoginCode) se funkce spustí v obou krocích přihlášení jménem a heslem – po zadání jména a hesla i po zadání autentizačního kódu, v přihlašovacím okně i v dialogu „Změna hesla“. Návratová hodnota s prefixem OK\r\n se v obou krocích vyhodnotí stejně a limit chybných pokusů o přihlášení se ověřuje před každým spuštěním.
  • Odmítne-li přihlášení sama funkce (návratovou hodnotou s prefixem OK\r\n), NET Genium pokus mezi chybné pokusy o přihlášení nezapočítá. Ověřuje-li funkce heslo v externím systému a neplatné heslo odmítá sama, musí ochranu proti hádání hesel zajistit tento externí systém.
  • Typickým důvodem pro modifikaci externí funkce NETGenium.OnBeforeLogin je snaha o autorizaci uživatele v externí aplikaci, která používá systém uživatelských rolí (povolené činnosti uživatele v informačním systému):
    • LDAP – seznam uživatelských rolí se zjišťuje voláním webových služeb LDAP
    • Azure Active Directory – seznam uživatelských rolí se zjišťuje voláním webových služeb Microsoft Graph API, nebo je seznam uživatelských rolí součástí položek přihlašovacího tokenu (id_token), které NET Genium při přihlášení uživatele přes Microsoft ukládá do session objektu "microsoft_claims" jako pole objektů Claim (role jsou položky typu "roles", případně "GroupsName"); session objekt "microsoft_access_token" nese přístupový token pro volání Microsoft Graph API
  • Ekvivalentem uživatelských rolí v externí aplikaci jsou naše uživatelské skupiny
    • Uživatel může být členem žádné, jedné, nebo více uživatelských skupin najednou
    • Uživatelská role v NET Geniu je definována jako uživatelská skupina se zaškrtnutým polem "Role" - na začátek názvu uživatelské skupiny se automaticky umístí řetězec "(R) ", a následuje název uživatelské skupiny
    • Uživatelská role v externí aplikaci určuje rozsah povolených činností uživatele
    • Uživatelská role v externí aplikaci nemůže být propojena 1:1 s naší uživatelskou skupinou, protože
      • systém uživatelských rolí v externí aplikaci nepoužívá systém práv u ovládacích prvků, aplikací atd. (externí aplikace pravděpodobně ani nepoužívá hierarchii jako jsou ovládací prvky, formuláře, aplikace apod.),
      • seznam uživatelských rolí v externí aplikaci není dostatečný pro to, abychom mohli správně určit seznam všech dalších uživatelských skupin, které musí být uživateli nastaveny spolu s uživatelskými skupinami typu "Role",
      • používáme typizované aplikace typu ERP apod., nebo tvoříme aplikace pro zákazníka na míru ve fázi, kdy od něj nemáme k dispozici konečný seznam uživatelských rolí.
  • Pro správné nastavení uživatelských skupin v NET Geniu na základě uživatelských rolí v externí aplikaci používáme skupiny oprávnění
    • Skupina oprávnění není ekvivalentem uživatelské role v externí aplikaci
    • Skupina oprávnění definuje množinu uživatelských skupin, ve kterých je uživatel členem
    • Skupina oprávnění je atributem uživatele, uživatel může být označen pouze jednou skupinou oprávnění (tento atribut je cizí klíč, a je možné podle něj filtrovat)
    • Skupina oprávnění je vyhodnocena automaticky při uložení uživatele tak, že se porovná seznam uživatelských skupin daného uživatele se seznamem skupin oprávnění
    • Skupina oprávnění obsahuje pole "Member of" - toto pole je ekvivalentem uživatelé role v externí aplikaci
    • Vyplněním "Member of" u alespoň jedné skupiny oprávnění říkáme, že má být při každém přihlášení uživatele nahrazen seznam jeho uživatelských skupin podle uživatelských rolí v externí aplikaci. Ze seznamu uživatelských rolí se zjistí, jaké skupiny oprávnění těmto rolím odpovídají, a z těchto skupin oprávnění se součtem sestaví seznam všech uživatelských skupin, které se následně nastaví danému uživateli. Pokud má výsledný seznam uživatelských skupin alespoň jeden prvek, uživatel oprávnění má, pokud je výsledný seznam prázdný, uživatel oprávnění nemá.
      • Pokud uživatel oprávnění má, bude seznam uživatelských skupin definovaných v NET Geniu nahrazen ekvivalentem uživatelských rolí
      • Pokud uživatel oprávnění nemá, bude mu seznam uživatelských skupin v NET Geniu vymazán
    • Pokud není "Member of" vyplněno ani u jedné skupiny oprávnění, autorizace v externí aplikaci slouží pouze pro zjištění, zda uživatel oprávnění pro přihlášení má nebo nemá.
      • Pokud uživatel oprávnění má, zůstane mu seznam uživatelských skupin definovaných v NET Geniu
      • Pokud uživatel oprávnění nemá, bude mu seznam uživatelských skupin v NET Geniu vymazán
    • Uživatelská role významově neodpovídá ani uživatelské skupině (v ERP používáme checkbox "Role", kterým rozlišujeme typ uživatelské skupiny), ani skupině oprávnění, která definuje seznam uživatelských skupin, a figuruje ve formuláři uživatele jako cizí klíč. Z našeho pohledu jde o uživatelskou roli v externí aplikaci, jejíž výčet je pro nás omezený, a nedostačující pro to, abychom mohli podle ní správně naprávovat naše aplikace. Uživatelská role je významově samostatná entita, pro kterou by mohla existovat nová tabulka, nicméně v tuto chvíli je zbytečná – momentálně nás zajímá pouze stringové ID uživatelské role, které vyplňujeme ve formuláři skupiny oprávnění, a to se vzhledem k vazbě 1:1 a unikátnosti ID uživatelské role nevyplňuje nikde jinde než na jedné skupině oprávnění.

5.25. NETGenium.OpenForm

  • Spustí se při každém požadavku na editační formulář po načtení záznamu, a to ještě před vyhodnocením oprávnění k ovládacím prvkům formuláře; při otevření smazaného nebo neexistujícího záznamu se nespustí
  • args = new string[] { ds.Form.ID.ToString() }
  • Funkce je spolu s funkcí NETGenium.OpenViewPage jediným místem, kde je možné nastavit hodnotu conn.Page.UserGroupIds - seznam ID uživatelských skupin, které má uživatel dočasně přidělené pro práci v editačním formuláři

5.26. NETGenium.OpenPortlets

  • Spustí se na hlavní stránce první aplikační skupiny po ověření přihlášení a po přesměrování na první aplikační skupinu, ještě před načtením portletů – i tehdy, když uživatel nemá žádný portlet, a také v administrátorském režimu, s výjimkou zobrazení vybrané aplikace v administrátorském režimu
  • args = new string[] { appgroup.ToString() } – ID první aplikační skupiny, ke které má uživatel oprávnění
  • Spouští se při každém požadavku na hlavní stránku první aplikační skupiny, tedy i při aktualizaci jednotlivého portletu; na ostatních aplikačních skupinách se nespouští
  • Návratová hodnota funkce se nepoužívá

5.27. NETGenium.OpenViewPage

  • Spustí se na nahlížecí stránce ihned po otevření připojení do databáze
  • args = new string[] { viewpage.ID.ToString() } – u neexistující nahlížecí stránky „0“
  • Spouští se při každém požadavku na nahlížecí stránku, tedy i při aktualizaci jednotlivého ovládacího prvku, a to ještě před přesměrováním podle typu stránky a před kontrolou oprávnění
  • Funkce může nastavit hodnotu conn.Page.UserGroupIds - seznam ID uživatelských skupin, které má uživatel dočasně přidělené pro práci na nahlížecí stránce; skupiny platí jen pro danou nahlížecí stránku
  • Návratová hodnota funkce se nepoužívá; výjimka ukončí načítání celé stránky

5.28. NETGenium.PageProcessingTime

  • Spustí se v editačním formuláři a na nahlížecí stránce těsně před odesláním HTML uživateli, jen při zapnutém logování dotazů a ne pro tichého uživatele
  • args = new string[] { (int)MathExt.Round(time.TotalMilliseconds).ToString() }
  • Výjimka se ignoruje

5.29. NETGenium.Payment

  • Spustí se při zobrazení stránky Payment.aspx s parametry v URL; v cloudové variantě NET Genium Online se nespouští
  • args = new string[] { }
  • Funkce může vracet html, řetězec musí začínat OK\r\n

5.30. NETGenium.PaymentNotification

  • Spustí se při zobrazení stránky PaymentNotification.aspx s parametry v URL; v cloudové variantě NET Genium Online se nespouští
  • args = new string[] { }
  • Funkce může vracet odpověď stránky, řetězec musí začínat OK\r\n

5.31. NETGenium.PlannerCellColor

  • Spustí se při zobrazení buňky v planneru
  • args = new string[] { viewfield.ToString(), "0", date1.ToString(), date2.ToString(), resource, StartDate.ToString(), EndDate.ToString() };
  • args = new string[] { viewfield.ToString(), "1", date1.ToString(), date2.ToString(), resource, date1.Date.ToString(), date1.Date.ToString() };
  • Funkce musí vracet barvu buňky ve formátu R,G,B, řetězec musí začínat OK\r\n

5.32. NETGenium.PlannerCellColorWeekend

  • Spustí se při zobrazení buňky v planneru
  • args = new string[] { }
  • Funkce musí vracet barvu buňky víkendového dne a státního svátku v zobrazení „Dny“ ve formátu R,G,B, řetězec musí začínat OK\r\n

5.33. NETGenium.PlannerCellHtml

  • Spustí se při zobrazení buňky v planneru, jen pokud planner povoluje překrývání událostí
  • args = new string[] { viewfield.ToString(), "0", date1.ToString(), date2.ToString(), resource, StartDate.ToString(), EndDate.ToString() };
  • args = new string[] { viewfield.ToString(), "1", date1.ToString(), date2.ToString(), resource, date1.Date.ToString(), date1.Date.ToString() };
  • Funkce musí vracet html, řetězec musí začínat OK\r\n

5.34. NETGenium.RegisterExternalFunction

  • Spustí se při zobrazení stránky ngef.aspx v situaci, kdy není externí funkce autorizovaná pro aktuálně přihlášeného uživatele (volání ngef.aspx nebylo umístěno například v ovládacím prvku HTML nebo JavaScript), a také při volání externí funkce metodou „ngef“ knihovny NETGeniumConnection přes webové služby
  • Touto situací je například přímé vyvolání stránky ngef.aspx například ve webovém prohlížeči
  • args = new string[] { id, arg0, arg1, ... } – na rozdíl od ostatních funkcí obsahuje args[0] identifikátor volané externí funkce a za ním následují její parametry tak, jak je poslal klient
  • Spouští se i pro nepřihlášeného uživatele; funkce proto musí parametry sama ověřit
  • Funkce může vracet OK\r\n, čímž spuštění dané externí funkce povolí
  • Volání této funkce je alternativou k seznamu veřejných externích funkcí, který se definuje v nastavení NET Genia

5.35. NETGenium.SendMessage

  • Spustí se po odeslání e-mailové zprávy z formuláře "Nová e-mailová zpráva"
  • Do args se přenesou cesty k souborovým přílohám na disku serveru, takže je možné tyto soubory např. zabalit do ZIPu a přiložit jako přílohu do NG apod.
  • Objekt conn.Container2 obsahuje odeslanou zprávu pod klíčem „message“ (MailMessage), příznak uložení do odeslaných pod klíčem „save“ a stav pod klíčem „state“; hodnoty zprávy (to, subject, body...) vrací conn["..."]
  • Vrátí-li funkce řetězec „skipsave“ (bez prefixu OK\r\n), zpráva se neuloží do odeslaných
  • Zpráva je v okamžiku volání již odeslaná. Výjimka ve funkci se zobrazí jako chybové hlášení ve formuláři nové zprávy, formulář zůstane otevřený a zpráva se neuloží do odeslaných; odeslání se tím nevrátí a opětovné stisknutí tlačítka „Odeslat“ zprávu odešle znovu

5.36. NETGenium.SortOrder

  • Spustí se po nastavení pořadí záznam buď v datagridu nebo tree
  • args = new string[] { "Q" + qb.ID, qb.Form.ID.ToString() };

5.37. NETGenium.TimeTableCellColor

  • Spustí se při zobrazení buňky v timetable v ganttově diagramu
  • args = new string[] { viewfield.ToString(), viewtype.ToString(), date1.ToString(), date2.ToString(), resource, mindate.ToString(), maxdate.ToString() };
    • date2 – konec buňky zmenšený o jeden den
    • resource – titulek zdroje
  • Funkce musí vracet barvu buňky ve formátu R,G,B, řetězec musí začínat OK\r\n

5.38. NETGenium.Translate

  • Spustí se při zobrazení stránky Translate.aspx, jen pro přihlášeného uživatele, při nastaveném klíči překladače Google a vyplněném zdrojovém jazyce
  • args = new string[] { sourcelanguage, targetlanguage, sourcevalue, format }
  • Funkce může vracet přeložený text, řetězec musí začínat OK\r\n; jinak se použije překladač Google

5.39. NETGenium.UnlockRecord

  • Spustí se, když editační formulář uvolní zámek databázového záznamu při řízeném opuštění formuláře – tlačítkem „Zpět“, přesměrováním nebo odchodem z formuláře jinou cestou portálu (menu, záhlaví, přepnutí režimu, odhlášení) – a jen u zámku, který drží session a okno prohlížeče, ze kterého se formulář opouští
  • Nespustí se pro tichého uživatele ani tehdy, zanikne-li zámek jinak – vypršením, restartem webové aplikace, odhlášením relace administrátorem nebo správcem uživatelských účtů, automatickým odhlášením podle konfiguračního souboru „SingleLogin.txt“, smazáním uživatele v NET Geniu nebo přes webové služby knihovny „NETGeniumConnection“, odhlášením relace ticketem přes tytéž webové služby, ukončením nečinné relace přihlášené tokenem, přes webové služby nebo přes Windows z adresy s parametrem „autologin“ dalším takovým přihlášením téhož uživatele nebo převzetím zámku jiným oknem či uživatelem
  • args = new string[] { form.ToString(), id.ToString() }

5.40. NETGenium.Url

  • Spustí se před odesláním e-mailové zprávy krokem skriptu „Odeslat e-mail“ se zapnutým odkazem na záznam
  • args = new string[] { user.DatabaseSettings.UrlEmails.Length != 0 ? user.DatabaseSettings.UrlEmails : user.DatabaseSettings.Url }
  • Funkce může vracet změněnou adresu, např. OK\r\nhttp://localhost/netgenium; více adres se odděluje středníkem

5.41. NETGenium.LoginHtml

  • Spustí se při vykreslení přihlašovacího okna
  • args = new string[] { }
  • Funkce může vracet html, které se vloží pod přihlašovací okno, řetězec musí začínat OK\r\n

5.42. NETGenium.OnAfterOpen

  • Spustí se při načtení editačního formuláře (i po přesměrování zpět na formulář, například po uložení tlačítkem „Uložit a pokračovat v editaci“), před spuštěním skriptu „OnAfterOpen“; nespustí se, je-li spouštění skriptu „OnAfterOpen“ na formuláři zakázané, nebo nezobrazí-li se uživateli v uživatelském režimu žádný ovládací prvek formuláře
  • Výjimka ve funkci ukončí načítání celého editačního formuláře
  • args = new string[] { form.ToString() }
  • Objekt „conn“ nemá zaregistrovaný záznam formuláře, conn["..."] proto vrací null
  • Návratová hodnota funkce se nepoužívá

5.43. NETGenium.OnAfterSave

  • Spustí se po uložení záznamu v editačním formuláři, před spuštěním skriptu „OnAfterSave“, a to i tehdy, když uložení přeskočila serverová funkce SKIPSAVE(); nespustí se, je-li spouštění skriptu „OnAfterSave“ na formuláři zakázané
  • Nespustí se při uložení záznamu mimo editační formulář – při hromadné změně nebo změně hodnoty v nahlížecí tabulce, při importu z Excelu ani ze serverové funkce „OBSOAS“
  • args = new string[] { form.ToString() }
  • Hodnoty uloženého záznamu vrací conn["..."], jen pokud předtím proběhl skript „OnBeforeSave“; jinak conn["..."] vrací null
  • Záznam je v okamžiku volání již uložený – výjimka uložení nevrátí: zobrazí se uživateli jako chyba skriptu „OnAfterSave“, skript „OnAfterSave“ se už nespustí a e-maily i synchronizace proběhnou jako po úspěšném uložení
  • Návratová hodnota funkce se nepoužívá

5.44. NETGenium.OnAfterDelete

  • Spustí se po smazání záznamu v editačním formuláři, před spuštěním skriptu „OnAfterDelete“, a to i tehdy, když smazání přeskočila serverová funkce SKIPDELETE(); nespustí se, je-li spouštění skriptu „OnAfterDelete“ na formuláři zakázané
  • Nespustí se při hromadném mazání záznamů v nahlížecí tabulce
  • args = new string[] { form.ToString() }
  • Hodnoty smazaného záznamu vrací conn["..."], jen pokud předtím proběhl skript „OnBeforeDelete“; jinak conn["..."] vrací null
  • Záznam je v okamžiku volání již smazaný – výjimka smazání nevrátí: zobrazí se uživateli jako chyba skriptu „OnAfterDelete“, skript „OnAfterDelete“ se už nespustí a synchronizace proběhne jako po úspěšném smazání
  • Návratová hodnota funkce se nepoužívá

6. Čtení dat z databáze

6.1. Načtení záznamů z SQL dotazu do objektu DataTable

using NETGenium;
using System;
using System.Data;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
DataTable data = Data.Get("SELECT * FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
Console.WriteLine(conn.User.FormatDataTableText(data));

foreach (DataRow row in data.Rows)
{
// Console.WriteLine(row["id"]);
}

return "";
}

6.2. Načtení záznamů z SQL dotazu do objektu DbRow

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
DbRow row = new DbRow("SELECT * FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (row.Read())
{
// Console.WriteLine(row["id"]);
Console.WriteLine(row.Report());
}

return "";
}

6.3. Parsování hodnot

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
DbRow row = new DbRow("SELECT * FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (row.Read())
{
int id = (int)row["id"];
Console.WriteLine("id: " + id);

int pid = Parser.ToInt32(row["pid"]);
Console.WriteLine("pid: " + pid);

double _pid = Parser.ToDouble(row["pid"]);
Console.WriteLine("pid: " + _pid);

string name = row["name"].ToString();
Console.WriteLine("name: " + name);

DateTime date = Parser.ToDateTime(row["date_"]);
Console.WriteLine("date: " + conn.User.FormatDateTime(date));
}

return "";
}

6.4. Indexace načtených záznamů podle primárního klíče

using NETGenium;
using System;
using System.Collections.Generic;
using System.Data;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
DataTable data = Data.Get("SELECT * FROM sholiday", conn);
Dictionary<int, DataRow> dictionary = Data.DictionaryInt32(data);

int id = 1;
if (dictionary.ContainsKey(id))
{
DataRow row = dictionary[id];
Console.WriteLine(row["id"]);
}

return "";
}

6.5. Indexace načtených vnořených záznamů podle cizího klíče „pid“

using NETGenium;
using System;
using System.Collections.Generic;
using System.Data;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
DataTable data = Data.Get("SELECT * FROM sholiday", conn);
Dictionary<int, List<DataRow>> dictionary = Data.DictionaryInt32(data, "pid", true);

int pid = 0;
if (dictionary.ContainsKey(pid))
{
List<DataRow> rows = dictionary[pid];
Console.WriteLine(rows.Count + " rows");
}

return "";
}

7. Zápis dat do databáze

7.1. INSERT INTO – vytvoření nového záznamu v databázi

7.1.1. DataSaver – vytvoření jednoho záznamu

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
DataSaver ds = new DataSaver("sholiday", 0, cmd);
ds.Add("name", "Nový rok");
ds.Add("date_", new DateTime(DateTime.Today.Year, 1, 1));
ds.Execute();

Console.WriteLine(ds.Report());

return "";
}
 

7.1.2. DataSaver – vytvoření jednoho záznamu zkopírováním jiného záznamu

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
int id = 1;

DbRow row = new DbRow("SELECT * FROM sholiday WHERE id = " + id, conn);
if (row.Read())
{
// row["ng_zadanokym"] = conn.User.LoginName;
// row["ng_zadanokdy"] = DateTime.Now;
// row["ng_zmenenokym"] = DBNull.Value;
// row["ng_zmenenokdy"] = DBNull.Value;

DataSaver ds = new DataSaver("sholiday", 0, cmd);
ds.Add(row);
ds.Execute();

Console.WriteLine(ds.Report());
}

return "";
}
 

7.1.3. DataSaverSynchro – vytvoření jednoho záznamu včetně vytvoření záznamu historie a zajištění synchronizace záznamu

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
DataSaverSynchro ds = new DataSaverSynchro("sholiday", 0, conn);
ds.Add("name", "Nový rok");
ds.Add("date_", new DateTime(DateTime.Today.Year, 1, 1));
ds.Save(cmd);

Console.WriteLine(ds.Report());

return "";
}

7.2. UPDATE – editace existujícího záznamu v databázi

7.2.1. DataSaver – editace záznamu, jehož ID je načteno z databáze

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
int id = Data.ExecuteScalarInt32("SELECT id FROM sholiday WHERE name = " + conn.Format("Nový rok") + " AND date_ = " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (id != 0)
{
DataSaver ds = new DataSaver("sholiday", id, cmd);
ds.Add("name", "Nový rok – TEST");
ds.Execute();

Console.WriteLine(ds.Report());
}

return "";
}
 

7.2.2. DataSaver – editace záznamu, jehož ID je uloženo v proměnné; pokud záznam neexistuje, bude vytvořen

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
int id = 1;

DataSaver ds = new DataSaver("sholiday", id, true, cmd);
ds.Add("name", "Nový rok – TEST");
ds.Execute();

Console.WriteLine(ds.Report());

return "";
}
 

7.2.3. DataSaverSynchro – editace záznamu, jehož ID je načteno z databáze, včetně vytvoření záznamu historie a zajištění synchronizace záznamu

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
int id = Data.ExecuteScalarInt32("SELECT id FROM sholiday WHERE name = " + conn.Format("Nový rok") + " AND date_ = " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (id != 0)
{
DataSaverSynchro ds = new DataSaverSynchro("sholiday", id, conn);
ds.Add("name", "Nový rok – TEST");
ds.Save(cmd);

Console.WriteLine(ds.Report());
}

return "";
}
 

7.2.4. DataSaverSynchro – editace záznamu, jehož ID je uloženo v proměnné, včetně vytvoření záznamu historie a zajištění synchronizace záznamu; pokud záznam neexistuje, bude vytvořen

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
int id = 1;

DataSaverSynchro ds = new DataSaverSynchro("sholiday", id, true, conn);
ds.Add("name", "Nový rok – TEST");
ds.Save(cmd);

Console.WriteLine(ds.Report());

return "";
}

7.3. Synchronizace dat dvou databázových tabulek podle jednotného klíče

using NETGenium;
using System;
using System.Collections.Generic;
using System.Data;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
string key = "ng_osobnicislo";

DataTable data1 = Data.Get("SELECT * FROM ng_data1", conn), data2 = Data.Get("SELECT * FROM ng_data2", conn);
Dictionary<int, DataRow> dictionary = Data.DictionaryInt32(data1, key);

foreach (DataRow row2 in data2.Rows)
{
DataRow row1 = Data.DataRow(dictionary, Parser.ToInt32(row2[key]));
if (row1 == null)
{
DataSaver ds = new DataSaver("ng_data1", 0, cmd);

for (int i = 1; i < data2.Columns.Count; i++)
{
ds.Add(data2.Columns[i].ColumnName, row2[data2.Columns[i].ColumnName]);
}

ds.Execute();
}
else
{
DataSaver ds = new DataSaver("ng_data1", (int)row1["id"], cmd);
for (int i = 1; i < data2.Columns.Count; i++)
if (row1[data2.Columns[i].ColumnName].ToString() != row2[data2.Columns[i].ColumnName].ToString())
{
ds.Add(data2.Columns[i].ColumnName, row2[data2.Columns[i].ColumnName]);
}

if (!ds.Empty)
{
ds.Execute();
}
}
}

return "";
}

8. Mazání dat z databáze

8.1. DELETE FROM – smazání záznamu z databáze

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
int id = Data.ExecuteScalarInt32("SELECT id FROM sholiday WHERE name = " + conn.Format("Nový rok – TEST") + " AND date_ = " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (id != 0)
{
cmd.CommandText = "DELETE FROM sholiday WHERE id = " + id;
cmd.ExecuteNonQuery();
}

return "";
}

8.2. DataSaverSynchro – smazání záznamu z databáze včetně vytvoření záznamu historie a zajištění synchronizace záznamu

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
int id = Data.ExecuteScalarInt32("SELECT id FROM sholiday WHERE name = " + conn.Format("Nový rok – TEST") + " AND date_ = " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (id != 0)
{
DataSaverSynchro ds = new DataSaverSynchro("sholiday", id, conn);
ds.Delete(cmd);
}

return "";
}

9. Editační formuláře

9.1. Zjištění ID aktuálně otevřeného editačního formuláře

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
string dbname = conn.FormData.Table.TableName;
int form = conn.Page.QS_ToInt32("form");

return "";
}

9.2. Načtení hodnoty ovládacího prvku v editačním formuláři

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
string name = conn["name"].ToString();

return "";
}

9.3. Uložení hodnoty do ovládacího prvku v editačním formuláři

using NETGenium;
using System;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
conn["name"] = "Nový rok – TEST";

return "";
}

9.4. Ajaxové volání z javascriptu

9.4.1. JavaScript

var p0 = 'ěščřžýáíé', p1 = 'ĚŠČŘŽÝÁÍÉ';
loadUrl('ngef.aspx?MyFirstFunction,' + urlEncode(p0) + ',' + urlEncode(p1), 'ajaxResponse', 'test', 'p0=' + urlEncode(p0) + '&p1=' + urlEncode(p1));

function ajaxResponse(html)
{
alert(html);
}
 

9.4.2. Externí funkce

case "MyFirstFunction": MyFirstFunction(args, conn); return "";

using NETGenium;
using System;
using System.Text;

private static void MyFirstFunction(string[] args, DbConnection conn)
{
StringBuilder sb = new StringBuilder();
sb.Append("MyFirstFunction REPORT");
sb.Append(" | GET args: ");
sb.Append(string.Join(", ", args));
sb.Append(" | POST args: ");
sb.Append(conn.Page.Form("p0"));
sb.Append(", ");
sb.Append(conn.Page.Form("p1"));
Html.FlushAjaxContent(sb.ToString(), conn);
}
  • Stránka ngef.aspx zavolá externí funkci jen tehdy, je-li pro aktuální session autorizovaná. Autorizaci zajistí:
    • vykreslení textu „ngef.aspx?Identifikátor“ uzavřeného do uvozovek v ovládacím prvku JavaScript, v kódu tlačítka (i tlačítka vloženého do databázového ovládacího prvku), v ovládacím prvku AutoSum nebo v copyrightu navigátoru – u copyrightu jen tehdy, nenahradí-li ho externí funkce NETGenium.Copyright; v ovládacím prvku HTML se rozpoznává jen zápis v dvojitých uvozovkách,
    • otevření nahlížecí stránky typu „Zobrazit webovou stránku“, jejíž adresa začíná textem „ngef.aspx?“, v uživatelském režimu,
    • návratová hodnota s prefixem OK\r\n z externí funkce NETGenium.RegisterExternalFunction,
    • zařazení funkce do seznamu veřejných externích funkcí v Nastavení NET Genia.
  • Autorizace platí po celou dobu session a pro libovolné parametry – volanou funkci lze tedy spustit s jakýmikoli hodnotami parametrů a funkce je musí sama ověřit. Neautorizované volání vrátí text „UNAUTHORIZED“.
  • Řetězec za otazníkem se nejdříve celý dekóduje a teprve potom rozdělí podle čárek, takže čárku nelze předat v parametru ani zakódovanou funkcí urlEncode – hodnotu obsahující čárku je nutné poslat v těle požadavku (parametr „params“ funkce loadUrl). Parametry se ořezávají o mezery a nezakódovaný znak „+“ se při dekódování změní na mezeru.
  • Externí funkce se volá s parametrem „test“ s hodnotou „false“ a objektem „cmd“ s hodnotou „null“. Návratová hodnota se vypíše do HTML stránky; čistou textovou odpověď pro JavaScript zajistí metoda „Html.FlushAjaxContent“.
  • Funkce loadUrl zpracovává vždy jen jeden požadavek – volání během rozpracovaného požadavku se zahodí.

9.5. Simulace otevření konkrétního záznamu v editačním formuláři z konzolové aplikace a přečtení hodnoty ovládacího prvku

using NETGenium;
using System;
using System.Data;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
int id = 1;

DataTable data = Data.Get("SELECT * FROM sholiday WHERE id = " + id, conn);
if (data.Rows.Count != 0)
{
conn.Register(data.Rows[0]);
}

string name = Parser.ToString(conn["name"]);
Console.WriteLine(name);

return "";
}

9.6. Zachycení událostí v editačním formuláři

9.6.1. Otevření editačního formuláře

// case "NETGenium.OnAfterOpen": OnAfterOpen(args, conn); return "";

using NETGenium;
using System;

private static void OnAfterOpen(string[] args, DbConnection conn)
{
int form = Parser.ToInt32(args[0]);
}
  • Hodnoty záznamu jsou v objektu „conn“ dostupné jen v callbacku po uložení a po smazání, a to jen pokud předtím proběhl skript „OnBeforeSave“, resp. „OnBeforeDelete“; jinak conn["id"] vrací null a Parser.ToInt64 vrátí 0. Podrobnosti jsou uvedeny v kapitolách 5.42 až 5.44.

9.6.2. Uložení záznamu

// case "NETGenium.OnAfterSave": OnAfterSave(args, conn); return "";

using NETGenium;
using System;

private static void OnAfterSave(string[] args, DbConnection conn)
{
int form = Parser.ToInt32(args[0]);
long id = Parser.ToInt64(conn["id"]);
}
 

9.6.3. Smazání záznamu

// case "NETGenium.OnAfterDelete": OnAfterDelete(args, conn); return "";

using NETGenium;
using System;

private static void OnAfterDelete(string[] args, DbConnection conn)
{
int form = Parser.ToInt32(args[0]);
long id = Parser.ToInt64(conn["id"]);
}

10. Nahlížecí tabulky

10.1. Spuštění externí funkce pomocí „ngef2“ z nahlížecí tabulky

10.1.1. Úpravy v NET Geniu

  • Ve formuláři „Uživatel“ vytvořit nový textbox
    • Název: „Test“
    • Zaškrtnout „Jen ke čtení“
    • Zaškrtnout „Skryté pole“
    • Výchozí hodnota: „ngef2(ngef2test)“
    • Zaškrtnout „Vyplnit výchozí hodnotu při každém otevření editačního formuláře“
  • Vytvořit novou nahlížecí stránku s datagridem, který bude zobrazovat pouze sloupec „Test“

10.1.2. Úpravy v externí funkci

// case "ngef2test": return ngef2test(args, conn);

using NETGenium;
using System;
using System.Collections.Generic;
using System.Data;

private static string ngef2test(string[] args, DbConnection conn)
{
int id = Parser.ToInt32(args[args.Length - 1]);

string key = "ngef2test";
Dictionary<int, DataRow> dictionary;

if (!conn.Container2.ContainsKey(key))
{
DataTable data = Data.Get("SELECT id, loginname FROM susers", conn);
dictionary = Data.DictionaryInt32(data);
conn.Container2.Add(key, dictionary);
}
else
{
dictionary = (Dictionary<int, DataRow>)conn.Container2[key];
}

if (dictionary.ContainsKey(id))
{
return dictionary[id]["id"] + ": " + dictionary[id]["loginname"].ToString();
}

return id.ToString();
}

10.2. Vyplnění hodnot v nahlížecí tabulce

10.2.1. Úpravy v NET Geniu

  • Ve formuláři „Uživatel“ vytvořit nový textbox
    • Název: „Test“
  • Zjistit ID textboxu: například „7125“
  • Vytvořit novou nahlížecí stránku s datagridem, který bude zobrazovat pouze sloupec „Test“
    • Ve zdroji dat na záložce „Ostatní“ zaškrtnout „ngef(NETGenium.DataTable)“
    • Zkopírovat do schránky ukázku zdrojového kódu pod zaškrtávacím tlačítkem:
      • if (args[0] == "Q987" && args[1] == "1")
      • {
      • DataTable data = (DataTable)conn.Container2[args[0]];
      • int form = Parser.ToInt32(args[1]);
      • }

10.2.2. Úpravy v externí funkci – verze 1 pro malé množství záznamů

// case "NETGenium.DataTable": QueryBuilder(args, conn); return "";

using NETGenium;
using System;
using System.Collections.Generic;
using System.Data;

private static void QueryBuilder(string[] args, DbConnection conn)
{
if (args[0] == "Q987" && args[1] == "1")
{
DataTable data = (DataTable)conn.Container2[args[0]];
int form = Parser.ToInt32(args[1]);

string key = "c7125";
if (data.Columns.Contains(key) && data.Rows.Count != 0)
{
List<int> ids = new List<int>();

foreach (DataRow row in data.Rows)
{
int id = (int)row["id"];
if (id != 0)
{
ids.Add(id);
}
}

if (ids.Count == 0)
{
return;
}

DataTable data2 = Data.Get("SELECT id, loginname FROM susers WHERE id IN (" + Sql.Ids(ids.ToArray()) + ")", conn);
Dictionary<int, DataRow> dictionary = Data.DictionaryInt32(data2);

foreach (DataRow row in data.Rows)
{
int id = (int)row["id"];
if (dictionary.ContainsKey(id))
{
row[key] = dictionary[id]["id"] + ": " +
dictionary[id]["loginname"].ToString();
}
else
{
row[key] = id.ToString();
}
}
}
}
}
 

10.2.3. Úpravy v externí funkci – verze 2 pro velké množství záznamů

// case "NETGenium.DataTable": QueryBuilder(args, conn); return "";

using NETGenium;
using System;
using System.Collections.Generic;
using System.Data;

private static void QueryBuilder(string[] args, DbConnection conn)
{
if (args[0] == "Q987" && args[1] == "1")
{
DataTable data = (DataTable)conn.Container2[args[0]];
int form = Parser.ToInt32(args[1]);

string key = "c7125";
if (data.Columns.Contains(key) && data.Rows.Count != 0)
{
Dictionary<int, DataRow> dictionary = new Dictionary<int, DataRow>();
List<int> ids = new List<int>();

foreach (DataRow row in data.Rows)
{
int id = (int)row["id"];
if (id != 0 && !dictionary.ContainsKey(id))
{
dictionary.Add(id, row);
ids.Add(id);
}
}

if (ids.Count != 0)
foreach (string group in Sql.IdsInGroupsOf100(ids.ToArray()))
using (DbCommand cmd = new DbCommand("SELECT id, loginname FROM susers WHERE id IN (" + group + ")", conn))
using (DbDataReader dr = cmd.ExecuteReader())
while (dr.Read())
{
int id = (int)dr["id"];
if (dictionary.ContainsKey(id))
{
dictionary[id][key] = id + ": " + dr["loginname"].ToString();
}
}
}
}
}

10.3. Export dat ze statistické nahlížecí tabulky

// case "NETGenium.DataGrid2Excel": DataGrid2Excel(args, conn); return "";

using NETGenium;
using System;

private static void DataGrid2Excel(string[] args, DbConnection conn)
{
string path = args[0], query = args[1];
int form = Parser.ToInt32(args[2]);
DateTime date1 = Parser.ToDateTime(args[3]);
DateTime date2 = Parser.ToDateTime(args[4]);
}

11. Souborové přílohy

11.1. Vytvoření souborové přílohy

using NETGenium;
using System;
using System.Text;

private static string MyFirstFunction(string[] args, DbConnection conn)
{
int file = Attachment.Add("test.txt", Encoding.UTF8.GetBytes("abc"), conn);
Console.WriteLine(file);

return "";
}

11.2. Načtení obsahu souborové přílohy

using NETGenium;
using System;
using System.Text;

private static string MyFirstFunction(string[] args, DbConnection conn)
{
int file = Attachment.Add("test.txt", Encoding.UTF8.GetBytes("abc"), conn);
Console.WriteLine(file);

string s = conn.GetAttachmentAsString(file, Encoding.UTF8);
if (s != null)
{
Console.WriteLine(s);
}

return "";
}

11.3. Zamezení stažení souborové přílohy – záměna obsahu za prázdný soubor

// case "NETGenium.Download": return Download(args, conn);

using NETGenium;
using System;

private static string Download(string[] args, DbConnection conn)
{
int id = Parser.ToInt32(args[0]);
string filename = args[1], path = args[2];

L.N("Download: " + conn.User.LoginName + "; " + id + "; " + filename + "; " + path);

path = conn.RootPath + "Images\\1x1.gif";
return "OK\r\n" + path;
}
  • Soubor se nabídne pod původním názvem a příponou, takže podstrčený obrázek se u jiných formátů neotevře. V cloudové variantě NET Genium Online adresář „Images“ v kořeni instance není.

12. E-maily

12.1. Odeslání e-mailové zprávy

using NETGenium;
using System;
using System.Net.Mail;

private static string SendMessage(string[] args, DbConnection conn)
{
string html = NETGenium.Email.Message.Container("<b>Hello</b>");

using (MailMessage message = new MailMessage())
{
message.From = new MailAddress("info@mojefirma.cz");
message.To.Add(new MailAddress("info@netgenium.com"));
message.Subject = "Test";
message.AlternateViews.Add(Config.CreateTextAlternateView(Html.ToText(html)));
message.AlternateViews.Add(Config.CreateHtmlAlternateView(html, conn));

string error = Config.SendMessage(message, conn);
return error != null ? error : "";
}
}
  • Metoda Config.SendMessage výjimku nevyvolá – při neúspěchu vrátí text chyby a zprávu uloží do adresáře „SMTP“, jinak vrátí null. Varianta Config.SendMessage(message, false, conn) odešle zprávu přes SMTP server 2.

12.2. Zachycení události odeslání e-mailové zprávy prostřednictvím formuláře „Nový email“, a přeskočení uložení zprávy do odeslaných

// case "NETGenium.SendMessage": return SendMessage(args, conn);

using NETGenium;
using System;
using System.Net.Mail;

private static string SendMessage(string[] args, DbConnection conn)
{
MailMessage message = (MailMessage)conn.Container2["message"];
bool save = (bool)conn.Container2["save"];

return "skipsave";
}
  • Vrácený řetězec „skipsave“ se porovnává bez prefixu OK\r\n a s rozlišením velikosti písmen; uplatní se jen tehdy, je-li zaškrtnuté uložení zprávy. Objekt „message“ se po návratu z funkce uvolní, nelze si ho tedy ponechat.

13. Tisk do tiskových šablon

13.1. Zachycení události tisku do tiskové šablony, a změna obsahu nebo názvu tištěného souboru

// case "NETGenium.OnAfterPrint": OnAfterPrint(args, conn); return "";

using NETGenium;
using System;

private static void OnAfterPrint(string[] args, DbConnection conn)
{
if (conn.PrintingProcess.Template == "Test.pdf")
{
string path = conn.PrintingProcess.FilePath;
Files.Write(path, "abc");
conn.PrintingProcess.FileName = "abc.txt";
}
}

13.2. Změna hesla pro uzamykání excelových tiskových šablon

// case "NETGenium.ExcelPassword": return ExcelPassword();

using NETGenium;
using System;

private static string ExcelPassword()
{
return "OK\r\n" + Guid.NewGuid().ToString();
}
  • Heslo uzamyká listy proti úpravám; soubor samotný se nešifruje a lze ho otevřít bez hesla.

14. Přihlašování uživatelů

14.1. Zachycení události „OnBeforeLogin“ bezprostředně před automatickým přihlášením uživatele přes Active Directory

// case "NETGenium.OnBeforeLogin": return OnBeforeLogin(args, conn);

using NETGenium;
using System;

private static string OnBeforeLogin(string[] args, DbConnection conn)
{
string loginby = args[0];
DbRow row;

if (loginby.Length != 0)
{
row = new DbRow("SELECT id, loginname FROM susers WHERE account = " + conn.Format(loginby) + " OR email = " + conn.Format(loginby), conn);
}
else
{
string loginname = args[1];
row = new DbRow("SELECT id, loginname FROM susers WHERE loginname = " + conn.Format(loginname), conn);
}

if (row.Read())
{
// externí autorizace uživatele, např. úprava jeho uživatelských skupin
}

return "";
}
  • Při přihlášení přes Active Directory obsahuje args[0] účet uživatele, při přihlášení přes poskytovatele identity jeho e-mailovou adresu (u Apereo bez e-mailové adresy identifikátor uživatele „sub“, který se v poli „Účet systému Windows“ hledá s předponou „AD\“, viz kapitola 5.24); u přihlášení jménem a heslem je args[0] prázdný a args[1] obsahuje přihlašovací jméno.
  • Návratovou hodnotou OK\r\n lze zamezit přihlášení jen u přihlášení jménem a heslem; u automatického přihlášení se návratová hodnota nepoužívá.

14.2. Zamezení přihlášení uživatelů

// case "NETGenium.OnAfterLogin": return OnAfterLogin(args, conn);

using NETGenium;
using System;

public static string OnAfterLogin(string[] args, DbConnection conn)
{
string error = Error(conn);
if (error != null)
{
conn.HttpContext.Session.Abandon();
return "OK\r\nalert(" + JS.ToString(error) + "); if (opener != null) window.close(); else top.location = 'Logout.aspx';";
}

return "";
}

private static string Error(DbConnection conn)
{
if (conn.User.ID != 1 && conn.User.Attributes.Contains("ng_aktivni") && conn.User["ng_aktivni"].ToString().Length == 0)
{
return "Neplatné přihlášení.";
}

return null;
}
  • JavaScript vrácený s prefixem OK\r\n se spustí v přihlašovacím okně portálu, v dialogu „Změna hesla“ a při přihlášení přes Active Directory; při přihlášení přes Microsoft, Google, Facebook nebo Apereo se spustí na jinak prázdné stránce místo přesměrování do portálu (kapitola 5.22). Při přihlášení přihlašovacím ticketem a při automatickém přihlášení přes Active Directory při otevření nahlížecí stránky nebo stránky Portlets.aspx adresou s parametrem „autologin“ se neprovede.
  • Funkce se nespustí při přihlášení MCP tokenem, přes webové služby knihovny NETGeniumConnection ani přes vlastní API, takže omezení touto funkcí se na tyto přístupy nevztahuje; přístup účtu se tam omezuje jeho uživatelskými skupinami, u webových služeb také blokováním přihlašování po opakovaných neplatných pokusech a u MCP tokenu a vlastního API smazáním nebo vypršením tokenu.

15. Ostatní

15.1. Logování na disk do adresáře „Logs“

using NETGenium;
using System;
using System.IO;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
try
{
throw new NullReferenceException("args");
}
catch (Exception ex)
{
L.E("MyFirstFunction", ex);
// L.LogError("MyFirstFunction", ex);

L.W("MyFirstFunction", ex);
// L.LogWarning("MyFirstFunction", ex);

L.N("MyFirstFunction", ex);
// L.LogNotice("MyFirstFunction", ex);
}

return "";
}
  • Volání s jediným textovým parametrem (zpráva, případně výjimka) zapíše záznam do denního logového souboru „Logs\yyyy-MM-dd.log“ – v ukázce výše je tedy „MyFirstFunction“ text zprávy, nikoli název souboru.
  • Do samostatného logového souboru se záznam zapíše voláním, jehož prvním parametrem je prefix názvu souboru, například „L.E("MyFirstFunction", "Zpráva", ex)“. Název souboru se z prefixu sestaví takto:
    • prefix neobsahuje „yyyy“ – soubor je měsíční, například „Logs\MyFirstFunction-2026-09.log“,
    • prefix obsahuje „yyyy“ – text před „yyyy“ zůstane beze změny a zbytek prefixu od „yyyy“ se použije jako formát data .NET, takže prefix „PDDP-yyyy-MM-dd“ vytvoří denní soubor „Logs\PDDP-2026-09-29.log“ a prefix „PDDP-yyyy“ roční soubor „Logs\PDDP-2026.log“,
    • prefixy „Errors“, „System“, „Version“ a „Warnings“ – soubor bez data, například „Logs\Errors.log“.
  • Veškerý text za „yyyy“ se interpretuje jako formát data, takže písmena jako „d“, „M“, „H“, „m“, „s“ nebo „t“ se nahradí hodnotami data. Text, který má za datem zůstat beze změny, se uzavírá do apostrofů, například „PDDP-yyyy-MM-dd'-import'“.

15.2. Zachycení události zamčení databázového záznamu

// case "NETGenium.LockRecord": LockRecord(args, conn); return "";
// case "NETGenium.UnlockRecord": UnlockRecord(args, conn); return "";

using NETGenium;
using System;

private static void LockRecord(string[] args, DbConnection conn)
{
int form = Parser.ToInt32(args[0]);
long id = Parser.ToInt64(args[1]);
}

private static void UnlockRecord(string[] args, DbConnection conn)
{
int form = Parser.ToInt32(args[0]);
long id = Parser.ToInt64(args[1]);
}

15.3. Změna obsahu textu „Copyright“

// case "NETGenium.Copyright": return Copyright(args, conn);

using NETGenium;
using System;

private static string Copyright(string[] args, DbConnection conn)
{
return "OK\r\n © NetGenium " + conn.Now.Year;
}

15.4. Dodatečné úpravy CSS stylů při uložení vzhledu

// case "NETGenium.CSS": return CSS(args);

using NETGenium;
using System;

private static string CSS(string[] args)
{
string value = args[0], browser = args[1];
return "OK\r\n" + value + ".teststyle { color: red; }";
}