Představení problému s cyklem for v Blazoru, kde se při použití s RenderFragment může objevit poslední hodnota řídící proměnné. Je potřeba řídící proměnnou vykopírovat do lokální proměnné nebo se jí vyhnout cyklem foreach.
Exception types – kdy který použít [Vzdělávací okénko, 10.4.2025]
NotImplementedException– výhradně během vývoje jako TODONullReferenceException– nikdy nevyhrazujeme explicitně, výhradně vyhazováno runtimemNotSupportedException– explicitně indikujeme, že o use-case víme, ale není řešenInvalidOperationException– „nemělo by v produkci nastat“, chyba vývoje (nesprávné volání ,switchnad nečekanou hodnotouenum, …)ArgumentNullException,ArgumentOutOfRangeException– výhradně přímé argumenty (nearg1.Property != null)ArgumentException– obecný problém s argumentem/-y (bližší specifikace vMessage)ContractFailedException– default proContract.Requires(cond),Contract.Assert(cond), …Exception– nedoporučuje se vyhazovat, mělo být spíšeabstract, použijte potomkyOperationFailedException– indikace chyby do UI (specficiké pro Havit.Blazor stack)ApplicationException– deprecated
Záznam ze Vzdělávacího okénka HAVIT z 10. dubna 2025.
Blazor – Proč nepoužívat parametry v OnInitialized [Vzdělávací okénko, 3.4.2025]
V tomto videu se podíváme na důležitý technický detail v Blazoru, který představil – proč by se v metodě OnInitialized popř. OnInitializedAsync neměly používat parametry. Ukážeme si na příkladu konkrétního problému, který může nastat, když komponenta nezmění instanci při změně routy a parametr zůstane se starou hodnotou. Dozvíš se:
- Jak funguje lifecycle metoda
OnInitializedv Blazoru - Proč je nevhodné používat
[Parameter]hodnoty v této fázi - Jaké chyby to může způsobit v praxi
- Kdy (a jestli vůbec) je použití parametrů v
OnInitializedv pořádku
Záznam ze Vzdělávacího okénka HAVIT z 3. dubna 2025.
YAML Pipelines – Azure DevOps [Jiří Kanda, Vzdělávací okénko, 27.3.2025]
V tomto videu se dozvíte vše o našich nových YAML pipelines v Azure DevOps, které prezentuje Jiří Kanda. Jirka vysvětluje, proč jsme se rozhodli přejít na YAML pipelines a jaké výhody nám to přináší.
- Specifika našich buildů a důvody pro změnu na YAML pipelines.
- Výhody YAML pipelines, jako jsou lepší parametrizace a paralelizace.
- Základní syntaxe YAML a struktura YAML pipelines.
- Paralelní běh jobů a použití více agentů.
- Volitelné parametry buildů a task scheduler.
- Podpora pro integrační testy a automatické pull requesty.
- Použití deduplication a reprodukovatelnost buildů.
- Validace zranitelností nuget balíčků a definice pipeline v projektech.
- Problémy s manuálním spuštěním buildů.
Záznam ze Vzdělávacího okénka HAVIT z 27. března 2025.
await foo?.DoAsync() [Vzdělávací okénko, 20.3.2025]
Krátce o pasti zápisu await foo?.DoAsync(), kdy použití null-conditional accessu vede na await null a NullReferenceException.
Blazor ValueExpression binding a validace – záznam [Vzdělávací okénko, 13.3.2025]
Tentokrát o ValueExpression parametrech v Blazoru a potřebě jejich správného použití pro fungování validací.
Záznam ze Vzdělávacího okénka HAVIT z 13. března 2025. Zkoušíme zpestřit novým formátem mini-okének, kde se budou objevovat ad-hoc témata v řádu 2-10 minut.
Novinky v .NET 9 a výhled na .NET 10 – záznam a slides [Robert Haken, WUG Dev Day, 28.2.2025]
Záznam ze Vzdělávacího okénka HAVIT z 28. února 2025, kde jsem telegraficky představoval novinky z „.NET 9 vlny“ a přicházející v „.NET 10 vlně“.
Slides
I[Async]Enumerable [Jiří Kanda, Vzdělávací okénko, 31.10.2024]
Záznam ze Vzdělávacího okénka HAVIT z 31. října 2024, kde Jiří Kanda povídal o IEnumerable interface a jeho asynchronní verzi IAsyncEnumerable.
Azure Entra ID – Conditional Access Policies [Dan Hrubý, HAVIT Vzdělávací okénko, 26.9.2024]
Záznam ze Vzdělávacího okénka HAVIT z 26. září 2024, kde Daniel Hrubý povídal o Microsoft Azure Entra ID a aspektech jako MFA, Conditional Access Policies, B2B Collaboration atp.
[Blazor] await periodicTimer.WaitForNextTickAsync() – dobrý sluha, ale špatný pán
Pozor na await periodicTimer.WaitForNextTickAsync(). Tato metoda láká svojí asynchronní signaturou k pohodlnému uspořádání periodických úloha a zejména v Blazoru vás tak může zlákat k implementaci aktualizací UI:
protected override async Task OnInitializedAsync()
{
await StartTimerAsync();
}
private async Task StartTimerAsync()
{
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(10));
while (await timer.WaitForNextTickAsync())
{
// do some UI updates here
}
}
POZOR! Takovéto uspořádání sice neblokuje UI thread a díky async-await to jede dál, problém je však v tom, že metoda, z které se takovýto kód volá, nikdy neskončí.
Pokud tedy například takovýto StartTimeAsync() přímo zavolám z OnIntializeAsync/OnParametersSetAsync/OnAfterRenderAsync/action-callbacku, pak tato parent-metoda nikdy neskončí a může to mít dost nečekané následky. Například:
- pokud to zavolám z
HxButton.OnClickobsluhy tlačítka, zůstane mi tam viset spinner, který nikdy neskončí,- tlačítko navíc zůstane pod single-click-protection, disabled, nepoužitelné,
- pokud to zavolám z
override OnInitializedAsync(), nedojde v prvním roundtripu k zavoláníOnParametersSet[Async]()a dokud nepřijde další roundtrip, tak se miOnParametersSet[Async]()neprovedou, - pokud to zavolám z
override OnParametersSetAsync(), zůstává mi viset nedokončenýTaskvComponentBase.CallStateHasChangedOnAsyncCompletion(), navíc musím ošetřit, že seOnParametersSetAsync()volá opakovaně a nechci si timerů pustit více, - pokud to zavolám
z override OnAfterRenderAsync(bool firstRender), mohu si tím zablokovat voláníawait base.OnAfterRenderAsync(firstRender), což mi může narušit funkčnost definovanou předkem při dědění (zejména profirstRender = true, které se provádí jen jednou)
PeriodicTimer.WaitForNextTickAsync() se tedy hodí do scénářů, kdy je zaručeno, že volající kód nikam nepokračuje a mohu se na příslušném místě točit „do nekonečna“ (např. jsem v metodě Main a točím nějakou cyklickou úlohu v konzolové aplikaci, nebo jsem v BackgroundService.ExecuteAsync()). Obecně však je potřeba dovolit dokončení volající metody a tedy pro spouštění použít tradiční uspořádání s Task.Run(..), kdy umístíme timer (může to být i klasický Timer, asynchronní metoda WaitForNextTickAsync() zde již nehraje tak velkou roli) na ThreadPool a neawaitujeme v aktuální metodě jeho dokončení (fire & forget). V případě Blazoru si v takovém případě musíme ručně volat StateHasChanged(), popř. DispatchExceptionAsync().
public MyComponent : IDisposable
{
private PeriodicTimer timer;
protected override async Task OnInitializedAsync()
{
_ = Task.Run(StartTimerAsync);
}
private async Task StartTimerAsync()
{
timer = new PeriodicTimer(TimeSpan.FromSeconds(10));
while (await timer.WaitForNextTickAsync())
{
// do some UI updates here
StateHasChanged(); // as needed
}
}
public void Dispose()
{
timer?.Dispose();
}
}
Nesmíme samozřejmě zapomenout na úklid – timer.Dispose(), jinak nám Timer zůstane běžet i po zániku komponenty, vzniká resource-leak atd.
Viz též ASP.NET Core Blazor dokumentace: