ASP.NET Core: Duplicate ‚Content‘ items were included. The .NET SDK includes ‚Content‘ items from your project directory by default.

Pokud dostanete na ASP.NET Core projektu ve Visual Studiu hlášku o duplicitním Contentu:

Error Duplicate ‚Content‘ items were included. The .NET SDK includes ‚Content‘ items from your project directory by default. You can either remove these items from your project file, or set the ‚EnableDefaultContentItems‘ property to ‚false‘ if you want to explicitly include them in your project file. For more information, see https://aka.ms/sdkimplicititems. The duplicate items were: ‚wwwroot\Index.html‘ Web C:\Program Files\dotnet\sdk\1.1.0\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.Sdk.DefaultItems.targets 188

…jedná se o nadrbaný .csproj a pomůže odebrat a přidat složky wwwroot z projektu:

  1. Solution Explorer – pravým na ~/wwwroot – Exclude From Project
  2. zapnout si viditelnost excludovaných souborů – Solution Explorer – Show All Files (jedna z ikonek nahoře)
  3. Solution Explorer – pravým na ~/wwwroot – Include in Project

TFS2017: SQL Query pro počet changesetů dle uživatele

…byl to nakonec trochu opruz dohledat správně uživatele, tak dávám do pléna

SELECT i.AccountName, COUNT(*)
	FROM tbl_ChangeSet AS cs
		LEFT JOIN tbl_IdentityMap im ON cs.OwnerId = im.localId
		LEFT JOIN Tfs_Configuration.dbo.tbl_Identity i ON im.masterId = i.Id
	GROUP BY i.AccountName WITH ROLLUP
	ORDER BY COUNT(*) DESC

Tipy a triky v .NET a C# – slides, dema a záznam [TechEd Praha 05/2017]

Slides, dema a záznam z mé přednášky pro TechEd DevCon Praha ze 17.5.2017:

Záznam z přednášky je publikován na našem HAVIT YouTube Channel.

Dotčená témata

  • VS – Windows Layouts
  • C# – NoRefactoringsInInactiveCode
  • C# – MSTestV2TestCases
  • VS Keyboard Shortcuts
  • C# – InternalsVisibleTo
  • C# – Test – HardcodedDependenciesTestability
  • VS – [Re-]Attach to process
  • VS – BoxSelection
  • C# – NameOf – nameof()
  • C# – Initializers + InitializersArray
  • VS – MoveLineUpDown
  • C# 5.0 – Caller Info Attributes
  • VS – Extensions.md
  • VS – Personal Tweaks.md
  • C# – Using Without Variable
  • C# – DebuggerDisplay ([DebuggerBrowsable], [DebuggerStepThrough])
  • C# – AsyncLocal

Azure PaaS – Praktické zkušenosti, tipy a triky – slides a záznam [TechEd Praha 05/2017]

Slides, dema a záznam z mé přednášky pro TechEd DevCon Praha z 16.5.2017:

Záznam z přednášky je publikován na našem HAVIT YouTube Channel.

Dotčená témata

  • IaaS vs. PaaS vs. XaaS
  • Motivace k Azure PaaS vs. Co vás může odradit
  • Klíčové služby
    • App Service
    • Azure SQL
    • Azure Storage
    • Application Insights
  • Praktické scénáře
    • Deployment (MSDeploy)
    • Práce se soubory IFileStorage
    • Práce s časem (DateTime.Now v UTC vs. ITimeService)
    • Posílání e-mailů (SendGrid)
    • Naplánované úlohy (Quartz.NET, WebJobs, WebJobs SDK, Dashboard)

Novinky ve VS2017 a C# 7.0 – slides, dema a záznam [TechEd Praha 05/2017]

Slides, dema a záznam z mé přednášky pro TechEd DevCon Praha z 15.5.2017:

Záznam z přednášky je publikován na našem HAVIT YouTube Channel.

Dotčená témata

  • VS 2017 Novinky
    • Go to All… (Naviagate to…)
    • IntelliSense
    • Find All References
    • Structure Guides
    • Live Unit Testing
    • Installer
    • Debugging – Run to Click
    • Debugging – Exception Helper (NullReferenceException)
  • MSTest v2 [DataRow]
  • Novinky C# 7.0
    • Binary Literals
    • Digit Separators
    • Expression Bodied Members – Constructors, Destructors (Finalizers), Property Accessors
    • throw expressions
    • out variables
    • Tuples
    • Local Functions
    • Pattern Matching
    • ValueTask<>
    • Ref Return, Ref Local

Označování textu v HTML aneb na počtvrté správně a po svém

Cíle

  1. Označit (resp. zvýraznit) text v prohlížeči (Chrome, Firefox, IE, Edge) a to i v mobilních verzích aplikace (Android, iOS, Windows Phone)
  2. Uložit serializovanou podobu označení do úložiště pro pozdější obnovení označení (například při návratu na stránku)
  3. Při novém načtení stránky (render stránky), označit text

Poprvé

Musím se přiznat, že k prvnímu pokusu o označení jsem pouze přišel s tím, že už to je implementované správně a funguje. Nefungovalo. V daném HTML byli vytvořené jakési „stropy“ (offsety), reprezentované prostým span HTML elementem s číselnou hodnotu v datasetu.

Tento kód zde raději ani nesdílím, neb bych nerad, aby se čtenáři udělalo nevolno.

Nebylo možné označování přes více různých elementů – původně počítalo s označením pouze v odstavcích, ale tabulky, divy nebo obrázky to ignorovalo.

Takhle to nepůjde.

Podruhé

Většinou nejprve hledám po internetu, jestli už někdo neřešil podobný problém. Měl jsem štěstí – řešil. Narazil jsem na knihovnu rangy.js. Má svou wiki, kde je krásně popsáno API, takže jsem se mohl podívat, co tato knihovna umí.

rangy.js má v sobě modul pro zvýraznění (Highlighter module), který má dvě implementace:

  • textContent
    • výhody: jednoduchý, rychlý algoritmus
    • nevýhody: změny DOMu mají za následek, označení něčeho jiného než bylo před změnou DOMu označeno, i jakýkoli bilý znak (white-space) měl za následek mutaci označení
  • TextRange
    • výhody: odolný proti zápisu více bílých znaků (white-space)
    • nevýhody: extrémně pomalý

Implmentace „textContent“ nemohla být použita, protože mobilní aplikace renderovala HTML trochu jinak a to i přesto, že bylo použito Chromium (jádro Chrome tzn. stejný render engine).

Zkusil jsem implementaci „TextRange“. Nepoužitelné. Mobilní aplikaci trvalo až 10s než vyrenderuje označené HTML.

I když bylo označení vždy přesné, tak z výkonových důvodu jsem od něj upustil.

Potřetí

Tento postup, už jsem vymýšlel já. Spoočíval v serializaci Range objektu velmi jednoduchou metodou. Range objekt má v sobě startContainer, startOffset, endContainer a endOffset. Serializace probíhá tak, že se vygeneruje validní selektor elementu startContainer a endContainer relativně ke zvolenému HTML elementu (například k body) a spočítá se startOffset a endOffset v daných start/end kontejnerech.

// Takto vypadá definice selektoru, který lze uložit do databáze jako JSON
interface IHtmlElementSelectorResult {
   selector: string;
   childNodeIndex: number;
   offset: number;
}
// Takto vypadá příklad serializované reprezentace Range objektu
{
   start: {
       selector: "div > div > p:nth-of-type(4)",
       childNodeIndex: 0,
       offset: 10
   },
   end: {
       selector: "div > div > p:nth-of-type(8) > strong",
       childNodeIndex: 0,
       offset: 5
   }
}

Z takto serializované hodnoty, lze velmi snad zrekonstruovat Range objekt a nad ním poté provést označení.

Dokud nezmutuje DOM. Pokud zmutuje, tak není možná rekonstrukce. A právě tím, že chceme označit text, tak DOM mutuje (vkládáme <span> HTML elementy, které zvýrazňují text).

Takže znova a jinak.

Počtvrté

Opět jsem se vyskytl na zelené louce.

S kolegou jsme se nad tímto problémem zamysleli z jiného pohledu. Označení nebude prováděno na základě znalosti (reprezentace) DOMu, ale na základě znalosti počtu výskytu jednotlivých slov, které jsme vybrali, že chceme označit a které se „lámali“ skrze DOM.

Pustil jsem se do implementace. Procházením DOMU a sbíráním počtu výskytu označených slov, jsem došel k cíli. Fungovalo to jak na desktopu, tak i na mobilních aplikacích, je to relativně svižné – PC maximálně malé stovky milisekund, i při označení obrovského kusu textu (DOMu), na mobilních aplikacích podobně.

Využil jsem k procházení DOMu objekt TreeWalker, který jsem si nastavil tak, aby procházel jen ten označený kus textu a spočítal si výskyty slov. Výpočet jsem si uložil do JSON, který ač je závislý na velikosti textu a počtu výskytu slov, tak funguje skvěle.

TL;DR

Pro označení, uložení pozice a opětovné označení textu v HTML (DOM) nejsou vhodné způsoby:

  • Vlastní implementace způsoby jako „počet znaků od začátku body elementu“, „počet znaků označeného textu“
  • Použití knihovny rangy.js (nad kterou se v době psaní tohoto článku stejně už 2 roky nic neděje)
  • Vlastní implementace způsobem serializace a deserializace Range objektu

Zatím jediný a funkční způsob byl vlastní implementace založená na znalosti označeného textu a počet výskytů jednotlivých slov, případně úseků slov – záleží na tom jak moc je DOM komplikovaný/velký/strukturovaný.

Working Effectively with Legacy Code – záznam, dema a slides [WUG Praha 04/2017]

Slides z mé přednášky pro WUG Praha z 26.4.2017:

Záznam z přednášky je publikován na našem HAVIT YouTube Channel.

Dotčená témata

  • „definice“ Legacy Code
  • Refactoring Mindset
  • Roslyn Code Analyzers – C#, StyleCop, SonarLint, Global Suppressions
  • Testability – extract dependencies do virtuálních metod + override v testu
  • Mocking – Moq
  • Advanced Testing – Fixture
  • extrakce dependencies, Dependency Injection

.NET C# – Parallel, Async – Martin Havel [HAVIT Vzdělávací okénko 6.4.2017]

Záznam a dema z příspěvku Martina Havla pro Vzdělávací okénko HAVIT z 6.4.2017:

Záznam je publikován na našem HAVIT YouTube Channel.

Dotčená témata

  • Thread.Start()
  • Task.Run()Task.Factory.StartNew()
  • Parallel.For()Parallel.Invoke()
  • awaitasync
  • ThreadPool.QueueUserWorkItem()
  • kvízy

Vzdělávací okénka máme v HAVITu každý čtvrtek odpoledne pro vzájemné obohacování v technologických dovednostech. Vybrané příspěvky budeme touto cestou publikovat, zvažujeme i umožnit účast na vzdělávacích akcích i příchozím z ulice. ;-)

TFS (XAML) Builds – Jak vytvořit lokální workspace

TFS (XAML) Build vytvoří workspace na build serveru, do něj stáhne zdrojové kódy a ty kompiluje. Workspace vytváří aktivita CreateWorkspace, která vytvoří serverový workspace a není způsob, jak této aktivitě říct, aby vytvořila workspace lokální. Aktivita CreateWorkspace navíc vrací instanci reprezentující založený workspace.

Když tedy nelze při říct, že založený workspace má být lokální, lze použít drobný workaround – založit workspace jako serverový a dodatečně jej přepnout na lokální. To lze provést zavoláním metody Update na instanci vrácené z CreateWorkspace. V rámci TFS (XAML) Buildu to můžeme udělat reflexí, tedy aktivitou InvokeMethod s těmito parametry:

  • Target Object: Workspace (resp. taková proměná, ve které máme vrácenou instanci z activity CreateWorkspace)
  • Method Name: Update
  • Parameters: In / Microsoft.TeamFoundation.VersionControl.Client.UpdateWorkspaceParameters / New UpdateWorkspaceParameters With { .Location = Microsoft.TeamFoundation.VersionControl.Common.WorkspaceLocation.Local }

O rozdílech mezi lokálním a serverovým workspacem si můžete přečíst tady nebo tady. Naše touha pro přechod ze serverového na lokální workspace byla vedena přiblížením prostředí buildu vývojářskému prostředí, zejména nenastavení read-only atributů na stažených souborech.

 

[ASP].NET Worst Practices – záznam, slides a dema [MS Fest Brno 03/2017]

Slides a dema z mé přednášky pro konferenci MS Fest Brno z 19.3.2017:

Záznam z přednášky je publikován na našem HAVIT YouTube Channel.

Dotčená témata

  • skládání stringů vs. StringBuilder
  • vyhledávání v datech – List vs. BinnarySearch vs. Dictionary vs. LINQ ToLookup()
  • ASP.NET Sessions
  • ASP.NET Over-posting / Mass-assignment
  • Nevěřte vstupu od klientů