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.

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“, která je uložena v adresáři „N:\NetGenium\Projekty\NetGenium\References”. „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 „NETGenium\bin\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);

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ů.
  • bool test
    • Logická hodnota „test“ určuje, zda je externí funkce volána z návrháře skriptů pomocí tlačítka „Spustit skript“.
    • 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.
  • 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“.
    • 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()“.
    • 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“.
    • 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.
      • U databáze Firebird vzniká „deadlock“ při pokusu o čtení z databázové tabulky, do které bylo v rámci transakce zapisováno. Firebird tedy během transakce zamyká celou databázovou tabulku, do které bylo zapisováno.
      • U databáze MSSQL vzniká „deadlock“ při pokusu o čtení z řádky databázové tabulky, do které bylo v rámci transakce zapisováno. MSSQL tedy během transakce zamyká řádky databázové tabulky, do kterých bylo zapisováno.
    • 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“.
  • 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.

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";
DateTime now = DateTime.Now;

console.WriteLine(MyFirstFunction(new string[] { "a", "b", "c" }, cmd, conn));

console.WriteLine();
console.WriteLine(conn.User.FormatTimeSpan(DateTime.Now - now));
}

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“.

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.).

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
    • html = html.Replace("[ODHLASENI]", "<a href=\"" + url + "/Unsubscribe.aspx?" + guid + "\">Odhlásit</a> se z těchto emailů...") + "<img src=\"" + url + "/Image.aspx?" + guid + "\">";
  • args = new string[] { queryString }

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
    • html = html.Replace("[ODHLASENI]", "<a href=\"" + url + "/Unsubscribe.aspx?" + guid + "\">Odhlásit</a> se z těchto emailů...") + "<img src=\"" + url + "/Image.aspx?" + guid + "\">";
  • args = new string[] { queryString }

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
    • html = html.Replace("[PROHLIZEC]", "<a href=\"" + url + "/View.aspx?" + guid + "\">Zobrazit ve webovém prohlížeči...</a>");
  • args = new string[] { queryString }

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
  • args = new string[] { value, browser.ToString() }
  • 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.FormInfo.ID.ToString(), qb.date1, qb.date2 }

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
  • Více v příručce Návrhář databázových dotazů

5.8. NETGenium.Download

  • Spustí se při zobrazení stránky Download.aspx
  • args = new string[] { id.ToString(), filename, path }
  • Funkce může vracet výslednou cestu k souboru na disku, který bude předán uživateli ke stažení, řetězec musí začínat OK\r\n

5.9. NETGenium.Elearning.Test.ERROR

  • Spustí se po neúspěšném složení testu
  • 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, řetězec musí začínat OK\r\n

5.10. NETGenium.Elearning.Test.OK

  • Spustí se po úspěšném složení testu
  • 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, řetězec musí začínat OK\r\n

5.11. NETGenium.ExcelPassword

  • Spustí se před zašifrováním excelového souboru
  • args = new string[] { }
  • Funkce musí vracet heslo pro zašifrování excelového souboru, řetězec musí začínat OK\r\n

5.12. NETGenium.Import

  • Spustí se při zobrazení stránky Import.aspx
  • args = new string[] { }
  • Funkce může vracet html, které se vloží do response
  • Pokud funkce nic nevrátí, do response se uloží prázdný string

5.13. NETGenium.ImportXml

  • Spustí se při zobrazení stránky ImportXml.aspx
  • args = new string[] { }
  • Funkce může vracet html, které se vloží do response
  • Pokud funkce nic nevrátí, do response se uloží prázdný string

5.14. NETGenium.LockRecord

  • Spustí se při zamknutí databázového záznamu
  • args = new string[] { form.ToString(), id.ToString() }

5.15. NETGenium.Log

  • Spustí se při logování na disk
  • args = new string[] { filenameWithoutExtension, message, logLevel.ToString(), loginname }

5.16. NETGenium.LoginCode

  • Spustí se před každým přihlášením uživatele pomocí uživatelského jména a hesla
  • Funkce musí vracet autentizační kód, který musí uživatel následně vyplnit v rámci dvoufaktorové autentizazace – řetězec musí začínat OK\r\n
  • Funkce musí tento kód uživateli odeslat odeslat buď pomocí emailu, nebo pomocí SMS

5.17. NETGenium.Logout

  • Spustí se po odhlášení uživatele
  • 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

5.18. 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.19. NETGenium.Menu1

  • Spustí se v editačním formuláři, na nahlížecí stránce, nebo v portletech
  • args = new string[] { }
  • Funkce musí vracet html, které se vloží na začátek stránky, např. OK\r\nhtml

5.20. NETGenium.Menu2

  • Spustí se v editačním formuláři, na nahlížecí stránce, nebo v portletech
  • args = new string[] { }
  • Funkce musí vracet html, které se vloží na konec stránky, např. OK\r\nhtml

5.21. NETGenium.OnAfterLogin

  • Spustí se po úspěšném přihlášení uživatele
  • 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...');"

5.22. NETGenium.OnAfterPrint

  • Spustí se ihned po tisku do tiskové šablony těšně před odesláním souboru na klientskou stanici, takže je možné soubor pomocí externí funkce ještě zmodifikovat
  • conn.PrintingProcess.File - cesta k souboru, do kterého se tiskne
  • conn.PrintingProcess.FileName - název souboru, který bude uživateli nabídnut ke stažení - možno změnit
  • conn.PrintingProcess.Template - cesta k tiskové šabloně
  • 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

5.23. 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.
    • Automatické přihlášení díky Azure Active Directory a LoginByMicrosoft.aspx: args = new string[] { email }
      • Externí funkce se spustí po úspěšné autentizaci uživatele na webu Microsoftu, 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.
  • 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í přihlašovacího tokenu, který NET Genium při autentizaci uživatele ukládá do session objektu "microsoft_access_token"
  • 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.24. NETGenium.OpenForm

  • Spustí se v editačním formuláři ihned po otevření připojení do databáze
  • args = new string[] { ds.Form.ID.ToString() }
  • Funkce je 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.25. NETGenium.OpenPortlets

  • Spustí se v portletech ihned po otevření připojení do databáze
  • args = new string[] { appgroup.ToString() }

5.26. NETGenium.OpenViewPage

  • Spustí se na nahlížecí stránce ihned po otevření připojení do databáze
  • args = new string[] { viewpage.ID.ToString() }

5.27. 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
  • args = new string[] { (int)MathExt.Round(time.TotalMilliseconds).ToString() }

5.28. NETGenium.Payment

  • Spustí se při zobrazení stránky Payment.aspx
  • args = new string[] { }
  • Funkce může vracet html, řetězec musí začínat OK\r\n

5.29. NETGenium.PaymentNotification

  • Spustí se při zobrazení stránky PaymentNotification.aspx
  • args = new string[] { }
  • Funkce může vracet html, řetězec musí začínat OK\r\n

5.30. 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.31. NETGenium.PlannerCellColorWeekend

  • Spustí se při zobrazení buňky v planneru
  • args = new string[] { }
  • Funkce musí vracet barvu buňky o víkendu ve formátu R,G,B, řetězec musí začínat OK\r\n

5.32. NETGenium.PlannerCellHtml

  • 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 html, řetězec musí začínat OK\r\n

5.33. 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)
  • Touto situací je například přímé vyvolání stránky ngef.aspx například ve webovém prohlížeči
  • Funkce může vracet OK\r\n, čímž spuštění dané externí funkce povolí
  • Volání této funkce je alternativou k seznamu anonymních externích funkcí, který se definuje v nastavení NET Genia

5.34. 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.

5.35. 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.36. 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() };
  • Funkce musí vracet barvu buňky ve formátu R,G,B, řetězec musí začínat OK\r\n

5.37. NETGenium.Translate

  • Spustí se při zobrazení stránky Translate.aspx
  • args = new string[] { sourcelanguage, targetlanguage, sourcevalue, format }
  • Funkce může vracet html, řetězec musí začínat OK\r\n

5.38. NETGenium.UnlockRecord

  • Spustí se při odemknutí databázového záznamu
  • args = new string[] { form.ToString(), id.ToString() }

5.39. NETGenium.Url

  • Spustí se před odesláním e-mailové zprávy ze skriptu
  • 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

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.ExecuteScalar2("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.ExecuteScalar2("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);

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.ExecuteScalar2("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.ExecuteScalar2("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;

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.Request.Form["p0"]);
sb.Append(", ");
sb.Append(conn.Page.Request.Form["p1"]);
Html.FlushAjaxContent(sb.ToString(), conn);
}

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 = conn["name"].ToString();
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]);
}
 

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]), id = (int)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]), id = (int)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í hodnotou 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 cliboardu 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);
}
}

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] = dictionary[id]["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.IO;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
string temp = Path.GetTempFileName();
Files.Write(temp, "abc");

int file = Attachment.Add("test.txt", temp, conn);
File.Delete(temp);
Console.WriteLine(file);

return "";
}

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

using NETGenium;
using System;
using System.IO;

private static string MyFirstFunction(string[] args, DbCommand cmd, DbConnection conn)
{
string temp = Path.GetTempFileName();
Files.Write(temp, "abc");

int file = Attachment.Add("test.txt", temp, conn);
File.Delete(temp);
Console.WriteLine(file);

string path = Attachment.FilePath(file, conn);
if (File.Exists(path))
{
string s = File.ReadAllText(path);
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;
}

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>");

MailMessage message = new MailMessage();
message.From = new MailAddress("@");
message.To.Add(new MailAddress("@"));
message.Subject = "";
message.AlternateViews.Add(Config.CreateTextAlternateView(Html.ToText(html)));
message.AlternateViews.Add(Config.CreateHtmlAlternateView(html, conn));

Config.SendMessage(message, conn);
}

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;

private static string SendMessage(string[] args, DbConnection conn)
{
MailMessage message = null;
bool save = false;

foreach (object co in conn.Container)
if (co is MailMessage)
{
message = (MailMessage)co;
}
else if (co is bool)
{
save = (bool)co;
}

return "skipsave";
}

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();
}

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 void OnBeforeLogin(string[] args, DbConnection conn)
{
string loginby = args[0];
DbRow row;

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

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["ng_aktivni"].ToString().Length == 0)
{
return "Neplatné přihlášení.";
}

return null;
}

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.Error("MyFirstFunction", ex);

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

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

return "";
}

15.2. Zachycení události z a m čení databázov ého záznam u

// case "NETGenium.LockRecord": LockRecord(); return "";
// case "NETGenium.UnlockRecord": UnlockRecord(); 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 " + DateTime.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; }";
}