<?xml version="1.0" encoding="utf-8"?>
<rss
  version="2.0">
  <channel>
    <title>Posts</title>
    <link>https://volaresoftware.com/nl</link>
    <description>Volare Software</description>
    <lastBuildDate>Wed, 06 May 2026 11:06:34 Z</lastBuildDate>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/buy-build-or-both</guid>
      <link>https://volaresoftware.com/nl/articles/buy-build-or-both</link>
      <title>Kopen, bouwen of allebei?</title>
      <description>&lt;p&gt;U wilt een nieuwe markt aanboren, kosten verlagen, of een proces automatiseren. Nieuwe software kan helpen, maar welke software past bij uw situatie?&lt;/p&gt;
&lt;p&gt;Er zijn drie hoofdcategorieën: 1) standaardsoftware, 2) software as a service (SaaS), en 3) maatwerksoftware. Dit artikel bespreekt de voor- en nadelen van elk type en helpt u de juiste keuze te maken.&lt;/p&gt;
&lt;p&gt;Een goed vertrekpunt is de vraag of het proces dat u wilt oplossen een concurrentievoordeel is of een standaardactiviteit. Als alle bedrijven in uw sector hetzelfde proces op dezelfde manier uitvoeren, is een pakketoplossing waarschijnlijk de juiste keuze. Als het proces juist onderscheidend is voor uw organisatie, is het de moeite waard om te overwegen de software die dat proces aantuurt zelf te bezitten.&lt;/p&gt;
&lt;h3 id="wanneer-is-standaardsoftware-of-saas-de-juiste-keuze"&gt;Wanneer is standaardsoftware of SaaS de juiste keuze?&lt;/h3&gt;
&lt;p&gt;Als u een tekstverwerker, e-mailclient, of boekhoudpakket nodig heeft, is het al gedaan. Het aanbod is groot, de producten zijn volwassen, en de prijzen lopen uiteen van gratis tot zeer betaalbaar.&lt;/p&gt;
&lt;p&gt;Steeds meer bedrijfssoftware valt in deze categorie, zoals enterprise content management, documentbeheer en CRM-software. Deze tools hebben een duidelijk doel en zijn daar doorgaans goed in.&lt;/p&gt;
&lt;p&gt;Qua kosten is standaardsoftware kopen meestal goedkoper dan maatwerksoftware laten bouwen. Dat klopt vaak, maar er zijn nuances die dit beeld kunnen veranderen.&lt;/p&gt;
&lt;p&gt;Dit is waar de meeste software-evaluaties eindigen. Het voldoet aan de eisen en het is goedkoper. Gewoon kopen en doorgaan, toch? Even niet zo snel.&lt;/p&gt;
&lt;p&gt;Er zijn risico's aan standaardsoftware en SaaS die vaak over het hoofd worden gezien:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ze bevatten vaak modules die u niet nodig heeft en missen soms functionaliteit die u wel nodig heeft. Extra modules kosten extra. Implementatie en aanpassing aan uw organisatie ook.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ze werken in functionele silo's en komen vaak van meerdere leveranciers. U moet zeker weten dat integratie met uw bestaande systemen haalbaar is.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ze geven u mogelijk niet de controle over uw eigen data die u nodig heeft.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uw gebruikers zijn misschien minder enthousiast over uw keuze dan uzelf.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Laten we deze risico's nader bekijken en bepalen wanneer ze de balans richting maatwerksoftware doen doorslaan.&lt;/p&gt;
&lt;h3 id="precies-wat-u-nodig-heeft-niet-meer-en-niet-minder"&gt;Precies wat u nodig heeft, niet meer en niet minder&lt;/h3&gt;
&lt;p&gt;Standaardsoftware kopen is de juiste keuze als het pakket volledig aansluit op uw bedrijfsprocessen. Maar in de praktijk koopt u vaak functionaliteit die u niet gebruikt en mist u functionaliteit die u wel nodig heeft. U zou uw bedrijfsvoering niet moeten aanpassen aan de software die u aanschaft.&lt;/p&gt;
&lt;p&gt;De gebruikelijke oplossing is consultants inschakelen om het pakket te implementeren en aan te passen. Als de software grotendeels aansluit op uw eisen, kan dat goed werken. U wilt dan dat consultants de scherpe randjes bijvijlen, niet dat ze het systeem herschrijven. Ze configureren het voor uw organisatie en koppelen het eventueel aan bestaande systemen.&lt;/p&gt;
&lt;p&gt;Op een gegeven moment, en dat moet vrij snel na de implementatie zijn, moeten de consultants klaar zijn en vertrekken. Als ze blijven terugkomen voor aanpassingen en integraties, bent u de rechtvaardiging voor kopen in plaats van bouwen al kwijt.&lt;/p&gt;
&lt;p&gt;Hier zit het addertje onder het gras dat organisaties vaak verrast: die aanpassingen blijven niet staan. Wanneer de leverancier een nieuwe versie uitbrengt, moet elke aanpassing opnieuw worden beoordeeld, getest, en in veel gevallen herschreven om de upgrade te overleven. Organisaties die zwaar hebben gecustomised, besteden structureel ontwikkelcapaciteit aan het bijhouden van hun eigen afwijkende versie. Op dat moment heeft u geen software meer gekocht. U heeft een startpunt gehuurd en vaste medewerkers aangenomen om de kloof met de standaardversie te onderhouden. Maatwerksoftware kost meer bij de start, maar u betaalt niet permanent voor aanpassingen die u eigenlijk nooit had moeten hoeven maken.&lt;/p&gt;
&lt;h3 id="diepe-integratie-met-uw-bestaande-systemen"&gt;Diepe integratie met uw bestaande systemen&lt;/h3&gt;
&lt;p&gt;Bij standaardsoftware loopt integratie met uw andere systemen uiteen van eenvoudig tot een volwaardig implementatieproject. Als u bijvoorbeeld CRM-software aanschaft en uw bestaande klantgegevens wilt importeren, zou dat standaard moeten werken. Pijnlijke integraties ontstaan wanneer u de data er niet uitkrijgt, of alleen via een leveranciers-API die per definitie niet is ontworpen om volledige export gemakkelijk te maken.&lt;/p&gt;
&lt;p&gt;Als het nieuwe systeem onderdeel is van een groter proces, of als het de centrale databron wordt voor uw organisatie, zijn er veel integratiepunten voor data die in en uit het systeem stromen.&lt;/p&gt;
&lt;p&gt;Bij maatwerksoftware zijn die integratiepunten ingebouwd omdat ze onderdeel zijn van de oorspronkelijke eisen. De software integreert diep met uw huidige systemen. Als het goed gedaan is, zijn de nieuwe APIs op een standaard manier gebouwd, zodat toekomstige applicaties er zonder extra werk gebruik van kunnen maken.&lt;/p&gt;
&lt;h3 id="hoe-stabiel-is-die-leverancier-wat-is-uw-exitstrategie"&gt;Hoe stabiel is die leverancier? Wat is uw exitstrategie?&lt;/h3&gt;
&lt;p&gt;De waardepropositie van standaardsoftware is de functionaliteit die u krijgt voor de prijs die u betaalt. Maar die waarde verdampt als de leverancier failliet gaat, wordt overgenomen, of de prijs verhoogt op het moment dat u te diep verweven bent om gemakkelijk te vertrekken. En hoe meer u heeft aangepast, hoe lastiger de overstap wordt. Dat is geen toeval.&lt;/p&gt;
&lt;p&gt;SaaS-bedrijven zijn hier bijzonder goed in. Lage instapprijzen halen u aan boord. Integratie met uw systemen en jaren aan opgeslagen data verhogen uw overstapkosten. Bij contractverlenging onderhandelt u vanuit een zwakke positie.&lt;/p&gt;
&lt;p&gt;Veel SaaS-platforms kennen ook geen standaard-API die concurrerende producten ondersteunen. Dat betekent dat uw exitplan een migratieproject vereist, niet alleen een beslissing. Voordat u een meerjarig contract tekent, moet u precies weten hoe u uw data terugkrijgt en in welk formaat. En test het. Voer de export uit in een niet-productieomgeving en controleer of het resultaat ook daadwerkelijk bruikbaar is. De meeste organisaties doen dit pas als het nodig is, en dat is precies het slechtste moment om te ontdekken dat het plan niet werkt.&lt;/p&gt;
&lt;p&gt;Bij maatwerksoftware bezit uw organisatie de code en de data vanaf dag één. Er is geen leverancier om mee te onderhandelen en geen eigen formaat om uit te ontsnappen.&lt;/p&gt;
&lt;h3 id="waar-staat-uw-data"&gt;Waar staat uw data?&lt;/h3&gt;
&lt;p&gt;Bij standaardsoftware staat de data vaak in een eigen database. Zelfs als het een gangbaar formaat is, ondersteunen veel leveranciers geen directe queries op hun dataopslag, of berekenen ze extra voor rapportagetoegang.&lt;/p&gt;
&lt;p&gt;Bij SaaS staat uw data in de cloud, op infrastructuur die u niet beheert en in een jurisdictie die u mogelijk niet heeft gekozen. Voor sommige organisaties is dat geen probleem. Voor enterprise-organisaties die opereren onder de AVG, sectorspecifieke regelgeving, of interne beveiligingseisen is het een reëel obstakel. Toezichthouders accepteren &amp;quot;de leverancier regelt dat&amp;quot; niet als antwoord wanneer er iets misgaat. U blijft verantwoordelijk voor uw data, ongeacht waar die zich bevindt.&lt;/p&gt;
&lt;p&gt;Maatwerksoftware plaatst de data waar uw organisatie dat vereist, omdat opslaglocatie, toegangscontrole en compliancevereisten onderdeel zijn van de oorspronkelijke specificatie. U kunt een beveiligingsaudit doorstaan omdat u de antwoorden kent.&lt;/p&gt;
&lt;h3 id="draagvlak-bij-uw-gebruikers"&gt;Draagvlak bij uw gebruikers&lt;/h3&gt;
&lt;p&gt;Het klassieke IT-inkoopproces is: eisen opstellen, het pakket zoeken dat het beste aansluit, en de technische beoordeling overdragen aan een specialist. Dat werkt prima voor de IT-kant van de afweging.&lt;/p&gt;
&lt;p&gt;Het probleem ontstaat wanneer een pakket is gekozen en gebruikers te horen krijgen dat ze de volgende maandag in training zitten en de maandag daarna met het nieuwe systeem moeten werken. Als gebruikers niet betrokken zijn geweest bij de keuze, kunnen ze het systeem afwijzen of de implementatie ondermijnen.&lt;/p&gt;
&lt;p&gt;Bij maatwerksoftware en maatwerkintegraties worden gebruikers vroeg betrokken bij de eisen, en het nieuwe systeem wordt gebouwd naar hun specificaties. Zij zijn de belangrijkste stakeholders en bepalen mede de toon voor een succesvolle adoptie in uw organisatie.&lt;/p&gt;
&lt;h3 id="conclusie"&gt;Conclusie&lt;/h3&gt;
&lt;p&gt;Software-inkoopbeslissingen kunnen net zo complex zijn als de problemen die ze moeten oplossen. Beslissers moeten de korte en lange termijn kosten en risico's afwegen van het kopen van standaard- of SaaS-software, het kopen en aanpassen ervan, of het volledig inzetten op maatwerksoftware. Het makkelijkste antwoord is niet altijd het beste antwoord als alle risico's worden meegewogen.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact op met Volare Software&lt;/a&gt; voor meer informatie over &lt;a href="https://volaresoftware.com/nl/services/custom-software-development"&gt;maatwerksoftware laten bouwen&lt;/a&gt; voor uw organisatie.&lt;/p&gt;
</description>
      <pubDate>Wed, 06 May 2026 11:06:34 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/what-is-custom-software</guid>
      <link>https://volaresoftware.com/nl/articles/what-is-custom-software</link>
      <title>Wat is maatwerk software?</title>
      <description>&lt;p&gt;Zeker, we verkopen software op maat, maar we zullen vaak de eerste zijn om off-the-shelf software aan te bevelen als dat beter past bij uw budget, bereik of tijdlijn. Off-the-shelf software is handig en kosteneffectief, maar soms voldoet het niet helemaal aan de unieke behoeften van uw bedrijf. In die gevallen kan softwareontwikkeling op maat de betere keuze zijn.&lt;/p&gt;
&lt;p&gt;U vraagt zich misschien af: wat IS maatwerksoftware precies? En wat is het verschil met de social media-apps op uw telefoon of de tekstverwerker die u op uw werk gebruikt?&lt;/p&gt;
&lt;p&gt;Simpel gezegd is maatwerksoftware een op maat gemaakte oplossing die speciaal is ontworpen voor de behoeften van uw bedrijf. In tegenstelling tot kant-en-klare software, die is ontworpen om te worden gebruikt door een breed scala van personen en organisaties, wordt maatwerksoftware gebouwd met uw specifieke bedrijfsprocessen, eisen en doelstellingen in gedachten.&lt;/p&gt;
&lt;p&gt;Software op maat is in veel opzichten vergelijkbaar met het bouwen van een huis op maat. Net zoals een huis op maat wordt ontworpen om te voldoen aan de specifieke behoeften en eisen van de eigenaar, wordt software op maat ontwikkeld om te voldoen aan de unieke behoeften en eisen van een bedrijf. In beide gevallen is het eindresultaat een oplossing die is afgestemd op de exacte specificaties van de eigenaar en zijn individuele stijl en voorkeuren weerspiegelt. Net zoals een huis op maat een team van architecten, bouwers en ontwerpers vereist om de visie van de eigenaar tot leven te brengen, vereist de ontwikkeling van software op maat een team van ontwikkelaars, ontwerpers en projectmanagers om een oplossing te creëren die voldoet aan de specifieke behoeften van de klant. En net zoals een huis op maat het leven van de eigenaar zowel efficiënter als mooier kan maken, kan software op maat een enorme waarde toevoegen aan een bedrijf, de productiviteit verbeteren, processen stroomlijnen en groei stimuleren.&lt;/p&gt;
&lt;p&gt;Bekijk het zo: de social media-apps die u op uw telefoon gebruikt, zijn ontworpen voor gebruik door een groot publiek, met functies en functionaliteit die zich richten op een breed scala aan gebruikers. Uw tekstverwerkingssoftware kan meer gespecialiseerde functies hebben, maar is nog steeds ontworpen om te worden gebruikt door een breed scala van industrieën en beroepen.&lt;/p&gt;
&lt;p&gt;Aan de andere kant is het voorraadbeheersysteem of de software voor wagenparkbeheer die uw bedrijf gebruikt waarschijnlijk meer gespecialiseerd en afgestemd op de specifieke behoeften van uw bedrijf. Het kan beschikken over functies en functionaliteiten die u niet kunt vinden in kant-en-klare software, en het is ontworpen om uw bedrijf efficiënter en effectiever te laten werken.&lt;/p&gt;
&lt;p&gt;Maatwerksoftware kan vele vormen aannemen, van desktopapplicaties tot mobiele apps en webgebaseerde systemen. Maar welke vorm het ook aanneemt, het doel van software op maat is om een oplossing te creëren die perfect bij uw bedrijf past.&lt;/p&gt;
&lt;p&gt;Waarom zou u maatwerksoftware verkiezen boven kant-en-klare oplossingen? Het antwoord is eenvoudig: omdat de software is ontworpen op basis van de unieke behoeften van uw bedrijf, kan maatwerksoftware een niveau van functionaliteit, efficiëntie en productiviteit bieden dat niet kan worden geëvenaard door standaardoplossingen. En omdat de software specifiek voor uw bedrijf is ontworpen, kan deze gemakkelijker worden geïntegreerd met uw bestaande systemen en processen, waardoor u minder tijd en moeite hoeft te besteden aan het trainen van uw personeel in nieuwe software.&lt;/p&gt;
&lt;p&gt;Bij Volare Software zijn we gespecialiseerd in het ontwikkelen van software op maat. We helpen bedrijven van alle groottes en industrieën om oplossingen te vinden die voldoen aan hun unieke behoeften. Als u moe bent van het gebruik van kant-en-klare software die gewoon niet helemaal past, neem dan &lt;a href="https://volaresoftware.com/nl/contact"&gt;vandaag nog contact met ons&lt;/a&gt; op voor meer informatie over hoe &lt;a href="https://volaresoftware.com/nl/services/custom-software-development"&gt;maatwerk software&lt;/a&gt; uw bedrijf naar een hoger niveau kan tillen.&lt;/p&gt;
</description>
      <pubDate>Tue, 18 Apr 2023 14:20:03 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/ten-mistakes-to-avoid-when-choosing-a-custom-software-development-company</guid>
      <link>https://volaresoftware.com/nl/articles/ten-mistakes-to-avoid-when-choosing-a-custom-software-development-company</link>
      <title>Tien fouten die u moet vermijden bij het kiezen van een bedrijf dat software op maat ontwikkelt</title>
      <description>&lt;h3 id="de-juiste-partner-kiezen-voor-softwareontwikkeling-op-maat"&gt;De juiste partner kiezen voor softwareontwikkeling op maat&lt;/h3&gt;
&lt;p&gt;De juiste softwareontwikkelingspartner kiezen is een van de meest bepalende beslissingen in een softwareproject. De verkeerde keuze kost tijd, geld en soms het project zelf. We bouwen al sinds 2009 enterprise software en hebben deze fouten van beide kanten van de tafel gezien.&lt;/p&gt;
&lt;h3 id="fout-1-een-bedrijf-kiezen-dat-niet-kan-leveren-wat-je-nodig-hebt"&gt;Fout 1: Een bedrijf kiezen dat niet kan leveren wat je nodig hebt&lt;/h3&gt;
&lt;p&gt;Dit klinkt voor de hand liggend, maar veel bedrijven evalueren leveranciers op prijs of beschikbaarheid in plaats van op relevante ervaring. Vraag om voorbeelden van werk dat vergelijkbaar is met jouw project. Niet alleen logo's op een website, maar echte casestudies met resultaten. Een bedrijf dat soortgelijke problemen heeft opgelost, stelt betere vragen en neemt betere beslissingen gedurende het project.&lt;/p&gt;
&lt;h3 id="fout-2-een-bedrijf-kiezen-dat-je-na-de-lancering-niet-kan-ondersteunen"&gt;Fout 2: Een bedrijf kiezen dat je na de lancering niet kan ondersteunen&lt;/h3&gt;
&lt;p&gt;Maatwerk software heeft onderhoud, beveiligingsupdates en verbeteringen nodig over tijd. Een leverancier die na de livegang verdwijnt, laat je achter met een systeem dat niemand meer begrijpt. Vraag hoe ze post-launch ondersteuning regelen voordat je tekent, niet erna.&lt;/p&gt;
&lt;h3 id="fout-3-referenties-en-track-record-niet-controleren"&gt;Fout 3: Referenties en track record niet controleren&lt;/h3&gt;
&lt;p&gt;Je ontwikkelingspartner heeft toegang tot jouw bedrijfsprocessen, jouw gegevens en soms de informatie van jouw klanten. Controleer referenties. Lees onafhankelijke beoordelingen op Clutch of vergelijkbare platforms. Een bedrijf met niets te verbergen maakt dit gemakkelijk.&lt;/p&gt;
&lt;h3 id="fout-4-vaste-prijscontracten-accepteren-zonder-de-risicos-te-begrijpen"&gt;Fout 4: Vaste prijscontracten accepteren zonder de risico's te begrijpen&lt;/h3&gt;
&lt;p&gt;Als prijzen te goed of te precies klinken, vraag dan hoe ze omgaan met scopewijzigingen. Vaste prijscontracten vereisen dat alle vereisten vooraf worden gedefinieerd, wat bij een echt project vrijwel nooit haalbaar is. Wanneer vereisten veranderen, en dat zullen ze, verandert een vast prijscontract jouw leverancier in een tegenstander die discussieert over wat wel en niet in de oorspronkelijke specificatie stond. We hebben nooit op basis van een vaste prijs gewerkt, omdat we het nooit een goed resultaat voor de klant hebben zien opleveren.&lt;/p&gt;
&lt;h3 id="fout-5-de-technologiestack-niet-controleren"&gt;Fout 5: De technologiestack niet controleren&lt;/h3&gt;
&lt;p&gt;Zorg ervoor dat de leverancier bouwt in technologieën die jouw organisatie kan ondersteunen en onderhouden. Als jouw IT-afdeling draait op Microsoft Azure en .NET, creëert een leverancier die een onbekend platform voorstelt een langetermijn onderhoudsprobleem. Vraag specifiek waarmee ze zullen bouwen en waarom.&lt;/p&gt;
&lt;h3 id="fout-6-het-belang-van-communicatie-onderschatten"&gt;Fout 6: Het belang van communicatie onderschatten&lt;/h3&gt;
&lt;p&gt;Je werkt maanden nauw samen met dit team. Slechte communicatie kost meer dan het bespaart. Zoek naar een leverancier die responsief is tijdens het verkoopproces, een duidelijk communicatieplan heeft voor het project en kan aantonen hoe ze klanten op de hoogte houden. Als ze moeilijk te bereiken zijn voor je tekent, zijn ze dat ook erna.&lt;/p&gt;
&lt;h3 id="fout-7-intellectuele-eigendomsrechten-niet-verduidelijken"&gt;Fout 7: Intellectuele-eigendomsrechten niet verduidelijken&lt;/h3&gt;
&lt;p&gt;In de meeste Nederlandse en Europese contracten is de opdrachtgever eigenaar van alles wat in het kader van een werk-voor-huur-overeenkomst wordt geproduceerd. Ga daar niet van uit. Leg het schriftelijk vast en bevestig dat de leverancier jouw code, architectuur of bedrijfslogica niet voor andere klanten mag hergebruiken.&lt;/p&gt;
&lt;h3 id="fout-8-de-ontwikkelingsmethodologie-niet-begrijpen"&gt;Fout 8: De ontwikkelingsmethodologie niet begrijpen&lt;/h3&gt;
&lt;p&gt;Vraag hoe de leverancier een project beheert van kickoff tot oplevering. Zie je regelmatig werkende software, of is er een lange stille periode gevolgd door een oplevering? Wij laten klanten aan het einde van elke sprint van twee weken werkende software zien, zodat er geen verrassingen zijn. Als een leverancier zijn proces niet duidelijk kan uitleggen, is dat een waarschuwingssignaal.&lt;/p&gt;
&lt;h3 id="fout-9-geen-duidelijk-contract-tekenen"&gt;Fout 9: Geen duidelijk contract tekenen&lt;/h3&gt;
&lt;p&gt;Een gedetailleerd contract beschermt beide partijen. Het moet scope, betalingsvoorwaarden, wijzigingsbeheer, intellectueel eigendom, aansprakelijkheid, vertrouwelijkheid, geschillenbeslechting en post-launch ondersteuning omvatten. Als een van deze onderwerpen vaag is in het contract dat je bekijkt, vraag dan om verduidelijking voor je tekent. Ons artikel over &lt;a href="https://volaresoftware.com/nl/articles/ten-disasters-to-avoid-in-your-next-custom-software-development-contract"&gt;tien rampen om te vermijden in je volgende contract voor softwareontwikkeling op maat&lt;/a&gt; beschrijft in detail waar je op moet letten.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact met ons op&lt;/a&gt; om jouw project te bespreken, of lees meer over onze &lt;a href="https://volaresoftware.com/nl/services/custom-software-development"&gt;softwareontwikkeling op maat&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Sun, 02 Apr 2023 18:24:49 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/what-does-custom-software-development-cost</guid>
      <link>https://volaresoftware.com/nl/articles/what-does-custom-software-development-cost</link>
      <title>Wat kost softwareontwikkeling op maat?</title>
      <description>&lt;h3 id="overweeg-je-maatwerk-software-te-laten-ontwikkelen"&gt;Overweeg je maatwerk software te laten ontwikkelen?&lt;/h3&gt;
&lt;p&gt;Wil je een idee van de kosten voordat je een kennismakingsgesprek plant? In dit artikel leggen we uit hoe maatwerk software geprijsd wordt, welke factoren de kosten bepalen en wat je bij verschillende projectgroottes kunt verwachten.&lt;/p&gt;
&lt;h3 id="hoeveel-kost-softwareontwikkeling-op-maat"&gt;Hoeveel kost softwareontwikkeling op maat?&lt;/h3&gt;
&lt;p&gt;De kosten van maatwerk software hangen af van teamgrootte, projectduur en complexiteit. Op basis van onze ervaring sinds 2009 hanteren we de volgende indicaties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Kleine projecten, zoals MVP's, kleine DevOps-trajecten of cloudmigraties, starten vanaf €25.000 voor één fulltime ontwikkelaar gedurende één tot twee maanden.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Middelgrote projecten, zoals webapplicaties met meerdere modules, API-integraties of databaseplatforms, lopen van €50.000 tot €200.000 en duren doorgaans drie tot zes maanden met één of twee ontwikkelaars.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grote enterprise-projecten met meerdere systemen, complexe integraties of regelgevingsvereisten kunnen meer dan €250.000 kosten en lopen van zes maanden tot meerdere jaren met teams van drie tot vijf ontwikkelaars.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="wat-bepaalt-de-kosten"&gt;Wat bepaalt de kosten?&lt;/h3&gt;
&lt;p&gt;De grootste kostenfactoren zijn teamgrootte en projectduur. Daarnaast verhogen de volgende zaken de complexiteit en daarmee de kosten:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Koppelingen met externe systemen. Elke API-verbinding met een extern systeem, of het nu gaat om een betaalverwerker, een ERP of een overheidsgegevensbron, vergroot de scope en het testoppervlak.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Betrokkenheid van bestaande systemen. Migreren of integreren met een bestaand systeem zonder goede documentatie of met inconsistente data kost aanzienlijk meer tijd dan nieuwbouw.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wet- en regelgeving. Projecten in de zorg, financiële sector, defensie of overheid brengen compliance-overhead mee die invloed heeft op de architectuur, het testen en de documentatie.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prestaties en schaalbaarheid. Een systeem dat duizenden transacties per minuut moet verwerken, vraagt een andere architectuur dan een systeem dat er tientallen verwerkt.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complexiteit van de gebruikerservaring. Een consumentgerichte applicatie met een verzorgde interface en mobiele optimalisatie kost meer tijd dan een intern systeem voor getraind personeel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="wat-is-er-inbegrepen-in-het-maandtarief"&gt;Wat is er inbegrepen in het maandtarief?&lt;/h3&gt;
&lt;p&gt;Bij Volare Software omvat ons maandtarief ontwikkeling, codereview, geautomatiseerd testen, deployment en projectcommunicatie. We brengen geen aparte kosten in rekening voor sprintplanning, architectuurbeslissingen of voortgangsrapportages. Je betaalt voor een team en dat team levert werkende software.&lt;/p&gt;
&lt;h3 id="waarom-we-geen-vaste-prijscontracten-aanbieden"&gt;Waarom we geen vaste prijscontracten aanbieden&lt;/h3&gt;
&lt;p&gt;Vaste prijscontracten vereisen dat alle eisen vooraf bekend en gedocumenteerd zijn. In de praktijk veranderen de eisen bij elk project, vaak ingrijpend. Een vast prijscontract plaatst je leverancier in de positie dat hij moet betogen dat jouw nieuwe wens niet in de oorspronkelijke specificaties stond. Dat is slecht voor het project en slecht voor de samenwerking.&lt;/p&gt;
&lt;p&gt;Wij werken liever met transparante time-and-materialsovereenkomsten waarbij we het maandelijkse teamtarief vastleggen en een bandbreedte voor de totale doorlooptijd opgeven. Jij bepaalt hoeveel scope je oppakt en kunt het team op elk moment aanpassen of het traject pauzeren.&lt;/p&gt;
&lt;h3 id="de-belangrijkste-software-eerst-opleveren"&gt;De belangrijkste software eerst opleveren&lt;/h3&gt;
&lt;p&gt;We werken met een agile ontwikkelproces waarbij de modules met de hoogste bedrijfswaarde als eerste worden gebouwd. Zo beschik je vroeg in het traject over werkende, inzetbare software, wat het risico vermindert en je in staat stelt het product te valideren bij echte gebruikers voordat het project is afgerond.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem vandaag nog contact met ons op&lt;/a&gt; voor meer informatie over onze &lt;a href="https://volaresoftware.com/nl/services/custom-software-development"&gt;softwareontwikkeling op maat&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Mon, 06 Aug 2018 06:00:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/unlocking-the-power-of-custom-software-is-it-worth-the-investment</guid>
      <link>https://volaresoftware.com/nl/articles/unlocking-the-power-of-custom-software-is-it-worth-the-investment</link>
      <title>De kracht van aangepaste software ontsluiten: is het de investering waard?</title>
      <description>&lt;h3 id="is-softwareontwikkeling-op-maat-de-investering-waard"&gt;Is softwareontwikkeling op maat de investering waard?&lt;/h3&gt;
&lt;p&gt;Maatwerk software kost meer vooraf dan kant-en-klare alternatieven. Voor veel organisaties is die kostprijs gerechtvaardigd. Voor andere niet. Dit artikel legt uit wanneer softwareontwikkeling op maat een sterk rendement op investering oplevert en wanneer niet.&lt;/p&gt;
&lt;h3 id="wanneer-maatwerk-software-financieel-zinvol-is"&gt;Wanneer maatwerk software financieel zinvol is&lt;/h3&gt;
&lt;p&gt;Maatwerk software is de investering waard wanneer een of meer van de volgende voorwaarden van toepassing zijn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Jouw proces is een concurrentievoordeel. Als de manier waarop je opereert jou onderscheidt van concurrenten, beschermt software die rond dat proces is gebouwd dat voordeel. Standaard software dwingt je te werken zoals jouw leverancier het heeft ontworpen, wat betekent dat je op dezelfde manier werkt als elk ander bedrijf dat dat product gebruikt.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Je betaalt voor functies die je niet gebruikt. Enterprise SaaS-producten rekenen voor mogelijkheden die zijn gebouwd voor de breedst mogelijke markt. Als je 20% van een platform gebruikt en voor 100% betaalt, verbeteren de economische voordelen van maatwerk software aanzienlijk over een horizon van drie tot vijf jaar.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Je hebt een integratieprobleem. Veel organisaties draaien op een combinatie van systemen die niet met elkaar communiceren. Maatwerk software, of een aangepaste API-laag, kan die systemen verbinden en het handmatige werk van het verplaatsen van gegevens ertussen elimineren.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Je bent je huidige systeem ontgroeid. Systemen die zijn gebouwd voor een kleinere versie van jouw bedrijf worden uiteindelijk beperkingen. Maatwerk software kan worden ontworpen om mee te groeien met jouw groei in plaats van elke paar jaar een migratie te forceren.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="wanneer-kant-en-klare-software-de-betere-keuze-is"&gt;Wanneer kant-en-klare software de betere keuze is&lt;/h3&gt;
&lt;p&gt;Maatwerk software is niet altijd het juiste antwoord. Als jouw behoeften goed worden bediend door een bestaand product, is kopen sneller en goedkoper dan bouwen. We zullen je dat rechtstreeks vertellen als dat van toepassing is op jouw situatie. We hebben het eerder gedaan.&lt;/p&gt;
&lt;p&gt;Het duidelijkste signaal dat kant-en-klare software de juiste keuze is, is wanneer jouw proces overeenkomt met wat het product doet. Als je boekhoudsoftware nodig hebt, koop dan boekhoudsoftware. De markt voor algemene bedrijfstools is volwassen en concurrerend.&lt;/p&gt;
&lt;h3 id="hoe-je-over-de-kosten-moet-nadenken"&gt;Hoe je over de kosten moet nadenken&lt;/h3&gt;
&lt;p&gt;De initiële kosten van maatwerk software zijn reëel. Dat geldt ook voor de doorlopende kosten van een systeem dat niet past, van handmatige oplossingen, van gegevens die op drie verschillende plaatsen staan en van een concurrerend proces dat iedereen kan repliceren door hetzelfde product te kopen dat jij gebruikt.&lt;/p&gt;
&lt;p&gt;De juiste vergelijking is niet maatwerk software versus de licentiekosten van een kant-en-klaar product. Het is maatwerk software versus de totale kosten van het alternatief, inclusief implementatie, aanpassing, integratiewerk, training en de kosten van de beperkingen die je accepteert.&lt;/p&gt;
&lt;h3 id="wat-je-van-volare-software-kunt-verwachten"&gt;Wat je van Volare Software kunt verwachten&lt;/h3&gt;
&lt;p&gt;We werken op trajecten van 3 tot 12 maanden met teams van één tot vijf ontwikkelaars. We geven je een schatting als bandbreedte na een kennismakingsgesprek en we committeren ons aan de maandelijkse teamkosten. Je kunt het team op- of afschalen en je kunt het traject pauzeren als jouw prioriteiten veranderen.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact met ons op&lt;/a&gt; voor een vrijblijvend kennismakingsgesprek, of lees meer over onze &lt;a href="https://volaresoftware.com/nl/services/custom-software-development"&gt;softwareontwikkeling op maat&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Tue, 08 Aug 2023 17:49:16 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/advantages-of-hiring-a-business-driven-custom-software-consultancy</guid>
      <link>https://volaresoftware.com/nl/articles/advantages-of-hiring-a-business-driven-custom-software-consultancy</link>
      <title>Voordelen van het inhuren van een bedrijfsgericht softwareadviesbureau op maat</title>
      <description>&lt;h3 id="wat-maakt-een-consultancybureau-voor-maatwerk-software-effectief"&gt;Wat maakt een consultancybureau voor maatwerk software effectief?&lt;/h3&gt;
&lt;p&gt;Technische vaardigheid is belangrijk bij de ontwikkeling van maatwerk software, maar het is niet genoeg op zichzelf. De bureaus die de meeste waarde leveren, zijn de bureaus die jouw bedrijf net zo goed begrijpen als de codebase. Dit artikel beschrijft waarom bedrijfsinzicht de belangrijkste factor is bij het kiezen van een partner voor softwareontwikkeling op maat.&lt;/p&gt;
&lt;h3 id="software-die-past-bij-jouw-bedrijf-niet-andersom"&gt;Software die past bij jouw bedrijf, niet andersom&lt;/h3&gt;
&lt;p&gt;Standaard software is gebouwd voor de algemene markt. Maatwerk software is gebouwd voor jouw specifieke processen, concurrentievoordelen en integratiebehoeften. Maar zelfs maatwerk software kan tekortschieten als het team dat het bouwt niet de tijd neemt om te begrijpen hoe jouw bedrijf daadwerkelijk werkt.&lt;/p&gt;
&lt;p&gt;Een businessgericht consultancybureau begint met de vraag waarom voordat het vraagt hoe. Welk probleem los je op? Hoe ziet succes eruit zes maanden na de lancering? Wie zijn de mensen die dit systeem dagelijks gebruiken? De antwoorden op die vragen bepalen elke architectuurbeslissing, elke functieprioriteit en elke afweging die tijdens het project wordt gemaakt.&lt;/p&gt;
&lt;h3 id="domeinervaring-vermindert-risico"&gt;Domeinervaring vermindert risico&lt;/h3&gt;
&lt;p&gt;Een consultancybureau dat ervaring heeft in jouw branche of met vergelijkbare vraagstukken, brengt patroonherkenning mee die een puur technisch team niet heeft. Ze weten welke integraties lastig zijn, welke compliancevereisten invloed hebben op het datamodel en welke functies eenvoudig lijken maar dat niet zijn. Die ervaring verkort de ontdekkingsfase, vermindert het aantal kostbare late wijzigingen en levert software op die werkt zoals jouw bedrijf werkt.&lt;/p&gt;
&lt;h3 id="zakelijke-afstemming-gedurende-het-hele-project-niet-alleen-bij-de-start"&gt;Zakelijke afstemming gedurende het hele project, niet alleen bij de start&lt;/h3&gt;
&lt;p&gt;Vereisten veranderen bij elk project. Een businessgericht consultancybureau behandelt dat niet als een probleem dat via contracttaal beheerd moet worden. Ze behandelen het als normaal en bouwen daar een proces omheen. Bij Volare Software gebruiken we agile ontwikkeling met korte iteraties, zodat nieuwe informatie en veranderende prioriteiten kunnen worden verwerkt zonder de planning of het budget te verstoren.&lt;/p&gt;
&lt;h3 id="lange-termijn-denken-boven-kortetermijnoplevering"&gt;Lange termijn denken boven kortetermijnoplevering&lt;/h3&gt;
&lt;p&gt;Een consultancybureau dat jouw bedrijf begrijpt, denkt na over wat er gebeurt nadat het project is afgerond. Is de software onderhoudbaar? Kan jouw interne team het overnemen? Is de architectuur flexibel genoeg om mee te groeien met jouw bedrijf? Dit zijn geen bijzaken. Het zijn ontwerpbeslissingen die op dag één worden genomen.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact met ons op&lt;/a&gt; om jouw project te bespreken met een consultancybureau dat sinds 2009 business-gedreven enterprise software bouwt.&lt;/p&gt;
</description>
      <pubDate>Sun, 28 Apr 2024 19:49:26 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/how-we-do-agile-software-development</guid>
      <link>https://volaresoftware.com/nl/articles/how-we-do-agile-software-development</link>
      <title>Hoe we agile software ontwikkelen</title>
      <description>&lt;h3 id="hoe-wij-agile-software-ontwikkelen"&gt;Hoe wij agile software ontwikkelen&lt;/h3&gt;
&lt;p&gt;We volgen een agile softwareontwikkelingsproces dat in meer dan 17 jaar van het opleveren van enterprise-projecten is verfijnd. Dit artikel beschrijft hoe wij werken, van initiële planning tot productie-deployment.&lt;/p&gt;
&lt;h3 id="stories-en-bugfixes"&gt;Stories en bugfixes&lt;/h3&gt;
&lt;p&gt;Het bedrijf, meestal via één productmanager, is primair verantwoordelijk voor het schrijven van nieuwe stories. De inhoud moet voldoende zijn voor de auteur om later te herinneren waar het over ging wanneer om details wordt gevraagd. Zodra een story in de werkcyclus aan de beurt komt, werkt het team met de relevante stakeholders om vragen te stellen, concrete voorbeelden uit te werken en indien nodig een ontwerp te maken. Deze gesprekken verduidelijken de reden voor de functie en vormen een sterke motivatie voor het team.&lt;/p&gt;
&lt;h3 id="prioritering"&gt;Prioritering&lt;/h3&gt;
&lt;p&gt;De productmanager beheert de backlog en stelt prioriteiten. Het team levert schattingen van de inspanning om die beslissingen te ondersteunen, maar de productmanager bepaalt wat er als volgende wordt gebouwd. Dit houdt het team gefocust op bedrijfswaarde in plaats van technische voorkeur.&lt;/p&gt;
&lt;h3 id="iteraties"&gt;Iteraties&lt;/h3&gt;
&lt;p&gt;We werken in sprints van twee weken. Aan het begin van elke sprint bekijkt het team de bovenste items in de backlog, bevestigt de scope en committeert zich aan een set stories voor die iteratie. Aan het einde van elke sprint demonstreren we werkende software aan stakeholders. Er zijn geen verrassingen aan het einde van een lang project, omdat stakeholders elke twee weken voortgang zien.&lt;/p&gt;
&lt;h3 id="werk-bijhouden"&gt;Werk bijhouden&lt;/h3&gt;
&lt;p&gt;We gebruiken een Kanban-stijl bord om stories door hun fases te volgen: gereed, in uitvoering, in review, klaar. Stories worden pas als klaar gemarkeerd nadat ze codereview en geautomatiseerd testen hebben doorstaan. Dit houdt de definitie van klaar consistent en voorkomt dat halfafgemaakt werk zich opstapelt.&lt;/p&gt;
&lt;h3 id="codereview"&gt;Codereview&lt;/h3&gt;
&lt;p&gt;Elke wijziging gaat door peer codereview voordat deze wordt samengevoegd. Codereview gaat niet alleen over het opsporen van bugs, hoewel het dat ook doet. Het gaat om kennisdeling, het handhaven van consistentie in de codebase en het vroegtijdig opsporen van ontwerpproblemen voordat ze kostbaar zijn om op te lossen.&lt;/p&gt;
&lt;h3 id="geautomatiseerd-testen"&gt;Geautomatiseerd testen&lt;/h3&gt;
&lt;p&gt;We schrijven geautomatiseerde tests voor bedrijfslogica en integratiepunten. Het doel is niet 100% dekking om de dekking zelf. Het doel is een testset die het team het vertrouwen geeft om snel wijzigingen aan te brengen zonder bestaand gedrag te breken.&lt;/p&gt;
&lt;h3 id="deployment"&gt;Deployment&lt;/h3&gt;
&lt;p&gt;We gebruiken CI-CD-pipelines zodat elke samenvoeging naar de hoofdbranch een geautomatiseerde build en deployment naar de ontwikkelomgeving activeert. Releases naar productie zijn een bewuste beslissing, geen handmatig proces. Dit vermindert het deploymentrisico en houdt omgevingen consistent.&lt;/p&gt;
&lt;h3 id="wat-dit-voor-jou-betekent"&gt;Wat dit voor jou betekent&lt;/h3&gt;
&lt;p&gt;Je ziet aan het einde van elke sprint van twee weken werkende software. Je kunt prioriteiten wijzigen tussen sprints. Je weet precies wat er is opgeleverd en wat het heeft gekost. Er zijn geen lange periodes van stilte gevolgd door een grote onthulling.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact met ons op&lt;/a&gt; voor meer informatie over hoe wij werken, of bekijk onze &lt;a href="https://volaresoftware.com/nl/services/agile-devops-automations"&gt;agile DevOps automatiseringen service&lt;/a&gt; voor hoe we deze werkwijzen toepassen op DevOps en pipeline-werk.&lt;/p&gt;
</description>
      <pubDate>Sat, 12 Aug 2023 11:43:25 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/ten-disasters-to-avoid-in-your-next-custom-software-development-contract</guid>
      <link>https://volaresoftware.com/nl/articles/ten-disasters-to-avoid-in-your-next-custom-software-development-contract</link>
      <title>Tien rampen om te vermijden in uw volgende contract voor softwareontwikkeling op maat</title>
      <description>&lt;h3 id="wat-het-contract-goed-moet-regelen"&gt;Wat het contract goed moet regelen&lt;/h3&gt;
&lt;p&gt;Een contract voor softwareontwikkeling op maat is niet zomaar papierwerk. Het bepaalt wie wat bezit, wie waarvoor verantwoordelijk is en wat er gebeurt als het misgaat. We hebben genoeg projecten meegemaakt om te weten dat een slecht opgesteld contract problemen veroorzaakt die geen enkele goede wil kan oplossen. Hier zijn tien dingen die je voor ondertekening goed moet regelen.&lt;/p&gt;
&lt;h3 id="geen-opzeggingsclausule"&gt;1. Geen opzeggingsclausule&lt;/h3&gt;
&lt;p&gt;Als de leverancier niet levert, kun je dan het contract beëindigen? Zonder een duidelijke opzeggingsclausule heb je daar mogelijk geen juridische grond voor. Zorg dat je contract je de mogelijkheid geeft om de samenwerking te beëindigen als je niet tevreden bent, en wees specifiek over welke omstandigheden dat recht activeren.&lt;/p&gt;
&lt;h3 id="onduidelijke-scope-en-geen-gedefinieerd-proces"&gt;2. Onduidelijke scope en geen gedefinieerd proces&lt;/h3&gt;
&lt;p&gt;Scopedocumenten zijn op zichzelf niet voldoende. De leverancier zal jouw vereisten anders interpreteren dan jij bedoelde, en zonder een gedefinieerd ontwikkelingsproces is er geen mechanisme om dat vroeg te ontdekken. Je contract moet specificeren hoe werk wordt opgesplitst in iteraties, hoe je de voortgang beoordeelt en hoe wijzigingen worden verwerkt. Een proces dat je elke twee weken werkende software laat zien, biedt veel meer bescherming dan een gedetailleerd specificatiedocument.&lt;/p&gt;
&lt;h3 id="vage-betalingsvoorwaarden"&gt;3. Vage betalingsvoorwaarden&lt;/h3&gt;
&lt;p&gt;Duidelijke betalingsvoorwaarden beschermen beide partijen. Vage voorwaarden leiden tot geschillen over wanneer betaling verschuldigd is, wat een voltooide mijlpaal inhoudt en wat er gebeurt als een van beide partijen te laat is. Leg dit voor de start van het project concreet vast.&lt;/p&gt;
&lt;h3 id="geen-intellectuele-eigendomsclausule"&gt;4. Geen intellectuele-eigendomsclausule&lt;/h3&gt;
&lt;p&gt;Wie is eigenaar van de code? In de meeste Nederlandse en Europese contracten is de opdrachtgever eigenaar van alles wat in het kader van een werk-voor-huur-overeenkomst wordt geproduceerd. Ga daar niet van uit. Leg het schriftelijk vast. Specificeer ook dat de leverancier jouw code niet opnieuw mag gebruiken voor andere klanten.&lt;/p&gt;
&lt;h3 id="geen-aansprakelijkheidsclausule"&gt;5. Geen aansprakelijkheidsclausule&lt;/h3&gt;
&lt;p&gt;Als de leverancier gebrekkige code levert die schade veroorzaakt aan jouw bedrijf of klanten, is hij dan aansprakelijk? Leveranciers willen hun aansprakelijkheid beperken, vaak tot de waarde van het contract. Zorg dat een eventueel aansprakelijkheidsplafond hoog genoeg is om jouw daadwerkelijke risicoBlootstelling te dekken.&lt;/p&gt;
&lt;h3 id="geen-geheimhoudingsovereenkomst"&gt;6. Geen geheimhoudingsovereenkomst&lt;/h3&gt;
&lt;p&gt;Je leverancier heeft toegang tot jouw processen, jouw gegevens en soms de informatie van jouw klanten. Een geheimhoudingsovereenkomst moet doorlopen na het einde van het project, doorgaans ten minste een jaar, en moet alle teamleden aan de kant van de leverancier omvatten.&lt;/p&gt;
&lt;h3 id="geen-geschillenbeslechtingsmechanisme"&gt;7. Geen geschillenbeslechtingsmechanisme&lt;/h3&gt;
&lt;p&gt;Als er een geschil ontstaat, is naar de rechter stappen langzaam en duur. Leg in het contract vast hoe geschillen worden opgelost, of via bindende arbitrage, mediation of een ander mechanisme. Dit is veel eenvoudiger overeen te komen voor een geschil dan erna.&lt;/p&gt;
&lt;h3 id="geen-non-solicitatieclausule"&gt;8. Geen non-solicitatieclausule&lt;/h3&gt;
&lt;p&gt;Wat gebeurt er als de leverancier jouw medewerkers wegkaapt, of jij die van hen? Een non-solicitatieclausule legt de regels voor beide partijen vast en vermindert het risico op ongemakkelijke situaties tijdens of na het project.&lt;/p&gt;
&lt;h3 id="geen-belangenconflictclausule"&gt;9. Geen belangenconflictclausule&lt;/h3&gt;
&lt;p&gt;Werkt de leverancier aan hetzelfde vraagstuk voor een van jouw concurrenten? Een belangenconflictclausule verplicht hen dit te melden en geeft je verhaal als het zonder melding gebeurt.&lt;/p&gt;
&lt;h3 id="geen-ondersteuningsovereenkomst"&gt;10. Geen ondersteuningsovereenkomst&lt;/h3&gt;
&lt;p&gt;Het project is klaar en de software draait in productie. Er duikt een bug op. Wie lost dat op? Leg de verantwoordelijkheden van de leverancier na de livegang vast voor je tekent, niet erna. Bepaal of je een doorlopende ondersteuningsovereenkomst wilt, een garantieperiode of een overdracht aan je interne team, en leg dat vast.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact met ons op&lt;/a&gt; voor meer informatie over hoe we onze &lt;a href="https://volaresoftware.com/nl/services/custom-software-development"&gt;softwareontwikkeling op maat&lt;/a&gt; trajecten structureren.&lt;/p&gt;
</description>
      <pubDate>Sun, 02 Apr 2023 20:39:06 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/should-you-go-with-an-offshore-team-for-your-custom-software-development-project</guid>
      <link>https://volaresoftware.com/nl/articles/should-you-go-with-an-offshore-team-for-your-custom-software-development-project</link>
      <title>Moet je met een offshore team in zee gaan voor je softwareontwikkelingsproject op maat?</title>
      <description>&lt;h3 id="offshore-nearshore-of-lokaal-wat-telt-er-echt-voor-jouw-project"&gt;Offshore, nearshore of lokaal: wat telt er echt voor jouw project&lt;/h3&gt;
&lt;p&gt;Kosten zijn meestal de eerste reden waarom bedrijven een offshore ontwikkelteam overwegen. Tarieven in India, Oost-Europa of Zuidoost-Azië zien er op papier aantrekkelijk uit vergeleken met Nederlandse of West-Europese tarieven. Maar de totale kosten van een softwareproject zijn niet alleen het uurtarief. Ze omvatten ook de kosten van miscommunicatie, herwerk, management-overhead en vertraagde oplevering. Dit artikel beschrijft wat je moet afwegen bij deze beslissing.&lt;/p&gt;
&lt;h3 id="de-werkelijke-kosten-van-offshore-ontwikkeling"&gt;De werkelijke kosten van offshore ontwikkeling&lt;/h3&gt;
&lt;p&gt;Offshore teams rekenen doorgaans minder per uur. Dat voordeel neemt af als je de volgende factoren meeneemt:&lt;/p&gt;
&lt;p&gt;Tijdzoneverschillen. Een verschil van 5 tot 8 uur tussen een Nederlandse klant en een offshore team betekent dat een vraag die je aan het einde van jouw dag stelt, pas aan het begin van de volgende dag wordt beantwoord. Op een complex project telt die dagelijkse vertraging bij elke uitwisseling snel op.&lt;/p&gt;
&lt;p&gt;Communicatie-overhead. Specificaties helder genoeg opschrijven voor een team met een andere culturele en taalkundige context dan die van jou, kost meer tijd en zorgvuldigheid dan de meeste klanten verwachten. Misverstanden die in een gesprek van vijf minuten opgelost zouden worden, kunnen uitlopen op omwegen van een week.&lt;/p&gt;
&lt;p&gt;Managementvereisten. Offshore trajecten vereisen doorgaans meer actief projectmanagement aan de kant van de klant. Als je geen toegewijde interne persoon hebt om de relatie te beheren, kunnen de besparingen verdwijnen in de tijd van je eigen team.&lt;/p&gt;
&lt;h3 id="wanneer-offshore-werkt"&gt;Wanneer offshore werkt&lt;/h3&gt;
&lt;p&gt;Offshore ontwikkeling werkt goed wanneer het werk duidelijk gedefinieerd, herhaalbaar is en weinig heen-en-weer communicatie vereist. Onderhoudstaken, goed gespecificeerde functie-toevoegingen en QA-werk zijn voorbeelden waarbij het tijdzoneverschil en de communicatie-overhead beheersbaar zijn.&lt;/p&gt;
&lt;p&gt;Het werkt minder goed voor projecten die ontdekking, evoluerende vereisten of nauwe samenwerking met zakelijke stakeholders vereisen. Die projecten profiteren van een team dat snel kan reageren en zonder wrijving kan communiceren.&lt;/p&gt;
&lt;h3 id="het-nearshore-alternatief"&gt;Het nearshore alternatief&lt;/h3&gt;
&lt;p&gt;Een nearshore team werkt in een vergelijkbare of overlappende tijdzone, deelt een vergelijkbare bedrijfscultuur en communiceert zonder taalbarrière. Voor Nederlandse en Europese klanten betekent dat Nederland en omliggende landen.&lt;/p&gt;
&lt;p&gt;Volare Software is gevestigd in Hilversum en bedient al sinds 2009 enterprise klanten in Nederland, Europa en de Verenigde Staten. Ons team werkt in CET, wat volledige overlap geeft met de werkdag in West-Europa. We werken in het Nederlands en Engels en passen hetzelfde agile proces toe op elk project, zodat je aan het einde van elke sprint van twee weken werkende software ziet.&lt;/p&gt;
&lt;p&gt;We zijn niet de goedkoopste optie. We zijn de optie die het risico vermindert dat het project mislukt of twee keer zo lang duurt als gepland.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact met ons op&lt;/a&gt; om jouw project te bespreken en te kijken of onze aanpak de juiste keuze is, of lees meer over onze &lt;a href="https://volaresoftware.com/nl/services/custom-software-development"&gt;softwareontwikkeling op maat&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Sun, 02 Apr 2023 18:25:24 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/the-importance-of-listening-to-users-during-the-design-process</guid>
      <link>https://volaresoftware.com/nl/articles/the-importance-of-listening-to-users-during-the-design-process</link>
      <title>Het belang van luisteren naar gebruikers tijdens het ontwerpproces</title>
      <description>&lt;h3 id="waarom-gebruikersfeedback-betere-software-oplevert"&gt;Waarom gebruikersfeedback betere software oplevert&lt;/h3&gt;
&lt;p&gt;Als we diep in een project zitten, is het makkelijk om vertrouwen te krijgen in onze eigen aannames over wat gebruikers nodig hebben. De producteigenaar heeft een duidelijke visie. De ontwikkelaars begrijpen de technische beperkingen. Maar geen van die perspectieven is hetzelfde als zitten met de mensen die de software dagelijks zullen gebruiken. Gebruikersfeedback tijdens het ontwerpproces is geen luxe. Het is een van de betrouwbaarste manieren om te voorkomen dat je het verkeerde bouwt.&lt;/p&gt;
&lt;h3 id="gebruikers-weten-dingen-die-jij-niet-weet"&gt;Gebruikers weten dingen die jij niet weet&lt;/h3&gt;
&lt;p&gt;De mensen die het werk doen dat jouw software ondersteunt, hebben context die niemand in het ontwikkelteam heeft. Ze weten welke delen van het huidige proces pijnlijk zijn, welke oplossingen ze zelf hebben bedacht en welke uitzonderlijke situaties elke week terugkomen. Die kennis verschijnt niet in een eisendocument tenzij iemand ernaar vraagt.&lt;/p&gt;
&lt;p&gt;Bij Volare Software behandelen we vroege gesprekken met gebruikers als onderdeel van het ontwerpproces, niet als een goedkeuringsstap aan het einde. Een gebruiker laten werken met een prototype of een vroege werkende iteratie en observeren wat hij doet, vertelt ons in een uur meer dan weken van specificaties schrijven.&lt;/p&gt;
&lt;h3 id="feedback-helpt-je-scope-te-verkleinen-niet-alleen-toe-te-voegen"&gt;Feedback helpt je scope te verkleinen, niet alleen toe te voegen&lt;/h3&gt;
&lt;p&gt;Een van de nuttigste dingen die gebruikersfeedback doet, is je vertellen wat je moet weglaten. De meeste softwareprojecten beginnen met meer functies dan ze nodig hebben. Gebruikers vertellen ons consistent welke delen van het voorgestelde ontwerp ze daadwerkelijk zouden gebruiken en welke delen goed klinken in een vergadering maar niet weerspiegelen hoe ze werken. Die informatie maakt de software kleiner, sneller te bouwen en gemakkelijker te gebruiken.&lt;/p&gt;
&lt;h3 id="niet-alle-feedback-is-bruikbaar-maar-alles-is-nuttig"&gt;Niet alle feedback is bruikbaar, maar alles is nuttig&lt;/h3&gt;
&lt;p&gt;Sommige gebruikersfeedback is duidelijk en direct. Sommige is tegenstrijdig. Sommige weerspiegelt wat een gebruiker vandaag wil in plaats van wat hij over zes maanden nodig heeft. Een deel van onze taak is feedback in context te interpreteren, af te wegen tegen de productdoelen en aanbevelingen terug te brengen naar de producteigenaar.&lt;/p&gt;
&lt;p&gt;We behandelen gebruikersfeedback niet als een stemsysteem waarbij het populairste verzoek wint. We behandelen het als gegevens die ontwerpbeslissingen ondersteunen, genomen door mensen die zowel de behoeften van de gebruiker als de technische beperkingen begrijpen.&lt;/p&gt;
&lt;h3 id="wanneer-gebruikers-te-betrekken"&gt;Wanneer gebruikers te betrekken&lt;/h3&gt;
&lt;p&gt;Hoe eerder hoe beter. Feedback op een schets of een eenvoudig prototype is goedkoop om op te handelen. Feedback op een afgewerkte functie is duur. We proberen een vorm van gebruikersinput te krijgen voordat grote ontwerpbeslissingen worden vastgelegd, en opnieuw nadat de eerste werkende iteratie beschikbaar is.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact met ons op&lt;/a&gt; voor meer informatie over onze aanpak van &lt;a href="https://volaresoftware.com/nl/services/web-app-development"&gt;web app ontwikkeling&lt;/a&gt; en gebruikersgerichte vormgeving.&lt;/p&gt;
</description>
      <pubDate>Sun, 02 Apr 2023 18:46:50 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/articles/five-essential-steps-to-ensure-your-web-app-is-secure</guid>
      <link>https://volaresoftware.com/nl/articles/five-essential-steps-to-ensure-your-web-app-is-secure</link>
      <title>Vijf stappen om ervoor te zorgen dat uw webapplicatie veilig is.</title>
      <description>&lt;h3 id="beveiliging-bouw-je-in-je-plakt-het-er-niet-achteraf-op"&gt;Beveiliging bouw je in, je plakt het er niet achteraf op&lt;/h3&gt;
&lt;p&gt;Beveiliging van web apps is geen eindchecklist voor de lancering. Tegen de tijd dat je pre-launch tests uitvoert, zijn de beslissingen die bepalen hoe veilig je applicatie is al genomen. De architectuur, het datamodel, de gekozen externe services, de manier waarop authenticatie werkt - dat alles lag maanden eerder vast. Dit artikel beschrijft vijf praktijken die we gedurende het hele ontwikkelproces toepassen om web apps veilig te houden.&lt;/p&gt;
&lt;h3 id="versleutel-al-het-verkeer"&gt;1. Versleutel al het verkeer&lt;/h3&gt;
&lt;p&gt;Elk verzoek tussen jouw gebruikers en jouw applicatie moet via HTTPS verlopen. Dit versleutelt gegevens onderweg en voorkomt dat ze kunnen worden gelezen als ze worden onderschept. SSL/TLS-certificaten zijn gratis beschikbaar via de meeste hostingproviders en cloudplatforms. Er is geen goede reden om productieverkeer via HTTP te laten lopen.&lt;/p&gt;
&lt;h3 id="versleutel-gevoelige-gegevens-in-opslag-en-sla-ze-niet-op-als-dat-niet-nodig-is"&gt;2. Versleutel gevoelige gegevens in opslag, en sla ze niet op als dat niet nodig is&lt;/h3&gt;
&lt;p&gt;Als je applicatie wachtwoorden opslaat, moeten ze worden gehasht met een modern algoritme zoals bcrypt of Argon2, nooit opgeslagen als leesbare tekst of met omkeerbare encryptie. Voor andere gevoelige gegevens zoals betalingsinformatie of identiteitsdocumenten, is de eerste vraag of je ze überhaupt hoeft op te slaan. Gegevens die je niet bewaart, kunnen niet worden gestolen. Als je ze wel moet opslaan, versleutel ze dan op veld- of rijniveau, niet alleen op schijfniveau.&lt;/p&gt;
&lt;h3 id="voer-beveiligingsscans-uit"&gt;3. Voer beveiligingsscans uit&lt;/h3&gt;
&lt;p&gt;Geautomatiseerde beveiligingsscanners testen je draaiende applicatie op veelvoorkomende kwetsbaarheden, waaronder injectie-aanvallen, gebrekkige authenticatie en blootgestelde gevoelige gegevens. Het regelmatig uitvoeren hiervan, en zeker voor elke grote release, ontdekt problemen die codereview alleen mist. Veel scanners zijn beschikbaar als onderdeel van een CI-CD-pipeline, zodat de scan automatisch bij elke build plaatsvindt.&lt;/p&gt;
&lt;h3 id="voer-statische-codeanalyse-uit"&gt;4. Voer statische codeanalyse uit&lt;/h3&gt;
&lt;p&gt;Statische analysetools onderzoeken je broncode zonder deze uit te voeren. Ze identificeren patronen die verband houden met bekende kwetsbaarheidsklassen: SQL-injectie, cross-site scripting, onveilige deserialisatie en andere. Het integreren van een statisch analysetools in je ontwikkelworkflow betekent dat deze controles bij elke commit plaatsvinden in plaats van als eenmalige oefening.&lt;/p&gt;
&lt;h3 id="controleer-je-beveiligingsheaders"&gt;5. Controleer je beveiligingsheaders&lt;/h3&gt;
&lt;p&gt;HTTP-beveiligingsheaders vertellen browsers hoe ze zich moeten gedragen bij het laden van jouw applicatie. De Content-Security-Policy header beperkt welke resources de browser laadt, wat het aanvalsoppervlak voor cross-site scripting verkleint. De Strict-Transport-Security header dwingt HTTPS af. X-Frame-Options voorkomt dat je pagina's worden ingebed in iframes op andere domeinen. Deze zijn eenvoudig te configureren en maken een meetbaar verschil in de beveiligingspositie van je applicatie.&lt;/p&gt;
&lt;p&gt;Beveiliging is een van de gebieden waar de kosten van het oplossen van problemen aanzienlijk toenemen naarmate de tijd verstrijkt. Problemen die tijdens de ontwikkeling worden ontdekt, zijn goedkoop op te lossen. Problemen die in productie worden ontdekt, zijn dat niet.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresoftware.com/nl/contact"&gt;Neem contact met ons op&lt;/a&gt; voor meer informatie over hoe we beveiliging inbouwen in ons &lt;a href="https://volaresoftware.com/nl/services/web-app-development"&gt;web app ontwikkeling&lt;/a&gt; proces.&lt;/p&gt;
</description>
      <pubDate>Tue, 18 Apr 2023 14:27:52 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/mocking-calls-with-jasmine</guid>
      <link>https://volaresoftware.com/nl/technical-posts/mocking-calls-with-jasmine</link>
      <title>Mocking calls with Jasmine</title>
      <description>&lt;p&gt;This post and the examples have been updated to the latest release of Jasmine, which is currently 3.5.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jasmine.github.io/"&gt;Jasmine&lt;/a&gt; is a simple, &lt;a href="https://en.wikipedia.org/wiki/Behavior-driven_development"&gt;BDD&lt;/a&gt;-style JavaScript testing framework, but to benefit from the full power out of the framework, you need to know how to mock calls the Jasmine way.&lt;/p&gt;
&lt;p&gt;Jasmine uses &lt;a href="https://jasmine.github.io/api/edge/global.html#spyOn"&gt;spies&lt;/a&gt; to mock asynchronous and synchronous function calls. As with most mocking frameworks, you can set the externally observed behavior of the code you are mocking.&lt;/p&gt;
&lt;h2 id="using-jasmine-spies-to-mock-code"&gt;Using Jasmine spies to mock code&lt;/h2&gt;
&lt;p&gt;Jasmine spies are easy to set up.  You set the object and function you want to spy on, and that code won't be executed.&lt;/p&gt;
&lt;p&gt;In the code below, we have a &lt;code&gt;MyApp&lt;/code&gt; module with a flag property and a &lt;code&gt;setFlag()&lt;/code&gt; function exposed.  We also have an instance of that module called &lt;code&gt;myApp&lt;/code&gt; in the test.  To spy on the &lt;code&gt;myApp.setFlag()&lt;/code&gt; function, we use:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;spyOn(myApp, &amp;quot;setFlag&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's a little strange that in Jasmine, you have to put the function you want to spy on in quotes, but that's the API.&lt;/p&gt;
&lt;p&gt;When you spy on a function like this, the original code is not executed.&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/z739u7LL/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;h2 id="returning-values-from-jasmine-spies"&gt;Returning values from Jasmine spies&lt;/h2&gt;
&lt;p&gt;Most of the time when setting up mocks, you want to set return values so you can test a specific code path. Again, this is easy to do with Jasmine.&lt;/p&gt;
&lt;p&gt;Here, I show setting the return value of a function so we can test specific branches in the code and skip over the real &lt;code&gt;getFlag()&lt;/code&gt; function, which is hard-coded to return false.&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/cvo1nps5/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;The key piece is intercepting the &lt;code&gt;getFlag()&lt;/code&gt; function with the spy and setting the value the substituted function returns:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;spyOn(myApp, &amp;quot;getFlag&amp;quot;).and.returnValue(true);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sometimes, setting a &lt;code&gt;returnValue&lt;/code&gt; isn't enough. If you need to replace the function you are mocking, you can use:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;spyOn(myApp, &amp;quot;useFlagForSomething&amp;quot;).and.callFake(function() {
    return &amp;quot;I'm replacing the real function with this&amp;quot;;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="using-jasmine-spies-to-verify-code-was-called"&gt;Using Jasmine spies to verify code was called&lt;/h2&gt;
&lt;p&gt;You can also call the original code with a spy. This may sound pointless (why set up a mock and then call the real code?) unless you think about interaction testing, where it's important to know that a function was or was not called.&lt;/p&gt;
&lt;p&gt;The syntax to call the original code but still spy on the function is:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;spyOn(myApp, &amp;quot;getFlag&amp;quot;).and.callThrough();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code below shows how you can verify a spied on function was called. We have a new function called &lt;code&gt;reallyImportantProcess()&lt;/code&gt;.  We have to test to make sure it's being run under the right conditions, and we know it should run when &lt;code&gt;getFlag()&lt;/code&gt; returns &lt;code&gt;false&lt;/code&gt;, which is the default value. So we don't need to mock or change &lt;code&gt;getFalse()&lt;/code&gt; to take this code branch, but we do need to &lt;code&gt;spyOn reallyImportantProcess()&lt;/code&gt; to verify it gets called.&lt;/p&gt;
&lt;p&gt;In this spy, we have lots of options. We could skip calling the real code, as we do below, or we could set up specific return values or substitute our own function for that function, or we could call the original code with &lt;code&gt;callThrough()&lt;/code&gt;. When you set up Jasmine spies, you can use any spy configuration and still see if it was called later with and &lt;code&gt;toHaveBeenCalled()&lt;/code&gt;.&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/Lucxt850/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;You can also test that a spied on function was NOT called with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;expect(myApp.reallyImportantProcess).not.toHaveBeenCalled();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or you can go further with your interaction testing to assert on the spied on function being called with specific arguments like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;expect(myApp.reallyImportantProcess).toHaveBeenCalledWith(123, &amp;quot;abc&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="testing-async-calls-in-jasmine-with-jquerys-deferred-and-helpers"&gt;Testing async calls in Jasmine with jQuery's Deferred and helpers&lt;/h2&gt;
&lt;p&gt;Async calls are a big part of JavaScript.  Most code dealing with async calls these day works through promises or callbacks.&lt;/p&gt;
&lt;p&gt;Here, some test helper code can be used to mock promises being returned from an async call. I'm using &lt;a href="https://api.jquery.com/category/deferred-object/"&gt;jQuery's $.Deferred() object&lt;/a&gt;, but any promise framework should work the same.&lt;/p&gt;
&lt;p&gt;You can mock an async success or failure, pass in anything you want the mocked async call to return, and test how your code handles it:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;var JasmineHelpers = function () {
&lt;pre&gt;&lt;code&gt;var deferredSuccess = function (args) {
    var d = $.Deferred();
    d.resolve(args);
    return d.promise();
};

var deferredFailure = function (args) {
    var d = $.Deferred();
    d.reject(args);
    return d.promise();
};

return {
    deferredSuccess: deferredSuccess,
    deferredFailure: deferredFailure
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;};
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is some Jasmine spy code using these async helpers. Again, we use jQuery &lt;code&gt;$.Deferred()&lt;/code&gt; object to set up a function that calls out to a pretend async call named &lt;code&gt;testAsync()&lt;/code&gt;.  It's invoked by &lt;code&gt;callSomethingThatUsesAsync()&lt;/code&gt;, which is the function we're testing.  We want to mock the &lt;code&gt;testAsync()&lt;/code&gt; call (maybe it goes off to the database and takes a while), and we want to assert that when that &lt;code&gt;testAsync()&lt;/code&gt; call succeeds, &lt;code&gt;callSomethingThatUsesAsync()&lt;/code&gt; goes on to give us a text message saying it succeeded.&lt;/p&gt;
&lt;p&gt;Since the function under test is using a promise, we need to wait until the promise has completed before we can start asserting, but we want to assert whether it fails or succeeds, so we'll put our assert code in the &lt;code&gt;always()&lt;/code&gt; function.  The &lt;code&gt;done()&lt;/code&gt;, &lt;code&gt;fail()&lt;/code&gt;, and &lt;code&gt;always()&lt;/code&gt; functions are promise code - (actually, jQuery &lt;code&gt;$.Deferred&lt;/code&gt; code if you want to be technical) they are not specific to Jasmine.&lt;/p&gt;
&lt;h2 id="testing-async-calls-in-jasmine-with-jasmines-done-callback"&gt;Testing async calls in Jasmine with Jasmine's done() callback&lt;/h2&gt;
&lt;p&gt;Testing synchronous specs is easy, but asynchronous testing requires some additional work.&lt;/p&gt;
&lt;p&gt;For example, the code below fails because Jasmine evaluates the &lt;code&gt;expect()&lt;/code&gt; piece before the &lt;code&gt;testAsync()&lt;/code&gt; function has finished its work.  The &lt;code&gt;setTimeout()&lt;/code&gt; call forces a two second delay, but Jasmine has already moved on and failed the test before the &lt;code&gt;setTimeout()&lt;/code&gt; completes:&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/yt13dnrt/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;With Jasmine async testing, we have to call the async code in the &lt;code&gt;beforeEach()&lt;/code&gt; function that runs before each &lt;code&gt;it()&lt;/code&gt; function block within a &lt;code&gt;describe()&lt;/code&gt; function block.&lt;/p&gt;
&lt;p&gt;We also have to let Jasmine know when the async function has completed by calling the special &lt;code&gt;done()&lt;/code&gt; callback function Jasmine provides. Here, we are passing this special &lt;code&gt;done()&lt;/code&gt; callback around so our code under test can invoke it.&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/5bcr0uro/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;This works, but changing the code under test to accept the &lt;code&gt;done()&lt;/code&gt; callback argument and invoke it may not be realistic. Why would you change your code under test just to make the testing framework happy?&lt;/p&gt;
&lt;p&gt;Instead, you can use promises and call the special Jasmine &lt;code&gt;done()&lt;/code&gt; callback when your promise has resolved. Note that the Jasmine &lt;code&gt;done()&lt;/code&gt; callback is NOT the same as the promise's &lt;code&gt;done()&lt;/code&gt; callback. They just use the same function name.&lt;/p&gt;
&lt;p&gt;Here, I'm using &lt;a href="https://api.jquery.com/category/deferred-object/"&gt;jQuery's $.Deferred() object&lt;/a&gt; for the promises, but this approach should work with any promises library.&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/yf8Lnfma/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;You can even use the data returned from the promise in the test once it is resolved. Here we are passing the return value in the &lt;code&gt;deferred.resolve()&lt;/code&gt; call:&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/b5vft6xy/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;But of course, real-world applications can't get away with simply testing with &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;true&lt;/code&gt;/&lt;code&gt;false&lt;/code&gt; flags, so here is a more real-world example.&lt;/p&gt;
&lt;p&gt;It calls &lt;code&gt;$.getJSON()&lt;/code&gt; to go fetch some public JSON data in the &lt;code&gt;beforeEach()&lt;/code&gt; function, and then tests the returned JSON in the &lt;code&gt;it()&lt;/code&gt; block to make sure it isn't an empty object or undefined.&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/k45Lypwo/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;h2 id="testing-async-calls-in-jasmine-with-asyncawait"&gt;Testing async calls in Jasmine with async/await&lt;/h2&gt;
&lt;p&gt;With version 2.8 and later of Jasmine and your compiler that supports async/await (e.g., Babel, TypeScript), you can change this to be more readable:&lt;/p&gt;
&lt;iframe width="100%" height="500" src="https://jsfiddle.net/joewilson0/k1wyby9m/embedded/js,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;p&gt;Much cleaner!&lt;/p&gt;
</description>
      <pubDate>Tue, 14 Apr 2020 06:00:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/autocomplete-dropdown-with-jquery-ui-and-mvc</guid>
      <link>https://volaresoftware.com/nl/technical-posts/autocomplete-dropdown-with-jquery-ui-and-mvc</link>
      <title>Autocomplete dropdown with jQuery UI and MVC</title>
      <description>&lt;p&gt;You know the &lt;a href="http://jqueryui.com/demos/autocomplete/"&gt;autocomplete dropdown&lt;/a&gt;.  It has become ubiquitous, and customers now expect them in their web apps.  &amp;quot;Can't you just set autocomplete=true or something?&amp;quot;  It's not quite that easy with &lt;a href="http://www.asp.net/mvc"&gt;ASP.NET MVC&lt;/a&gt;, but it's pretty simple.&lt;/p&gt;
&lt;p&gt;We want to set up a text box on a web page that uses &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; to call back to a controller action as the user types.  The action method will return a &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; array of values that match what the user has typed so far.  Each time they type and pause for a second, the screen should show the new matching records.&lt;/p&gt;
&lt;h2 id="the-view"&gt;The view&lt;/h2&gt;
&lt;p&gt;First, we'll work on the view.  Set a reference to jQuery and to &lt;a href="http://jqueryui.com/"&gt;jQuery UI&lt;/a&gt;.  These are included with new MVC 3 projects (look in the Scripts folder), or you can find a &lt;a href="http://code.google.com/apis/libraries/devguide.html#jqueryUI"&gt;CDN&lt;/a&gt; and reference them there.  I've got this in my view's head section:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Autocomplete Test &amp;lt;/title&amp;gt;
    &amp;lt;script src=&amp;quot;&amp;lt;%: Url.Content(&amp;quot;~/Scripts/jquery-1.4.4.min.js&amp;quot;)%&amp;gt;&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;&amp;lt;%: Url.Content(&amp;quot;~/Scripts/jquery-ui.min.js&amp;quot;)%&amp;gt;&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you need a text box to tie all this too.  The search results will be shown under this text box to give the appearance of a dropdown.  This simple form should do:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;form action=&amp;quot;/Search/ProcessTheForm&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
    &amp;lt;input id=&amp;quot;searchTerm&amp;quot; name=&amp;quot;searchTerm&amp;quot; type=&amp;quot;text&amp;quot; /&amp;gt;
    &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Go&amp;quot; /&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, you'll need to use the autocomplete function in jQuery UI like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
    $(function () {
        $(&amp;quot;#searchTerm&amp;quot;).autocomplete({
            source: &amp;quot;/Search/AutocompleteSuggestions&amp;quot;,
            minLength: 3,
            select: function (event, ui) {
                if (ui.item) {
                    $(&amp;quot;#searchTerm&amp;quot;).val(ui.item.value);
                    $(&amp;quot;form&amp;quot;).submit();
                }
            }
        });
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we've got a jQuery selector binding the autocomplete function to the searchTerm input box(&amp;quot;#searchTerm&amp;quot;).  We then set the URL for the source for the autocomplete suggestions, which in this case, will be our controller (Search) and action method (AutocompleteSuggestions).  Then we set the number of characters the user has to type before we make the first call.  It's set to three here to prevent pulling back meaningless matches from searching too soon.&lt;/p&gt;
&lt;p&gt;Finally, we set up the autocomplete function's select event to set the selected value from the dropdown list as the value in the searchTerm input box and submit the form to the Search controller and the ProcessTheForm action method.&lt;/p&gt;
&lt;p&gt;Here's the entire view for reference:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; Inherits=&amp;quot;System.Web.Mvc.ViewPage&amp;lt;dynamic&amp;gt;&amp;quot; %&amp;gt;
&lt;p&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;Autocomplete Test&amp;lt;/title&amp;gt;
&amp;lt;script src=&amp;quot;&amp;lt;%: Url.Content(&amp;quot;&lt;sub&gt;/Scripts/jquery-1.4.4.min.js&amp;quot;)%&amp;gt;&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;&amp;lt;%: Url.Content(&amp;quot;&lt;/sub&gt;/Scripts/jquery-ui.min.js&amp;quot;)%&amp;gt;&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;form action=&amp;quot;/Search/ProcessTheForm&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
&amp;lt;input id=&amp;quot;searchTerm&amp;quot; name=&amp;quot;searchTerm&amp;quot; type=&amp;quot;text&amp;quot; /&amp;gt;
&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Go&amp;quot; /&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
$(function () {
$(&amp;quot;#searchTerm&amp;quot;).autocomplete({
source: &amp;quot;/Search/AutocompleteSuggestions&amp;quot;,
minLength: 3,
select: function (event, ui) {
if (ui.item) {
$(&amp;quot;#searchTerm&amp;quot;).val(ui.item.value);
$(&amp;quot;form&amp;quot;).submit();
}
}
});
});
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="the-controller"&gt;The controller&lt;/h2&gt;
&lt;p&gt;Now you need to write something that will return the records that match what the user has entered so far.  This might be a database call with a LIKE searchTerm + &amp;quot;%&amp;quot; (watch out for SQL injection, though) or SOUNDEX or a web service call.  Be sure you limit your returned search results to maybe the top 10 matches so you don't bog things down with too much data moving over the wire.&lt;/p&gt;
&lt;p&gt;Next, set up a controller action to invoke this back-end call and JSON up the returned list.  We've already names the controller (Search) and action (AutocompleteSuggestions) in our view.  Something like this should work, where _searchRepository is my repository call that finds matching strings, which are then converted to JSON:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public JsonResult AutocompleteSuggestions(string term)
{
    var suggestions = _searchRepository.GetAutoCompleteSearchSuggestion(term);
    return Json(suggestions, JsonRequestBehavior.AllowGet);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don't forget the JsonRequestBehavior.AllowGet parameter in the Json call.  You won't get anything back from the action method if you leave it off.&lt;/p&gt;
&lt;p&gt;Also, the name of the parameter passed into the action method is important.  The jQuery UI autocomplete method will call your source URL with a query string like &amp;quot;?term=foo&amp;quot;.  If you set the parameter name to a string named &amp;quot;term&amp;quot;, the MVC model binder will grab the value from the query string for you.&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://jqueryui.com/demos/autocomplete/"&gt;jQuery UI Autocomplete&lt;/a&gt; function has several other options and events you can use in your app, and the demos are worth checking out too.&lt;/p&gt;
</description>
      <pubDate>Sat, 05 Feb 2011 01:40:23 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/building-a-windows-8-live-tile-with-javascript</guid>
      <link>https://volaresoftware.com/nl/technical-posts/building-a-windows-8-live-tile-with-javascript</link>
      <title>Building a Windows 8 Live Tile with JavaScript</title>
      <description>&lt;p&gt;If you've seen Windows 8 yet, you know it's got a tile-based start menu.  One of the cool things (or annoying things) you can do is post values on your app's tile.  This is called a &amp;quot;live tile&amp;quot; in Windows 8 world.  Your app users can turn them on or off with a right click on the tile.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/image_19.png" alt="image_19.png" /&gt;&lt;/p&gt;
&lt;p&gt;Here's how I built one with JavaScript.&lt;/p&gt;
&lt;h2 id="figure-out-what-you-want-to-display-on-your-live-tiles"&gt;Figure out what you want to display on your live tiles&lt;/h2&gt;
&lt;p&gt;This is what my tile looks like before it's &amp;quot;live&amp;quot; as both a smaller (square) and a larger (wide) tile:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/small-tile.png" alt="small-tile.png" /&gt;          &lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/wide-tile.png" alt="wide-tile.png" /&gt;&lt;/p&gt;
&lt;p&gt;The live tile concept is that you pick a style template, build up some XML, then push that XML to the tile through the notification API.  &lt;a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx"&gt;These guidelines show you the different tile templates you can pick&lt;/a&gt;.  Find a square tile and a wide tile you like, and pay attention to the name of that template, since you'll use that soon.&lt;/p&gt;
&lt;p&gt;In this case, I decided I like TileSquareText01:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/square-sample.png" alt="square-sample.png" /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;tile&amp;gt;
  &amp;lt;visual&amp;gt;
    &amp;lt;binding template=&amp;quot;TileSquareText01&amp;quot;&amp;gt;
      &amp;lt;text id=&amp;quot;1&amp;quot;&amp;gt;Text Field 1&amp;lt;/text&amp;gt;
      &amp;lt;text id=&amp;quot;2&amp;quot;&amp;gt;Text Field 2&amp;lt;/text&amp;gt;
      &amp;lt;text id=&amp;quot;3&amp;quot;&amp;gt;Text Field 3&amp;lt;/text&amp;gt;
      &amp;lt;text id=&amp;quot;4&amp;quot;&amp;gt;Text Field 4&amp;lt;/text&amp;gt;
    &amp;lt;/binding&amp;gt;  
  &amp;lt;/visual&amp;gt;
&amp;lt;/tile&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and TileWideText01:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/wide-sample.png" alt="wide-sample.png" /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;tile&amp;gt;
  &amp;lt;visual&amp;gt;
    &amp;lt;binding template=&amp;quot;TileWideText01&amp;quot;&amp;gt;
      &amp;lt;text id=&amp;quot;1&amp;quot;&amp;gt;Text Header Field 1&amp;lt;/text&amp;gt;
      &amp;lt;text id=&amp;quot;2&amp;quot;&amp;gt;Text Field 2&amp;lt;/text&amp;gt;
      &amp;lt;text id=&amp;quot;3&amp;quot;&amp;gt;Text Field 3&amp;lt;/text&amp;gt;
      &amp;lt;text id=&amp;quot;4&amp;quot;&amp;gt;Text Field 4&amp;lt;/text&amp;gt;
      &amp;lt;text id=&amp;quot;5&amp;quot;&amp;gt;Text Field 5&amp;lt;/text&amp;gt;
    &amp;lt;/binding&amp;gt;  
  &amp;lt;/visual&amp;gt;
&amp;lt;/tile&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The plan is to show the users current altitude as a number on the top, larger font line, then show the units (feet or meters) under that in the smaller font.&lt;/p&gt;
&lt;p&gt;There are several rules about what you can and can't show on your tiles, so &lt;a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh465403.aspx"&gt;check the guidelines carefully&lt;/a&gt; to be sure your idea will not get rejected by the Windows Store during the certification process.&lt;/p&gt;
&lt;h2 id="tests-for-the-correct-live-tile-xml"&gt;Tests for the correct live tile XML&lt;/h2&gt;
&lt;p&gt;Since the live tile notification is all about sending the right XML, let's start with a test of the XML we want at the end.  Here I'm using &lt;a href="http://qunitjs.com/"&gt;QUnit&lt;/a&gt; to check the XML.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;test(&amp;quot;tile&amp;quot;, function () {
    var altitude = 6071,
        altitudeUnits = &amp;quot;feet&amp;quot;,
        result,
        expected;
&lt;pre&gt;&lt;code&gt;result = tile.buildSquareTileXml(altitude, altitudeUnits);
expected = '&amp;amp;lt;tile&amp;amp;gt;' +
    '&amp;amp;lt;visual&amp;amp;gt;' +
    '&amp;amp;lt;binding template=&amp;amp;quot;TileSquareText01&amp;amp;quot; branding=&amp;amp;quot;name&amp;amp;quot;&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;1&amp;amp;quot;&amp;amp;gt;6071&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;2&amp;amp;quot;&amp;amp;gt;feet&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;3&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;4&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;/binding&amp;amp;gt;' +
    '&amp;amp;lt;/visual&amp;amp;gt;' +
    '&amp;amp;lt;/tile&amp;amp;gt;';
equal(result.getXml().toString(), expected, &amp;amp;quot;should get correct xml for square tile&amp;amp;quot;);

result = tile.buildWideTileXml(altitude, altitudeUnits);
expected = '&amp;amp;lt;tile&amp;amp;gt;' +
    '&amp;amp;lt;visual&amp;amp;gt;' +
    '&amp;amp;lt;binding template=&amp;amp;quot;TileWideText01&amp;amp;quot; branding=&amp;amp;quot;name&amp;amp;quot;&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;1&amp;amp;quot;&amp;amp;gt;6071&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;2&amp;amp;quot;&amp;amp;gt;feet&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;3&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;4&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;text id=&amp;amp;quot;5&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/text&amp;amp;gt;' +
    '&amp;amp;lt;/binding&amp;amp;gt;' +
    '&amp;amp;lt;/visual&amp;amp;gt;' +
    '&amp;amp;lt;/tile&amp;amp;gt;';
equal(result.getXml().toString(), expected, &amp;amp;quot;should get correct xml for wide tile&amp;amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;});
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;These tests fail since we haven't written the functions yet, but we'll do that next.  Ignore the &amp;quot;branding&amp;quot; attribute for now.  We'll come back to that.&lt;/p&gt;
&lt;h2 id="build-up-the-live-tile-xml"&gt;Build up the live tile XML&lt;/h2&gt;
&lt;p&gt;Here's the code to get the correct XML and get those tests passing.  See those calls the &lt;code&gt;Windows.UI.Notifications.TileTemplateType&lt;/code&gt;?  That's where you plug in the name of the square and wide template you picked from the catalog.&lt;/p&gt;
&lt;p&gt;I'm building up an array of values for the different lines of text.  Use any XML or string manipulation technique you like.  I got this one from the Windows 8 SDK samples.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;function buildSquareTileXml(altitude, altitudeUnits) {
    var squareTemplate = Windows.UI.Notifications.TileTemplateType.tileSquareText01,
            squareTileLines = [
                altitude,
                altitudeUnits
            ],
            squareTileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(squareTemplate),
            squareTileTextAttributes = squareTileXml.getElementsByTagName(&amp;quot;text&amp;quot;);
&lt;pre&gt;&lt;code&gt;for (var i = 0; i &amp;amp;lt; squareTileLines.length; i++) {
    squareTileTextAttributes[i].appendChild(squareTileXml.createTextNode(squareTileLines[i]));
}

var squareTileBinding = squareTileXml.getElementsByTagName(&amp;amp;quot;binding&amp;amp;quot;);
if (squareTileBinding[0]) {
    squareTileBinding[0].setAttribute(&amp;amp;quot;branding&amp;amp;quot;, &amp;amp;quot;name&amp;amp;quot;);
}

return squareTileXml;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;function buildWideTileXml(altitude, altitudeUnits) {
var wideTemplate = Windows.UI.Notifications.TileTemplateType.tileWideText01,
wideTileLines = [
altitude,
altitudeUnits
],
wideTileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(wideTemplate),
wideTileTextAttributes = wideTileXml.getElementsByTagName(&amp;quot;text&amp;quot;);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (var i = 0; i &amp;amp;lt; wideTileLines.length; i++) {
    wideTileTextAttributes[i].appendChild(wideTileXml.createTextNode(wideTileLines[i]));
}

var binding = wideTileXml.getElementsByTagName(&amp;amp;quot;binding&amp;amp;quot;);
if (binding[0]) {
    binding[0].setAttribute(&amp;amp;quot;branding&amp;amp;quot;, &amp;amp;quot;name&amp;amp;quot;);
}

return wideTileXml;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="combine-the-square-and-wide-xml"&gt;Combine the square and wide XML&lt;/h2&gt;
&lt;p&gt;Since users of your tile can toggle the smaller (square) or larger (wide) version of your tile, you want to combine the square and wide XML and send down both.  Here's how to do that.  Again, this is just XML manipulation, use any technique you like.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;function combineTileXml(wideTileXml, squareTileXml) {
    var node = wideTileXml.importNode(squareTileXml.getElementsByTagName(&amp;quot;binding&amp;quot;).item(0), true);
    wideTileXml.getElementsByTagName(&amp;quot;visual&amp;quot;).item(0).appendChild(node);
&lt;pre&gt;&lt;code&gt;return wideTileXml;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="pass-the-combined-live-tile-xml-to-the-windows-8-api"&gt;Pass the combined live tile XML to the Windows 8 API&lt;/h2&gt;
&lt;p&gt;Now that you've got the final XML you want, create a Tile Notification object and pass it to the Tile Update Manager:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;function sendTileUpdate(altitude, altitudeUnits) {
    var wideTileXml,
        squareTileXml,
        combinedTileXml,
        tileNotification;
&lt;pre&gt;&lt;code&gt;if (altitude &amp;amp;amp;amp;&amp;amp;amp;amp; altitudeUnits) {
    wideTileXml = buildWideTileXml(altitude, altitudeUnits);
    squareTileXml = buildSquareTileXml(altitude, altitudeUnits);
    combinedTileXml = combineTileXml(wideTileXml, squareTileXml);

    tileNotification = new Windows.UI.Notifications.TileNotification(combinedTileXml);
    Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForApplication().update(tileNotification);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The last two lines are doing the real work here, by using the Windows 8 notifications API.  The rest is calling the other helper functions.&lt;/p&gt;
&lt;h2 id="calling-the-notification-code"&gt;Calling the notification code&lt;/h2&gt;
&lt;p&gt;So who notifies the notifier code that we've got some new stuff to show on the line tile?  You do!  Figure out when something interesting happens in your app, and send a notification to the live tile then.  In this case, that looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;tile.sendTileUpdate(altitude, altitudeUnits);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="putting-it-all-together"&gt;Putting it all together&lt;/h2&gt;
&lt;p&gt;Here's the result for the square and wide tiles:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/smaill-live-tile.png" alt="smaill-live-tile.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/wide-live-tile.png" alt="wide-live-tile.png" /&gt;&lt;/p&gt;
&lt;p&gt;Here's the combined JavaScript.  I put it all in a file named it tile.js and used the WinJS namespacing function.  This is pretty much the same as the revealing module pattern, and it means I can call &lt;code&gt;tile.&amp;lt;whatever&amp;gt;&lt;/code&gt; from the tests and other JavaScript files.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;(function () {
    &amp;quot;use strict&amp;quot;;
&lt;pre&gt;&lt;code&gt;function sendTileUpdate(altitude, altitudeUnits) {
    var wideTileXml,
        squareTileXml,
        combinedTileXml,
        tileNotification;

    if (altitude &amp;amp;amp;amp;&amp;amp;amp;amp; altitudeUnits) {
        wideTileXml = buildWideTileXml(altitude, altitudeUnits);
        squareTileXml = buildSquareTileXml(altitude, altitudeUnits);
        combinedTileXml = combineTileXml(wideTileXml, squareTileXml);

        tileNotification = new Windows.UI.Notifications.TileNotification(combinedTileXml);
        Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForApplication().update(tileNotification);
    }
}

function buildSquareTileXml(altitude, altitudeUnits) {
    var squareTemplate = Windows.UI.Notifications.TileTemplateType.tileSquareText01,
            squareTileLines = [
                altitude,
                altitudeUnits
            ],
            squareTileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(squareTemplate),
            squareTileTextAttributes = squareTileXml.getElementsByTagName(&amp;amp;quot;text&amp;amp;quot;);

    for (var i = 0; i &amp;amp;lt; squareTileLines.length; i++) {
        squareTileTextAttributes[i].appendChild(squareTileXml.createTextNode(squareTileLines[i]));
    }

    var squareTileBinding = squareTileXml.getElementsByTagName(&amp;amp;quot;binding&amp;amp;quot;);
    if (squareTileBinding[0]) {
        squareTileBinding[0].setAttribute(&amp;amp;quot;branding&amp;amp;quot;, &amp;amp;quot;name&amp;amp;quot;);
    }

    return squareTileXml;
}

function buildWideTileXml(altitude, altitudeUnits) {
    var wideTemplate = Windows.UI.Notifications.TileTemplateType.tileWideText01,
            wideTileLines = [
                altitude,
                altitudeUnits
            ],
            wideTileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(wideTemplate),
            wideTileTextAttributes = wideTileXml.getElementsByTagName(&amp;amp;quot;text&amp;amp;quot;);

    for (var i = 0; i &amp;amp;lt; wideTileLines.length; i++) {
        wideTileTextAttributes[i].appendChild(wideTileXml.createTextNode(wideTileLines[i]));
    }

    var binding = wideTileXml.getElementsByTagName(&amp;amp;quot;binding&amp;amp;quot;);
    if (binding[0]) {
        binding[0].setAttribute(&amp;amp;quot;branding&amp;amp;quot;, &amp;amp;quot;name&amp;amp;quot;);
    }

    return wideTileXml;
}

function combineTileXml(wideTileXml, squareTileXml) {
    var node = wideTileXml.importNode(squareTileXml.getElementsByTagName(&amp;amp;quot;binding&amp;amp;quot;).item(0), true);
    wideTileXml.getElementsByTagName(&amp;amp;quot;visual&amp;amp;quot;).item(0).appendChild(node);

    return wideTileXml;
}

WinJS.Namespace.define(&amp;amp;quot;tile&amp;amp;quot;, {
    sendTileUpdate: sendTileUpdate,
    buildWideTileXml: buildWideTileXml,
    buildSquareTileXml: buildSquareTileXml
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;})();
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="branding"&gt;Branding&lt;/h2&gt;
&lt;p&gt;In the bottom left corner of the tile, I am showing the name of the app, in this case &amp;quot;Altitude&amp;quot;, on the live tile.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/smaill-live-tile_1.png" alt="smaill-live-tile_1.png" /&gt;          &lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/wide-live-tile_1.png" alt="wide-live-tile_1.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you like, you can show your logo here instead.  This comes from the 30x30 logo in your package.appxmanifest on the Application UI tab, under Tile &amp;gt; Small Logo.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/image_20.png" alt="image_20.png" /&gt;&lt;/p&gt;
&lt;p&gt;Change these lines:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;binding[0].setAttribute(&amp;quot;branding&amp;quot;, &amp;quot;name&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;binding[0].setAttribute(&amp;quot;branding&amp;quot;, &amp;quot;logo&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And you'll get this instead:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/small-live-tile-logo.png" alt="small-live-tile-logo.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/wide-live-tile-logo.png" alt="wide-live-tile-logo.png" /&gt;&lt;/p&gt;
&lt;p&gt;In fact, you can take out all the code around branding if you like the logo there, since that's the default behavior.  If you want neither your app name nor your logo there, you can set the branding attribute to &amp;quot;none&amp;quot;.&lt;/p&gt;
&lt;h2 id="hey-my-live-tile-doesnt-work"&gt;Hey, my Live Tile doesn't work!&lt;/h2&gt;
&lt;p&gt;I had this experience the first couple times I ran my code, too.  The most common mistake I've seen is invalid XML, so be sure you add those test first to avoid that.&lt;/p&gt;
&lt;p&gt;The other snag was using the Simulator in Visual Studio 2012 that simulates a tablet with touch and rotating.  I don't know what the issue was, but my live tile didn't update when I ran it through the Simulator.  Other live tiles could be turned on and off, but not the one for my app.  When I ran on Local Machine instead, the live tile worked fine.  So if you're not seeing your live tile work in the Simulator, switch to Local Machine and see if that fixes it for you.&lt;/p&gt;
</description>
      <pubDate>Tue, 16 Oct 2012 00:39:54 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/making-your-aspnet-mvc-app-look-decent-on-an-iphone-or-ipad</guid>
      <link>https://volaresoftware.com/nl/technical-posts/making-your-aspnet-mvc-app-look-decent-on-an-iphone-or-ipad</link>
      <title>Making your ASP.NET MVC app look decent on an iPhone or iPad</title>
      <description>&lt;p&gt;I wanted to try out the &lt;a href="http://www.asp.net/mvc/tutorials/mvc-4/aspnet-mvc-4-mobile-features"&gt;new mobile features of ASP.NET MVC 4&lt;/a&gt; to convert an existing site (this one!) to a half-decent looking &lt;a href="http://www.apple.com/iphone/"&gt;iPhone&lt;/a&gt;/&lt;a href="http://www.apple.com/ipad/"&gt;iPad&lt;/a&gt; app.  It was really easy.  Here are the steps and what I learned in the process.&lt;/p&gt;
&lt;h2 id="think-about-what-your-mobile-user-will-want-to-do"&gt;Think about what your mobile user will want to do&lt;/h2&gt;
&lt;p&gt;This is the most important piece, and it's one you need to take seriously before you dive in.  If you skip it, you'll just have a mess.  You know that tablets and phones are smaller, so things that require lots of screen space won't work.  But what is the &lt;strong&gt;main&lt;/strong&gt; thing people open the site/app to do?  Optimize for that and put it front and center.  If there is more than one thing your site/app does, how will mobile user's navigate around?  When converting an existing app to mobile, you'll probably want to cut out a lot of extraneous stuff.  You could also phase in different chunks.  It doesn't have to be all or nothing.&lt;/p&gt;
&lt;h2 id="choose-your-technical-approach"&gt;Choose your technical approach&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://twitter.com/shanselman"&gt;Scott Hanselman&lt;/a&gt; has a &lt;a href="http://www.hanselman.com/blog/CreateAGreatMobileExperienceForYourWebsiteTodayPlease.aspx"&gt;nice blog post and chart showing effort compared to user experience&lt;/a&gt; across different approaches to making your app mobile.&lt;/p&gt;
&lt;p&gt;He covers responsive design (&lt;a href="http://www.w3.org/TR/css3-mediaqueries/"&gt;CSS media queries&lt;/a&gt; and resizing), using a mobile framework (like &lt;a href="http://jquerymobile.com/"&gt;jQuery Mobile&lt;/a&gt;), or going native (&lt;a href="http://en.wikipedia.org/wiki/Objective-C"&gt;Objective-C&lt;/a&gt;).  My only quibble with the Scott's chart is the green circle for native apps is too small.  I think that's WAAAAY more effort.&lt;/p&gt;
&lt;p&gt;For this post, I went with a mobile framework (jQuery Mobile).  This is the most bang for your buck.  You can learn it in less than an hour, and convert views and layouts in a half day to a day, depending on how complicated your views are.&lt;/p&gt;
&lt;h2 id="get-jquery-mobile"&gt;Get jQuery Mobile&lt;/h2&gt;
&lt;p&gt;Add the &lt;a href="http://nuget.org/packages/jquery.mobile"&gt;jQuery Mobile NuGet package&lt;/a&gt; to your web project.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/9/image_17.png" alt="image_17.png" /&gt;&lt;/p&gt;
&lt;p&gt;It will add the JavaScript, CSS, and sprite icon images in the /Scripts, /Content, and /Content/Images folders in your web project.  I moved the JavaScript and CSS to /Content/Scripts/Downloaded and /Content/Styles/Downloaded folders.  I prefer to do this so I can bundle scripts with wildcards like /Content/Scripts/Site/*.js. Here's my folder structure:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/9/image_18.png" alt="image_18.png" /&gt;&lt;/p&gt;
&lt;h2 id="bundling"&gt;Bundling&lt;/h2&gt;
&lt;p&gt;I dropped the &lt;code&gt;*.min.js&lt;/code&gt; and &lt;code&gt;*.min.css&lt;/code&gt; files since I'm combining and minifying these with the BundleConfig like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web.Optimization;
&lt;p&gt;namespace App_Start
{
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
// Scripts&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        bundles.Add(new ScriptBundle(&amp;amp;quot;~/Content/Scripts/modernizr&amp;amp;quot;).Include(
            &amp;amp;quot;~/Content/Scripts/Downloaded/modernizr-2.6.2.js&amp;amp;quot;)); 

        bundles.Add(new ScriptBundle(&amp;amp;quot;~/Content/Scripts/all&amp;amp;quot;).Include(
            &amp;amp;quot;~/Content/Scripts/Downloaded/jquery-1.8.1.js&amp;amp;quot;, 
            &amp;amp;quot;~/Content/Scripts/Downloaded/jquery.unobtrusive-ajax.js&amp;amp;quot;,
            &amp;amp;quot;~/Content/Scripts/Downloaded/jquery.validate.js&amp;amp;quot;,
            &amp;amp;quot;~/Content/Scripts/Downloaded/jquery.validate.unobtrusive.js&amp;amp;quot;,
            &amp;amp;quot;~/Content/Scripts/Site/*.js&amp;amp;quot;));

        bundles.Add(new ScriptBundle(&amp;amp;quot;~/Content/Scripts/mobileall&amp;amp;quot;).Include(
            &amp;amp;quot;~/Content/Scripts/Downloaded/jquery-1.8.1.js&amp;amp;quot;,
            &amp;amp;quot;~/Content/Scripts/Downloaded/jquery.mobile-1.1.1.js&amp;amp;quot;));

        // Styles

        bundles.Add(new StyleBundle(&amp;amp;quot;~/Content/Styles/all&amp;amp;quot;).Include(
            &amp;amp;quot;~/Content/Styles/Site/Site.css&amp;amp;quot;));

        bundles.Add(new StyleBundle(&amp;amp;quot;~/Content/Styles/mobileall&amp;amp;quot;).Include(
            &amp;amp;quot;~/Content/Styles/Downloaded/jquerymobile/*.css&amp;amp;quot;,
            &amp;amp;quot;~/Content/Styles/Site/Mobile.css&amp;amp;quot;));
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The bundles created here are for the JavaScript and CSS for the desktop site (&amp;quot;all&amp;quot;) and the mobile site (&amp;quot;mobileall&amp;quot;).  The &amp;quot;modernizr&amp;quot; bundle is separate because it only works in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section, but the rest is loaded at the bottom of the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag in the Layout view so it doesn't block page loading.&lt;/p&gt;
&lt;h2 id="make-a_layout.mobile.cshtml"&gt;Make a _Layout.Mobile.cshtml&lt;/h2&gt;
&lt;p&gt;You'll want a mobile layout view. It's probably simplest to take your existing &lt;code&gt;_Layout.cshtml&lt;/code&gt;, copy/paste, and rename it to &lt;code&gt;_Layout.Mobile.cshtml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The view engine routes &amp;quot;mobile&amp;quot; requests to the correct place.  I have mobile in quotes here because it puts iPads in that category.  Seems like it would be either &lt;code&gt;_Layout.Tablet.cshtml&lt;/code&gt; or &lt;code&gt;_Layout.Phone.cshtml&lt;/code&gt; instead of &lt;code&gt;_Layout.Mobile.cshtml&lt;/code&gt;, since those are very different form factors, but that's what you get out of the box.&lt;/p&gt;
&lt;p&gt;If you don't like that, you can add specific views for specific devices with &lt;a href="http://msdn.microsoft.com/en-us/library/jj149688.aspx"&gt;display modes&lt;/a&gt;.  I recommend looking through your web logs to see what your users are really browsing with so you spend your time making your app look its best for the most popular user agents.  Start with a generic mobile layout and go from there if it starts to break down and you're getting enough traffic from that device to warrant the extra work.&lt;/p&gt;
&lt;p&gt;You'll probably rip out pieces of your app/site in the mobile layout.  Some stuff doesn't make sense on a phone, so this is where you can take it out if it's site wide.  If it's something in a view you want to hide, see below.&lt;/p&gt;
&lt;p&gt;For the JavaScript, you can probably get away with just jQuery and jQuery Mobile.  You probably won't need Modernizr.  You may have some site-specific JavaScript you need to include in their, too.&lt;/p&gt;
&lt;p&gt;For style sheets, I recommend starting with just the jQuery Mobile CSS.  You can add your own Mobile.css (you can rename this to anything you like) referenced in your mobile layout for tweaks and overrides you need to do.  I'd leave the jQuery Mobile CSS as-is so you can upgrade later without problems.&lt;/p&gt;
&lt;p&gt;You'll also want to set your viewport to max width for every device:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's my &lt;code&gt;_Layout.Mobile.cshtml&lt;/code&gt; (the relevant parts anyway):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt;
    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;@ViewBag.Title&amp;lt;/title&amp;gt;
    @Styles.Render(&amp;quot;~/Content/Styles/mobileall&amp;quot;)
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div data-role=&amp;quot;page&amp;quot; data-theme=&amp;quot;c&amp;quot;&amp;gt;
        &amp;lt;header data-role=&amp;quot;header&amp;quot;&amp;gt;
            &amp;lt;div&amp;gt;
                &amp;lt;a href=&amp;quot;@Url.Action(&amp;quot;Index&amp;quot;, &amp;quot;Home&amp;quot;)&amp;quot;&amp;gt;
                    &amp;lt;img src=&amp;quot;@Url.Content(&amp;quot;~/Content/Images/Logos/Logo_100px_High.png&amp;quot;)&amp;quot; alt=&amp;quot;Volare Systems, Inc.&amp;quot; width=&amp;quot;160px&amp;quot; height=&amp;quot;100px&amp;quot; /&amp;gt;
                &amp;lt;/a&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/header&amp;gt;
        &amp;lt;section id=&amp;quot;content&amp;quot; data-role=&amp;quot;content&amp;quot;&amp;gt;
            @RenderBody()
        &amp;lt;/section&amp;gt;
        &amp;lt;footer&amp;gt;
            &amp;lt;nav&amp;gt;
                &amp;lt;ul data-role=&amp;quot;listview&amp;quot; data-content-theme=&amp;quot;c&amp;quot; data-divider-theme=&amp;quot;d&amp;quot; data-inset=&amp;quot;true&amp;quot; &amp;gt;
                    &amp;lt;li data-role=&amp;quot;list-divider&amp;quot;&amp;gt;What We Do&amp;lt;/li&amp;gt;
                    &amp;lt;li&amp;gt;@Html.ActionLink(&amp;quot;Home&amp;quot;, &amp;quot;Index&amp;quot;, &amp;quot;Home&amp;quot;)&amp;lt;/li&amp;gt;
                    &amp;lt;li&amp;gt;@Html.ActionLink(&amp;quot;Services&amp;quot;, &amp;quot;Index&amp;quot;, &amp;quot;Services&amp;quot;)&amp;lt;/li&amp;gt;
                    &amp;lt;li&amp;gt;@Html.ActionLink(&amp;quot;Customer testimonials&amp;quot;, &amp;quot;CustomerTestimonials&amp;quot;, &amp;quot;Services&amp;quot;)&amp;lt;/li&amp;gt;
                    ...
                &amp;lt;/ul&amp;gt;
            &amp;lt;/nav&amp;gt;
            &amp;lt;div id=&amp;quot;copyright&amp;quot;&amp;gt;
                &amp;amp;amp;copy; 2009 - @DateTime.Now.Year.ToString() @Html.ActionLink(&amp;quot;Volare Systems, Inc.&amp;quot;, &amp;quot;Index&amp;quot;, &amp;quot;Home&amp;quot;)
            &amp;lt;/div&amp;gt;
        &amp;lt;/footer&amp;gt;
    &amp;lt;/div&amp;gt;
    @Scripts.Render(&amp;quot;~/Content/Scripts/mobileall&amp;quot;)
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="start-using-jquery-mobile"&gt;Start using jQuery Mobile&lt;/h2&gt;
&lt;p&gt;Now it's time to start adding in the &lt;code&gt;data-*&lt;/code&gt; attributes and classes jQuery Mobile wants to use.  You'll find them here on the &lt;a href="http://jquerymobile.com/demos/1.1.1/"&gt;demo site&lt;/a&gt;.  I used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jquerymobile.com/demos/1.1.1/docs/pages/page-anatomy.html"&gt;data-page=&amp;quot;page&amp;quot;&lt;/a&gt; in the mobile layout as an outer wrapper&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jquerymobile.com/demos/1.1.1/docs/api/themes.html"&gt;data-theme=&amp;quot;c&amp;quot;&lt;/a&gt; (try out the different themes to see what suits you best by swapping out letters a-e)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jquerymobile.com/demos/1.1.1/docs/about/getting-started.html"&gt;data-role=&amp;quot;content&amp;quot;&lt;/a&gt; around the &lt;code&gt;@RenderBody&lt;/code&gt; markup&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jquerymobile.com/demos/1.1.1/docs/lists/docs-lists.html"&gt;data-role=&amp;quot;listview&amp;quot;&lt;/a&gt; and &lt;a href="http://jquerymobile.com/demos/1.1.1/docs/lists/lists-divider.html"&gt;data-role=&amp;quot;list-divider&amp;quot;&lt;/a&gt; for the navigation&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jquerymobile.com/demos/1.1.1/docs/content/content-collapsible-set.html"&gt;data-role=&amp;quot;collapsible-set&amp;quot;&lt;/a&gt; and &lt;a href="http://jquerymobile.com/demos/1.1.1/docs/content/content-collapsible.html"&gt;data-role=&amp;quot;collapsible&amp;quot;&lt;/a&gt; for collapsible text that shows/hides when you click it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are the results:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/9/home1.png" alt="home1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/9/phonehome.png" alt="phonehome.png" /&gt;&lt;/p&gt;
&lt;p&gt;Click through the docs and see what you can find that adapts well to your situation.  For forms, I found it was fine to remove my normal style sheet and let jQuery Mobile take over.&lt;/p&gt;
&lt;h2 id="make-a-mobile.css"&gt;Make a Mobile.css&lt;/h2&gt;
&lt;p&gt;I use Site.css and Mobile.css as my desktop and tablet/phone CSS files.  The &lt;code&gt;_Layout.Mobile.cshtml&lt;/code&gt; references to the Mobile.css, and &lt;code&gt;_Layout.cshtml&lt;/code&gt; references the &lt;code&gt;Site.css&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You may not need a Mobile.css, but I found it useful to tweak margins, padding, etc. to get the look I wanted.  You'll probably have to use the &lt;code&gt;!important&lt;/code&gt; CSS tag to force your CSS to override the jQuery Mobile CSS, so watch out for that.  Also, every time you do this, someone at &lt;a href="http://www.alistapart.com/"&gt;A List Apart&lt;/a&gt; sighs heavily.&lt;/p&gt;
&lt;h2 id="test-and-tweak-your-views"&gt;Test and tweak your views&lt;/h2&gt;
&lt;p&gt;There are lots of cheap and free iPhone/iPad simulators out there.  Try to find a free one you like.  I gave up and downloaded the &lt;a href="http://www.electricplum.com/simulator.aspx"&gt;Electric Plum&lt;/a&gt; one.  So far, so good.  It's more stable than the free ones I tried.&lt;/p&gt;
&lt;p&gt;Once you browse to your site on localhost, you'll see things you didn't realize would be such a fail on the phone.  This is your chance to remove it or fix it.  There are several approaches I used, based on the situation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add jQuery Mobile &lt;code&gt;data-*&lt;/code&gt; attributes to your view to render it the jQuery Mobile way.  Sprinkling these should not collide with your HTML for desktop rendering.&lt;/li&gt;
&lt;li&gt;Change the &lt;code&gt;Mobile.css&lt;/code&gt; to draw the elements a little differently just for mobile.  If it's really minor, you can hide it with a CSS &lt;code&gt;display: none;&lt;/code&gt;, but keep in mind this will run on a phone.  If you have the chance to send fewer bytes from the server to the device, that's almost always going to be the way to go.&lt;/li&gt;
&lt;li&gt;Add server-side conditional checks for code or markup that is &lt;strong&gt;only&lt;/strong&gt; for mobile (or just for desktop).  In a MVC Razor view, this looks like:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;@if (Request.Browser.IsMobile) {
    // do something just for mobile
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;If the conditional branching inside your view get to be too ugly, you can add a mobile-only view with the same naming pattern.  So &lt;code&gt;Index.cshtml&lt;/code&gt; has a mobile cohort in &lt;code&gt;Index.Mobile.cshtml&lt;/code&gt;.  You can break common code between the two views into partial views, and have the mobile and non-mobile views reference those partial views with the normal&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;@Html.Partial(&amp;quot;_ThePartialView&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Mon, 24 Sep 2012 02:35:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/getting-http2-working-with-azure-cdn</guid>
      <link>https://volaresoftware.com/nl/technical-posts/getting-http2-working-with-azure-cdn</link>
      <title>Getting HTTP/2 working with Azure CDN</title>
      <description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/HTTP/2"&gt;HTTP/2&lt;/a&gt; serves web content faster through multiplexing, where several requests can be sent on the same TCP connection.  However HTTP/2 is not available today on Azure App Services (web apps). &lt;a href="https://feedback.azure.com/forums/169385-web-apps/suggestions/9552936-enable-http-2-on-azure-web-apps"&gt;A lot of people wish it was&lt;/a&gt;, but that's a limitation of Azure hosting right now. One of the Azure feedback admins had this to say on January 9, 2018:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi all. As everyone had noticed, we have upgraded App Service resources to Server 2016. As mentioned in our updates, this is indeed paving the way to HTTP/2 support across the board. As we are settling in with stability of the new OS version, we will begin work to open up HTTP/2. When I have a concrete timeline to share, I will do so. We should expect that in the next few months.&lt;/p&gt;
&lt;p&gt;Thanks,&lt;br /&gt;
Oded&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So it's coming, and hopefully soon, but it's not there yet.  In the meantime, you can put static resources like images on an Azure CDN and get HTTP/2 performance benefits, in addition to normal CDN benefits for long-lived content, like cache headers that don't expire any time soon and a geographically distributed network to host it on.&lt;/p&gt;
&lt;p&gt;This post is a walkthrough on how to do that with Azure Storage and Azure CDN services.&lt;/p&gt;
&lt;h3 id="azure-setup"&gt;Azure Setup&lt;/h3&gt;
&lt;p&gt;First, go into your Azure account and create a new resource group.  This makes it easier for testing so you can delete the whole thing when you're done playing around. I named mine &lt;code&gt;testresourcegroup&lt;/code&gt;.  There are so many pieces to an Azure infrastructure, you are better off if you prefix or suffix everything with one name, like your project name or acronym, and then put the name of the Azure thing you're creating somewhere in that name.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_resource_grou.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_resource_grou.png" /&gt;&lt;/p&gt;
&lt;p&gt;When that's created, go to that resource group. We'll add an App Service Plan (Azure-speak for the server/account type you want for your web app) and an App Service.&lt;/p&gt;
&lt;p&gt;I click the + button to add, search for &amp;quot;App Service Plan&amp;quot;, pick that, and fill that out. In the Pricing tier, I selected &amp;quot;Free&amp;quot; for this demo.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_service_plan.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_service_plan.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now create a test web app by adding another resource to your resource group, searching for App Service, and selecting Web App. Be sure to select your newly created App Service Plan. I ended up having to go to &lt;code&gt;testweb17&lt;/code&gt; to get to a unique, publicly addressable name.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_web_app.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_web_app.png" /&gt;&lt;/p&gt;
&lt;p&gt;While that's being created, let's add Azure blob storage. Go back to your resource group, click the + button again to add, and search for &amp;quot;blob storage&amp;quot;, then select &amp;quot;Storage account – blob, file, table, queue&amp;quot;. Give it a unique name. In my case, I had to use &lt;code&gt;teststorge19&lt;/code&gt; to get a unique, publicly addressable name. I also changed the default Account kind to Blob storage since that's all I need. You can come back later and tweak the other settings here based on your app's needs.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_storage_account.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_storage_account.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now we need to create the CDN in Azure. Go back to your resource group, click the + to add, and search for &amp;quot;CDN&amp;quot; and select it from the list. Give it a name. I used &lt;code&gt;testcdn&lt;/code&gt;. Pick a pricing tier. I used Standard Verizon (Verizon allows custom domain HTTPS connections, Akamai doesn't).&lt;/p&gt;
&lt;p&gt;Then select the option to create a CDN Endpoint. Like the App Service and App Service Plan relationship, the CDN is the service level and pricing, but the CDN Endpoint is the thing you really connect to. Pick a CDN endpoint name.  I used &lt;code&gt;testcdn19&lt;/code&gt; to match up with my storage account name. Again, this must be unique and publicly addressable. Be sure to pick Origin type of Storage and pick the Original hostname for your storage account from the drop down. I used &lt;code&gt;teststorage19.blog.core.windows.net&lt;/code&gt; since that is my test storage account created above.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_cdn_profile.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_cdn_profile.png" /&gt;&lt;/p&gt;
&lt;p&gt;When Azure is done huffing and puffing, your new resource group should look like this, but of course with your names. You'll have an App Service Plan with an App Service, a Storage Account, and a CDN Profile with a CDN Endpoint.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_services.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_services.png" /&gt;&lt;/p&gt;
&lt;h3 id="web-setup"&gt;Web Setup&lt;/h3&gt;
&lt;p&gt;I've made a one page web app with an index.html and an image.  You can &lt;a href="https://github.com/VolareSoftware/HTTP2WithAzureCDN"&gt;download them from GitHub&lt;/a&gt; or use your own content or test page. It's nothing more than this HTML and a picture.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt;
    &amp;lt;title&amp;gt;HTTP/2 with Azure CDN&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;p&amp;gt;Here is an image of an elk in Rocky Mountain National Park.&amp;lt;/p&amp;gt;
    &amp;lt;img src=&amp;quot;images/Fall - Estes Elk.jpg&amp;quot; /&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To upload this web app to Azure, I first need to get a publish profile from Azure in my App Service.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_get_publish_profile.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_get_publish_profile.png" /&gt;&lt;/p&gt;
&lt;p&gt;Then I open my web app in Visual Studio, right click on the web site or web project and select Publish Web App.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/visual_studio_publish_web_app.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/visual_studio_publish_web_app.png" /&gt;&lt;/p&gt;
&lt;p&gt;Next, I tell Visual Studio to import the just downloaded publish profile.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/visual_studio_publish_settings.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/visual_studio_publish_settings.png" /&gt;&lt;/p&gt;
&lt;p&gt;Then when I publish my web app, it goes up to Azure and is publicly available.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/visual_studio_publish.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/visual_studio_publish.png" /&gt;&lt;/p&gt;
&lt;p&gt;After the publishing process completes, my browser opens the test web app at &lt;code&gt;https://testweb17.azurewebsites.net/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/sample_web_page_with_image.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/sample_web_page_with_image.png" /&gt;&lt;/p&gt;
&lt;p&gt;If I open Chrome Dev Tools and go to the Network tab, I can see the two requests (one for the page, one for the image) are using HTTP 1.1. Let's see if we can get that image to be served using HTTP/2.&lt;/p&gt;
&lt;h3 id="storage-setup"&gt;Storage Setup&lt;/h3&gt;
&lt;p&gt;Go to your Azure resource group, find the storage account you set up, and add a blob container.  This is not quite a folder, but kind of acts like one for our purposes.  I'll add one for &amp;quot;web&amp;quot;. Be sure to set your container to something other than Private. I set mine to Blob.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_storage_container.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_storage_container.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now I can select my container and upload the image to it. There are lots of client tools to upload, download, and manage your Azure storage files, like &lt;a href="https://www.cloudberrylab.com/explorer/microsoft-azure.aspx"&gt;CloudBerry Explorer for Microsoft Azure&lt;/a&gt;, which is free.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_storage_container_upload.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_storage_container_upload.png" /&gt;&lt;/p&gt;
&lt;p&gt;Once I have uploaded the image, I can click it and get its URL.  Open that URL to test that you can see the image. If not, check that you didn't make your container private. Also, be sure you are using the correct case. Calls to storage blobs are case sensitive. If you file is Image.jpg and request image.jpg (lowercase &amp;quot;I&amp;quot;), you'll get a 404. In my case, the image URL ends up as &lt;code&gt;https://teststorage19.blob.core.windows.net/web/Fall%20-%20Estes%20Elk.jpg&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you open Chrome Dev Tools and refresh the image, you can see it's being served over HTTP/2 already without being on a CDN.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/web_http2.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/web_http2.png" /&gt;&lt;/p&gt;
&lt;p&gt;Let's update the HTML to use that new URL and check that it's still using HTTP/2 when uploaded to the Azure App Service.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt;
    &amp;lt;title&amp;gt;HTTP/2 with Azure CDN&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;p&amp;gt;Here is an image of an elk in Rocky Mountain National Park.&amp;lt;/p&amp;gt;
    &amp;lt;img src=&amp;quot;https://teststorage19.blob.core.windows.net/web/Fall - Estes Elk.jpg&amp;quot; /&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I made this change and re-published the web app, and sure enough, it's served over HTTP/2.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/cdn_http2.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/cdn_http2.png" /&gt;&lt;/p&gt;
&lt;p&gt;Let's go one step further and serve the image from a CDN, instead of directly from the storage account.&lt;/p&gt;
&lt;h3 id="cdn-setup"&gt;CDN Setup&lt;/h3&gt;
&lt;p&gt;In Azure, open your CDN Endpoint. You should see the URLs for your storage account and your CDN that maps to your storage account.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_cdn_endpoint.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_cdn_endpoint.png" /&gt;&lt;/p&gt;
&lt;p&gt;Since all our content is in a storage container called &amp;quot;web&amp;quot; and that becomes part of the URL, we can make that a default path for the CDN Endpoint under Origin.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/azure_cdn_origin_path.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/azure_cdn_origin_path.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now we'll have URLs like this, using the CDN and skipping the /web/ folder in the URL:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://testcdn19.azureedge.net/Fall - Estes Elk.jpg&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;instead of:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://teststorage19.blob.core.windows.net/web/Fall - Estes Elk.jpg&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This change can take up to 90 minutes to propagate, so if you get 404s, that may be what's happening.&lt;/p&gt;
&lt;p&gt;Once you can browse to the image URL with your browser, replace that image source in the HTML markup and re-publish your web app to Azure.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt;
    &amp;lt;title&amp;gt;HTTP/2 with Azure CDN&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;p&amp;gt;Here is an image of an elk in Rocky Mountain National Park.&amp;lt;/p&amp;gt;
    &amp;lt;img src=&amp;quot;https://testcdn19.azureedge.net/Fall - Estes Elk.jpg&amp;quot; /&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you browse to it now, you can open Chrome Dev Tools and confirm the image is coming from the CDN and is using HTTP/2.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/web_http_final.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/web_http_final.png" /&gt;&lt;/p&gt;
</description>
      <pubDate>Sat, 03 Feb 2018 16:49:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/working-with-two-sets-of-eslint-rules-for-legacy-es5-and-modern-javascript-using-gulp</guid>
      <link>https://volaresoftware.com/nl/technical-posts/working-with-two-sets-of-eslint-rules-for-legacy-es5-and-modern-javascript-using-gulp</link>
      <title>Working with two sets of ESLint rules for legacy ES5 and modern JavaScript using Gulp</title>
      <description>&lt;p&gt;I've written before about &lt;a href="https://volaresoftware.com/en/technical-posts/working-with-the-latest-javascript-syntax-on-your-project-today"&gt;using file extensions to tell webpack and Babel which files are older-style ES5 syntax and which are newer-style JavaScript&lt;/a&gt;. What if you've got a project that has both, and you need to run &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; on the older, &lt;code&gt;*.js&lt;/code&gt; files as well as the new &lt;code&gt;*.es6&lt;/code&gt; files?&lt;/p&gt;
&lt;p&gt;You can run both in one task with &lt;a href="https://gulpjs.com/"&gt;Gulp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, set up separate ESLint &lt;a href="https://eslint.org/docs/rules/"&gt;rules&lt;/a&gt; files. These are usually &lt;code&gt;.eslintrc.json&lt;/code&gt; files, but since we need two sets of rules, create &lt;code&gt;.eslintrc.es5.json&lt;/code&gt; (for the older syntax rules) and &lt;code&gt;.eslintrc.es6.json&lt;/code&gt; (for the newer syntax rules).&lt;/p&gt;
&lt;p&gt;Then create Gulp task (&amp;quot;validate-es5&amp;quot;) to get a glob of the &lt;code&gt;*.js&lt;/code&gt; files and apply the rules in the &lt;code&gt;.eslintrc.es5.json&lt;/code&gt; rules config and a Gulp task (&amp;quot;validate-es6&amp;quot;) to get a glob of the &lt;code&gt;*.es6&lt;/code&gt; files and apply the rules in the &lt;code&gt;.eslintrc.es6.json&lt;/code&gt; rules:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const gulp = require(&amp;quot;gulp&amp;quot;);
const eslint = require(&amp;quot;gulp-eslint&amp;quot;);
const plumber = require(&amp;quot;gulp-plumber&amp;quot;);
const paths = {
    es6scripts: &amp;quot;Scripts/**/*.es6&amp;quot;,
    es5scripts: &amp;quot;Scripts/**/*.js&amp;quot;
};
const es5eslintGlob = [paths.es5scripts];
const es6eslintGlob = [paths.es6scripts];
 
 
gulp.task(&amp;quot;validate-es5&amp;quot;, () =&amp;gt;
    eslintPipeline(gulp.src(es5eslintGlob), &amp;quot;.eslintrc.es5.json&amp;quot;)
);
 
gulp.task(&amp;quot;validate-es6&amp;quot;, () =&amp;gt;
    eslintPipeline(gulp.src(es6eslintGlob), &amp;quot;.eslintrc.es6.json&amp;quot;)
);
 
function eslintPipeline(stream, rules) {
    return stream
        .pipe(plumber({
            errorHandler: error =&amp;gt; {
                console.log(error.message);
                console.log(error.toString());
            }
        }))
        .pipe(eslint(rules))
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, create a Gulp task to run both tasks named &amp;quot;watch&amp;quot; to run a watch on those files and execute ESLint with the correct rule set for each file extension when a file changes:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const print = require(&amp;quot;gulp-print&amp;quot;).default;
const watch = require(&amp;quot;gulp-watch&amp;quot;);
 
gulp.task(&amp;quot;watch&amp;quot;, () =&amp;gt; {    
    eslintPipeline(watch(es5eslintGlob)
        .pipe(print(filepath =&amp;gt; `ESLint (ES5): ${filepath}`)), &amp;quot;.eslintrc.es5.json&amp;quot;)
        .pipe(eslint.failOnError());
    eslintPipeline(watch(es6eslintGlob)
        .pipe(print(filepath =&amp;gt; `ESLint (ES6): ${filepath}`)), &amp;quot;.eslintrc.es6.json&amp;quot;)
        .pipe(eslint.failOnError());
});
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Tue, 05 Feb 2019 01:39:05 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/fix-for-weird-errors-in-mvc4-when-adding-a-new-area</guid>
      <link>https://volaresoftware.com/nl/technical-posts/fix-for-weird-errors-in-mvc4-when-adding-a-new-area</link>
      <title>Fix for weird errors in MVC4 when adding a new Area</title>
      <description>&lt;p&gt;MVC has let you add Areas to your web project for a couple versions now.  Areas help you group large chunks of code in your web app.  You can group along a technical axes (like &amp;quot;Api&amp;quot;) or a functional axes (like &amp;quot;Admin&amp;quot;).&lt;/p&gt;
&lt;h2 id="the-first-error"&gt;The first error&lt;/h2&gt;
&lt;p&gt;I created a new MVC4 project, added an area called &amp;quot;Test&amp;quot;, and browsed to the home page (http://localhost:59669).  Works!  Then I browse to the new area (http://localhost:59669/Test) and get this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/12/image_thumb_5.png" alt="https://cdn.volaresoftware.com/images/posts/2012/12/image_thumb_5.png" /&gt;&lt;/p&gt;
&lt;p&gt;What's going on with those underscores?  The error message shows the problem is in my Web.config, but not the application root one, the one under &lt;code&gt;/Areas/Test/Views/Web.config&lt;/code&gt;.  I open it in Visual Studio, and sure enough, underscores.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;configSections&amp;gt;
  &amp;lt;sectionGroup name=&amp;quot;system.web.webPages.razor&amp;quot; type=&amp;quot;System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=__WebPagesVersion__.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot;&amp;gt;
    &amp;lt;section name=&amp;quot;host&amp;quot; type=&amp;quot;System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=__WebPagesVersion__.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot; requirePermission=&amp;quot;false&amp;quot; /&amp;gt;
    &amp;lt;section name=&amp;quot;pages&amp;quot; type=&amp;quot;System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=__WebPagesVersion__.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot; requirePermission=&amp;quot;false&amp;quot; /&amp;gt;
  &amp;lt;/sectionGroup&amp;gt;
&amp;lt;/configSections&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I compare that to the other &lt;code&gt;Web.config&lt;/code&gt; under the root &lt;code&gt;/Views/Web.config&lt;/code&gt;, and copy and paste those values in.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;configSections&amp;gt;
  &amp;lt;sectionGroup name=&amp;quot;system.web.webPages.razor&amp;quot; type=&amp;quot;System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot;&amp;gt;
    &amp;lt;section name=&amp;quot;host&amp;quot; type=&amp;quot;System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot; requirePermission=&amp;quot;false&amp;quot; /&amp;gt;
    &amp;lt;section name=&amp;quot;pages&amp;quot; type=&amp;quot;System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot; requirePermission=&amp;quot;false&amp;quot; /&amp;gt;
  &amp;lt;/sectionGroup&amp;gt;
&amp;lt;/configSections&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, I'm assuming there is a bug in the &amp;quot;Add Area&amp;quot; template.  So let's build and refresh the browser and it should work now, right?&lt;/p&gt;
&lt;h2 id="the-second-error"&gt;The second error&lt;/h2&gt;
&lt;p&gt;Of course not.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/12/image_thumb_6.png" alt="https://cdn.volaresoftware.com/images/posts/2012/12/image_thumb_6.png" /&gt;&lt;/p&gt;
&lt;p&gt;Hmm.  Lots of details in that stack trace, but not much to go on here.  I checked my route registration code and checked my area registration code.  Both looked fine:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web.Mvc;
using System.Web.Routing;
&lt;p&gt;namespace MvcApplication2.App_Start
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute(&amp;quot;.axd/{*pathInfo}&amp;quot;);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        routes.MapRoute(
            name: &amp;amp;quot;Default&amp;amp;quot;,
            url: &amp;amp;quot;{controller}/{action}/{id}&amp;amp;quot;,
            defaults: new {controller = &amp;amp;quot;Home&amp;amp;quot;, action = &amp;amp;quot;Index&amp;amp;quot;, id = UrlParameter.Optional},
            namespaces: new[] { &amp;amp;quot;MvcApplication2.Controllers&amp;amp;quot; }
            );
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;using System.Web.Mvc;&lt;/p&gt;
&lt;p&gt;namespace MvcApplication2.Areas.Test
{
public class TestAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return &amp;quot;Test&amp;quot;; }
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            name: &amp;amp;quot;Test_default&amp;amp;quot;,
            url: &amp;amp;quot;Test/{controller}/{action}/{id}&amp;amp;quot;,
            defaults: new {action = &amp;amp;quot;Index&amp;amp;quot;, id = UrlParameter.Optional},
            namespaces: new[] {&amp;amp;quot;MvcApplication2.Areas.Test.Controllers&amp;amp;quot;}
            );
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I also added the namespaces to the area (the last parameter above) to help the routing engine find the right controller.  That looked fine, too.&lt;/p&gt;
&lt;p&gt;The error message was about a bad assembly (&amp;quot;The given assembly name or codebase was invalid.&amp;quot;).  Maybe something didn't get built or loaded right ?  I tried a Clean and Rebuild.  No luck.&lt;/p&gt;
&lt;p&gt;Maybe ASP.NET temp files were cached?  Let's clear browser cache, close and re-open the browser, close and re-open Visual Studio, restart IIS Express, and see if that helps….and no, no luck.&lt;/p&gt;
&lt;h2 id="the-solution"&gt;The solution&lt;/h2&gt;
&lt;p&gt;I was running out of ideas, but since the first problem was the &lt;code&gt;Web.config&lt;/code&gt;, maybe this was, too.  I opened up the generated &lt;code&gt;Web.config&lt;/code&gt; under &lt;code&gt;/Areas/Test/Views/Web.config&lt;/code&gt; again and compared it to the one under the root &lt;code&gt;/Views/Web.config&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Sure enough, more freaking underscores.  I just copied ALL the values from the root view's &lt;code&gt;Web.config&lt;/code&gt; into the areas one, built, refreshed, and finally got the areas showing up.&lt;/p&gt;
&lt;p&gt;Maybe I have a wacky install.  Maybe I got hold of some bad pre-release NuGet package.  But it seems there is a template bug here when adding Areas to an MVC project.  I have the Fall Update on Visual Studio 2012, so my About screen looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/12/image_thumb_8.png" alt="https://cdn.volaresoftware.com/images/posts/2012/12/image_thumb_8.png" /&gt;&lt;/p&gt;
&lt;p&gt;I'm writing this up in the hopes that I save someone else some time.  If you have suggestions on where I got an underscore happy template, please let me know in the comments below.&lt;/p&gt;
</description>
      <pubDate>Thu, 13 Dec 2012 01:39:38 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/running-specflow-and-watin-tests-with-teamcity-and-appharbor</guid>
      <link>https://volaresoftware.com/nl/technical-posts/running-specflow-and-watin-tests-with-teamcity-and-appharbor</link>
      <title>Running SpecFlow and WatiN tests with TeamCity and AppHarbor</title>
      <description>&lt;p&gt;If you're using SpecFlow and WatiN to automate your web testing, things work great on localhost, but tend to fall apart on the continuous integration server.  It's a &amp;quot;chicken or the egg&amp;quot; paradox.  If the new code hasn't been deployed yet, it can't be externally tested with WatiN, but it shouldn't be deployed until all the tests have passed.  What are you supposed to do?&lt;/p&gt;
&lt;h2 id="teamcity"&gt;TeamCity&lt;/h2&gt;
&lt;p&gt;If your SpecFlow and WatiN tests are in their own assembly (something like &lt;code&gt;MyProject.AcceptanceTests.dll&lt;/code&gt;), and you're using TeamCity, it's easy to run your unit tests and integration tests, then deploy the code to a web server, then run your acceptance tests in a separate build step.  It's just a matter of breaking up the steps and designating which test assemblies will be run at which time.&lt;/p&gt;
&lt;p&gt;This step in the screen shot below is running the unit tests and integration tests.  A separate, later step will run the tests in the &lt;code&gt;**\*AcceptanceTests.dll&lt;/code&gt; assembly after the code has been deployed to the web server.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2011/6/image_9.png" alt="image_9.png" /&gt;&lt;/p&gt;
&lt;h2 id="appharbor"&gt;AppHarbor&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2011/6/image_10.png" alt="image_10.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you're using AppHarbor to run your tests on check in with &lt;code&gt;git push appharbor master&lt;/code&gt;, (and you should - it's super easy), you don't want to run your web tests until the code is deployed, but AppHarbor doesn't deploy &lt;strong&gt;anything&lt;/strong&gt; until all the tests pass.&lt;/p&gt;
&lt;p&gt;What we want is for AppHarbor to ignore the web automation tests until the code is deployed.  AppHarbor flips a &lt;code&gt;*.config&lt;/code&gt; &lt;code&gt;appSetting&lt;/code&gt; key named &amp;quot;Environment&amp;quot; to &amp;quot;Test&amp;quot; when it's testing and to &amp;quot;Release&amp;quot; when the code is deployed.  So while your tests are running, your &lt;code&gt;App.config&lt;/code&gt; in your test project should look something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;appSettings&amp;gt;
  &amp;lt;add key=&amp;quot;Environment&amp;quot; value=&amp;quot;Test&amp;quot;/&amp;gt;
&amp;lt;/appSettings&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can take advantage of this &lt;code&gt;appSetting&lt;/code&gt; test runner change to tell SpecFlow to ignore this set of tests, which allows AppHarbor to continue running other tests and deploying the code.&lt;/p&gt;
&lt;p&gt;This is not be the most elegant way to do this, but I got this working today:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[Binding]
public class MyStepDefinition
{
    [BeforeFeature]
    public void BeforeFeature()
    {
        if (ConfigurationManager.AppSettings[&amp;quot;Environment&amp;quot;] == &amp;quot;Test&amp;quot;)
            Assert.Ignore();
    }
&lt;pre&gt;&lt;code&gt;// Rest of step definition code...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;BeforeFeature&lt;/code&gt; attribute tells the SpecFlow test runner to execute that method before each feature.  With a quick check on the Environment &lt;code&gt;appSetting&lt;/code&gt; value, we can tell AppHarbor to ignore this test and continue processing.  This will ignore all scenarios in all feature files.  Since all my scenarios are web automation tests, that works for me.&lt;/p&gt;
&lt;p&gt;But what if you have some scenarios that rely on web automation testing and others that don't?  A more targeted approach would be to set a SpecFlow tag, like @web over the SpecFlow scenarios that require web automation testing to pass.  Then in the [BeforeScenario(&amp;quot;web&amp;quot;)] handlers for that tag, you could set Assert.Ignore to skip those scenarios while executing all other scenarios.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[BeforeScenario(&amp;quot;web&amp;quot;)]
public void BeforeScenario()
{
    if (ConfigurationManager.AppSettings[&amp;quot;Environment&amp;quot;] == &amp;quot;Test&amp;quot;)
        Assert.Ignore();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once your non-web automation tests have passed and the code is deployed, you can point your local test runner at the AppHarbor URL and test against the newly deployed web app.&lt;/p&gt;
</description>
      <pubDate>Fri, 03 Jun 2011 00:40:12 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/sharing-data-from-within-your-windows-8-app-using-javascript</guid>
      <link>https://volaresoftware.com/nl/technical-posts/sharing-data-from-within-your-windows-8-app-using-javascript</link>
      <title>Sharing data from within your Windows 8 app using JavaScript</title>
      <description>&lt;p&gt;One of the nifty features of Windows 8 is the ability of the OS to share data between apps.  For instance, if I open the Weather app, click Windows + H, I get the Share bar that let's me send the weather forecast to the Mail, Tweetro, or People apps.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/image_21.png" alt="image_21.png" /&gt;&lt;/p&gt;
&lt;p&gt;Most sharing apps take relevant text, HTML, and links, and prepare a draft email, tweet, etc. for you to send.  Here is the HTML the Mail app prepares to send from the Weather app:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/image_22.png" alt="image_22.png" /&gt;&lt;/p&gt;
&lt;p&gt;This post is about how to do the same thing from within your app.&lt;/p&gt;
&lt;h2 id="what-do-you-want-to-share"&gt;What do you want to share?&lt;/h2&gt;
&lt;p&gt;You can share text, HTML, images, files, etc.  I'm going to share text with my current location information from an altitude app.  This is what we're going for:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/image_23.png" alt="image_23.png" /&gt;&lt;/p&gt;
&lt;p&gt;It's just plain text, but &lt;a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh771179.aspx"&gt;you can get fancier&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="listen-for-the-sharing-event"&gt;Listen for the sharing event&lt;/h2&gt;
&lt;p&gt;The first thing you'll do in your code is listen for Windows 8 telling you the user wants to share something.  Wire up the sharing event listener in your &amp;quot;ready&amp;quot; code, and unhook it in your &amp;quot;unload&amp;quot; code like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;var dataTransferManager;
&lt;p&gt;var page = WinJS.UI.Pages.define(&amp;quot;/default.html&amp;quot;, {
ready: function(element, options) {
dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
dataTransferManager.addEventListener(&amp;quot;datarequested&amp;quot;, onSharingRequested);
},
unload: function() {
dataTransferManager.removeEventListener(&amp;quot;datarequested&amp;quot;, onSharingRequested);
}
});
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="build-up-the-sharing-payload"&gt;Build up the Sharing payload&lt;/h2&gt;
&lt;p&gt;Now we've got a function called &amp;quot;onSharingRequested&amp;quot; that will run when the user starts sharing within our app, but we need to write the code in that event/function to build up the text to share.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;function onSharingRequested(e) {
    var request = e.request;
    request.data.properties.title = &amp;quot;My current altitude and location&amp;quot;;
    request.data.setText(&amp;quot;My current altitude and location are Altitude: &amp;quot; + location.altitude + &amp;quot; &amp;quot; + location.altitudeUnits +
        &amp;quot;, Latitude: &amp;quot; + location.latitudeFormatted + &amp;quot;, Longitude: &amp;quot; + location.longitudeFormatted +
        &amp;quot;, Accuracy: &amp;quot; + location.accuracy + &amp;quot;, Near: &amp;quot; + location.near);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You set properties on the passed in request object, like the title and the text shown here.  The title must be set or sharing won't work.&lt;/p&gt;
&lt;h2 id="adding-a-button-to-start-sharing"&gt;Adding a button to start Sharing&lt;/h2&gt;
&lt;p&gt;Sharing data between apps is something people will probably get used to eventually, but if you want to be sure the users of your app know they can share, make a button that does that same thing as Windows + H or a swipe from the right on a tablet.&lt;/p&gt;
&lt;p&gt;On your button click event, call the showShareUI method of the DataTransferManager like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;function onSharingButtonClick() {
    Windows.ApplicationModel.DataTransfer.DataTransferManager.showShareUI();
}
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Wed, 17 Oct 2012 00:39:51 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/validation-frameworks-in-aspnet-mvc</guid>
      <link>https://volaresoftware.com/nl/technical-posts/validation-frameworks-in-aspnet-mvc</link>
      <title>Validation frameworks in ASP.NET MVC</title>
      <description>&lt;p&gt;There are plenty of validation frameworks out there.  I've worked with &lt;a href="http://nhforge.org/wikis/validator/nhibernate-validator-1-0-0-documentation.aspx"&gt;NHibernate Validators&lt;/a&gt;, Microsoft's &lt;a href="http://msdn.microsoft.com/en-us/library/dd140112.aspx"&gt;Enterprise Application Blocks&lt;/a&gt;, and now &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt;.  They primarily work by adding attributes to the properties in the class you want to validate.&lt;/p&gt;
&lt;h2 id="how-are-they-different"&gt;How are they different?&lt;/h2&gt;
&lt;p&gt;Not very.  The biggest difference between them is their syntax.  I guess the Validation Blocks from Microsoft's P&amp;amp;P group have a lot of configuration options, but I haven't needed that on a project.  The most prominent differences are in the attributes themselves.&lt;/p&gt;
&lt;p&gt;You can probably make a case for Data Annotations having a slight advantage since it's going to be in the .NET base-class libraries.  Easier to deal with assemblies installed in the GAC instead of the ones you have to drag around for each deployment.&lt;/p&gt;
&lt;h2 id="how-do-you-integrate-them-with-mvc"&gt;How do you integrate them with MVC?&lt;/h2&gt;
&lt;p&gt;Each of these frameworks can be integrated with ASP.NET MVC.  But the best validation call is one you don't have to explicitly make.  Huh?&lt;/p&gt;
&lt;p&gt;It's OK to call &lt;code&gt;MyClass.IsValid()&lt;/code&gt; in a controller action, but if you can avoid it, I think you're better off.  Otherwise, what happens if you &lt;strong&gt;forget&lt;/strong&gt; to call it?&lt;/p&gt;
&lt;p&gt;Instead, use a model binder that invokes the validation framework for you.  This is how I am using the Data Annotations model binder with the MVC framework:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;ModelBinders.Binders.DefaultBinder = new Microsoft.Web.Mvc.DataAnnotations.DataAnnotationsModelBinder();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now this guy will intercept calls to your controller actions and reject invalid incoming view models.  Here is a &lt;a href="http://www.asp.net/learn/mvc/tutorial-39-cs.aspx"&gt;simple tutorial for using Data Annotations&lt;/a&gt; that goes into more detail.&lt;/p&gt;
&lt;h2 id="how-do-you-lay-this-out-in-the-solution"&gt;How do you lay this out in the solution?&lt;/h2&gt;
&lt;p&gt;I have an Application Services layer that my MVC layer calls into.  My controllers have constructors with an interface to an application service injected into them.  My IoC container decides which concrete version of this application service interface to use at runtime.&lt;/p&gt;
&lt;p&gt;Next, my Application Service layer has a DTO folder that holds all the DTOs (property-only classes) my views need in my MVC app.  These are &lt;strong&gt;not&lt;/strong&gt; my domain entities.  There might be a lot of overlap with those domain entities, but these DTOs are &lt;strong&gt;just&lt;/strong&gt; there for communication between the UI layer and Application Services layer.  These DTOs are where I put my validation attributes.&lt;/p&gt;
&lt;p&gt;So now I've got views that are tightly bound to the DTOs, which are owned in the Application Services layer.  This allows strong typing of the view so I can use the DTO's properties as my view's model.  This is handy for the Html Helpers to get design-time IntelliSense and compile-time checking.&lt;/p&gt;
&lt;h2 id="what-else-can-you-do"&gt;What else can you do?&lt;/h2&gt;
&lt;p&gt;I haven't spent a lot of time looking into it, but &lt;a href="http://xval.codeplex.com/"&gt;xVal&lt;/a&gt; looks pretty strong for client side AND server side validation using Data Annotations and a couple other validation frameworks.  It also lets you validate your business rules in your domain and throw an exception.  I need to check into this more, because that sounds like the validation holy grail for validation to me: getting UI validation and business rule validation into a common format.&lt;/p&gt;
</description>
      <pubDate>Thu, 17 Sep 2009 00:41:23 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/the-case-for-tdd</guid>
      <link>https://volaresoftware.com/nl/technical-posts/the-case-for-tdd</link>
      <title>The case for TDD</title>
      <description>&lt;p&gt;TDD is hard. It sounds like it wouldn't be hard. It's just a little test. The code is the hard part, right?  But it's &lt;strong&gt;really&lt;/strong&gt; hard to do it well. I struggle with it plenty and I know my way around C# and OO pretty well.&lt;/p&gt;
&lt;p&gt;There better be a payoff for this bass-ackwards way of coding.  It takes a while to get there, but I can see the light at the end of the tunnel in my own development.  Here's where I've seen my code improve as I've moved toward TDD:&lt;/p&gt;
&lt;h2 id="focusness"&gt;Focusness&lt;/h2&gt;
&lt;p&gt;You focus on the behavior of your code instead of the implementation.  You don't start by thinking of tables, classes, and properties (or in my case, try hard not to).  You start off thinking of the business requirements and roles.  User stories are popular because they push you into restating the requirements in context: &amp;quot;As a (some role)...I want to (do something)...so that (some business value)&amp;quot;.  The first two chunks of this can guide your test creation.  You can write methods that cover these scenarios.&lt;/p&gt;
&lt;p&gt;If you're doing it the RED-GREEN-REFACTOR way, you'll write a test and just enough for the code to compile, get the test to pass with the minimum amount of code possible.  Finally, you can go back and clean up what you aren't proud of from your first effort, then run the test again.  You get to keep repeating that until you are happy with the code and that the requirement/story is met and the user accepts it.&lt;/p&gt;
&lt;p&gt;Then you &lt;strong&gt;STOP&lt;/strong&gt;.  That's the fourth step you don't see in the pretty RED-GREEN-REFACTOR icon.  If you don't stop, you loose your focus on the functionality and you start trying to gold-plate the code.  Which can lead to...&lt;/p&gt;
&lt;h2 id="dude-you-know-what-would-make-this-really-cool"&gt;Dude, you know what would make this REALLY cool?&lt;/h2&gt;
&lt;p&gt;You're getting paid to write software to meet the requirements.  If you going beyond that, be careful who you're doing the coding for.  If it's the business, and you're glad to show them how much time you've spent on it, you might be justified in doing it.  But if you're coding it for yourself, do it on your own time.&lt;/p&gt;
&lt;p&gt;Unfortunately, people who are drawn to programming are often tinkerers and bit-twiddlers.  I appreciate having a framework for my development that keeps me on task, because I am easily distracted by grand visions of what I might be able to code into the app.  There is no code we couldn't tweak a little and add this new cool pattern or just-learned technique to.  TDD forces you to go directly to the requirements, not the technology.&lt;/p&gt;
&lt;h2 id="solid-code"&gt;SOLID code&lt;/h2&gt;
&lt;p&gt;The more you move toward TDD, the more little classes you have with giant names.  Same thing with methods.  There are tons, they are very short (one screen or so max), and they have long names.  This is progress?&lt;/p&gt;
&lt;p&gt;Yes, I think it is because of the &lt;a href="https://en.wikipedia.org/wiki/SOLID"&gt;SOLID principals&lt;/a&gt;. SOLID is a horrible acronym of acronyms, but it can help you keep some object-oriented principals in mind. I'll go over it and how I've tried to learn it in more depth in a future post, but &lt;a href="http://www.lostechies.com/blogs/chad_myers/archive/2008/03/07/pablo-s-topic-of-the-month-march-solid-principles.aspx"&gt;the guys at Los Techies covered SOLID in depth&lt;/a&gt; already.  So the side effect of decoupled code is you have lots of little files that just do one little thing.  It took me a while to get over this and the file bloat in the project, but I'm at peace with it now. The payoff is that I am using more SOLID principals than I was before, and that's a good thing.&lt;/p&gt;
&lt;h2 id="oh-yeah-you-get-some-tests-too"&gt;Oh yeah, you get some tests, too&lt;/h2&gt;
&lt;p&gt;It's been said before, but TDD is kind of misnamed.  Yes, you start with the test, but that's not the most important thing.  The most important thing is the requirement focus and the way it drives you toward a more loosely coupled design.  But it's pretty fun to see that screen light up with green checks or circles after you've made a change.&lt;/p&gt;
&lt;p&gt;The real value of the tests themselves is that today's unit tests become tomorrow's regression tests.  You won't remember why you wrote the code last week, but you don't have to.  The tests can also serve as mini-documentation of the requirements if you write the test names in a consistent way.  There are BDD frameworks that let you spit out some HTML to do exactly this.&lt;/p&gt;
&lt;h2 id="ruthless-refactoring"&gt;Ruthless Refactoring&lt;/h2&gt;
&lt;p&gt;All this adds up to something of a safety net for refactoring. Think of the confidence you can have changing the code, even if it's another team members code.  Or if (gasp!) they make changes to your code.  It's nice to know your code still works.&lt;/p&gt;
&lt;p&gt;If you write the tests first, you know you've got the &amp;quot;happy path&amp;quot; covered on your code.  That's the one you started with.  You can write a few more tests to cover the likely deviations from that happy path, but when you get to the weird stuff (what if you order $999,999,999,999 in widgets?), call it good and move on.&lt;/p&gt;
</description>
      <pubDate>Fri, 17 Jul 2009 11:39:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/showing-and-saving-user-settings-in-a-windows-8-app-with-javascript</guid>
      <link>https://volaresoftware.com/nl/technical-posts/showing-and-saving-user-settings-in-a-windows-8-app-with-javascript</link>
      <title>Showing and saving user settings in a Windows 8 app with JavaScript</title>
      <description>&lt;p&gt;If your Windows 8 app has user-based settings, you need a place to show those values, let users change them, and save them for later use.  Sometimes these are called preferences, but in Windows 8, they are called &amp;quot;settings&amp;quot;.&lt;/p&gt;
&lt;p&gt;You can see and set your settings in a Windows 8 app with Windows + I.  You'll pull up a fly out dialog from the right like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/image_24.png" alt="image_24.png" /&gt;&lt;/p&gt;
&lt;p&gt;Clicking on the &amp;quot;Options&amp;quot; choice opens up the settings for the app:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/image_25.png" alt="image_25.png" /&gt;&lt;/p&gt;
&lt;p&gt;Before you dive in and do this with your app, get acquainted with the &lt;a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh770544.aspx"&gt;Windows 8 app settings guidelines&lt;/a&gt;.  Here's what I did for mine.&lt;/p&gt;
&lt;h2 id="create-the-options-view"&gt;Create the Options view&lt;/h2&gt;
&lt;p&gt;Here is my &lt;code&gt;options.html&lt;/code&gt; file.  Most of this is plain old HTML.  Note the ID of the outer div is &amp;quot;options&amp;quot;.  This could be named anything, but keep that ID in mind since we'll need it later.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt;
    &amp;lt;title&amp;gt;Options&amp;lt;/title&amp;gt;
&lt;pre&gt;&lt;code&gt;&amp;amp;lt;!-- WinJS references --&amp;amp;gt;
&amp;amp;lt;link href=&amp;amp;quot;https://volaresoftware.com/blog/Microsoft.WinJS.1.0/css/ui-light.css&amp;amp;quot; rel=&amp;amp;quot;stylesheet&amp;amp;quot; /&amp;amp;gt;
&amp;amp;lt;script src=&amp;amp;quot;//Microsoft.WinJS.1.0/js/base.js&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
&amp;amp;lt;script src=&amp;amp;quot;//Microsoft.WinJS.1.0/js/ui.js&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;

&amp;amp;lt;!-- App references --&amp;amp;gt;
&amp;amp;lt;link href=&amp;amp;quot;https://volaresoftware.com/blog/css/settings.css&amp;amp;quot; rel=&amp;amp;quot;stylesheet&amp;amp;quot; /&amp;amp;gt;
&amp;amp;lt;script src=&amp;amp;quot;/js/app/options.js&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div id=&amp;quot;options&amp;quot; class=&amp;quot;win-settingsflyout&amp;quot; data-win-control=&amp;quot;WinJS.UI.SettingsFlyout&amp;quot; data-win-options=&amp;quot;{ width:'narrow' }&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;win-header&amp;quot;&amp;gt;
&amp;lt;button id=&amp;quot;backButton&amp;quot; class=&amp;quot;win-backbutton&amp;quot; aria-label=&amp;quot;Back&amp;quot; onclick=&amp;quot;WinJS.UI.SettingsFlyout.show()&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;
&amp;lt;div class=&amp;quot;win-label&amp;quot;&amp;gt;Options&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;win-content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;win-settings-section&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;label&amp;gt;Use feet or meters&amp;lt;/label&amp;gt;
&amp;lt;label&amp;gt;
&amp;lt;input id=&amp;quot;feet&amp;quot; name=&amp;quot;feetOrMeters&amp;quot; type=&amp;quot;radio&amp;quot; value=&amp;quot;Feet&amp;quot; checked /&amp;gt;Feet
&amp;lt;/label&amp;gt;
&amp;lt;label&amp;gt;
&amp;lt;input id=&amp;quot;meters&amp;quot; name=&amp;quot;feetOrMeters&amp;quot; type=&amp;quot;radio&amp;quot; value=&amp;quot;Meters&amp;quot; /&amp;gt;Meters
&amp;lt;/label&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;label for=&amp;quot;refreshInterval&amp;quot;&amp;gt;Refresh interval in minutes&amp;lt;/label&amp;gt;
&amp;lt;input id=&amp;quot;refreshInterval&amp;quot; name=&amp;quot;refreshInterval&amp;quot; type=&amp;quot;range&amp;quot; min=&amp;quot;0&amp;quot; max=&amp;quot;15&amp;quot; value=&amp;quot;1&amp;quot; /&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
&amp;lt;label for=&amp;quot;movementThreshold&amp;quot;&amp;gt;Movement threshold in feet&amp;lt;/label&amp;gt;
&amp;lt;input id=&amp;quot;movementThreshold&amp;quot; name=&amp;quot;movementThreshold&amp;quot; type=&amp;quot;range&amp;quot; min=&amp;quot;0&amp;quot; max=&amp;quot;100&amp;quot; value=&amp;quot;50&amp;quot; /&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The CSS classes may not be familiar, but these are coming from the Windows 8 SDK CSS (&lt;code&gt;ui-light.css&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The interesting parts are 1) there is no form tag or submit button (we'll see the JavaScript below that works with these values), 2) the data-win-control stuff in the top level div,&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div id=&amp;quot;options&amp;quot; class=&amp;quot;win-settingsflyout&amp;quot; data-win-control=&amp;quot;WinJS.UI.SettingsFlyout&amp;quot; data-win-options=&amp;quot;{ width:'narrow' }&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and 3) the onclick event for the back button that calls WinJS.UI.SettingsFlyout.show().&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;button id=&amp;quot;backButton&amp;quot; class=&amp;quot;win-backbutton&amp;quot; aria-label=&amp;quot;Back&amp;quot; onclick=&amp;quot;WinJS.UI.SettingsFlyout.show()&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The WinJS area we're working with here is the &lt;code&gt;SettingsFlyout&lt;/code&gt;, and the &lt;code&gt;show()&lt;/code&gt; and &lt;code&gt;hide()&lt;/code&gt; methods display it and move it out of the way.&lt;/p&gt;
&lt;p&gt;In modern web development, it's a venial sin to put JavaScript code in the onclick event of a button.  We usually aim for unobtrusive JavaScript where all the events are wired up in JavaScript and the HTML just does the layout.  I think that's a good practice, but for a back button like this, it makes the JavaScript more cluttered to have a tangential concern shoved in there.  So take your pick on where you put your onclick event – the button itself or the JavaScript file.&lt;/p&gt;
&lt;h2 id="open-the-options-view"&gt;Open the Options view&lt;/h2&gt;
&lt;p&gt;Now that we've got lovely labels and inputs to show in the Settings pane, we're ready to show it off.  Add the following to your default.js file:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;app.onsettings = function(e) {
    e.detail.applicationcommands = {
        &amp;quot;options&amp;quot;: {title: &amp;quot;Options&amp;quot;, href: &amp;quot;/pages/settings/options.html&amp;quot;},
    };
    WinJS.UI.SettingsFlyout.populateSettings(e);
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code will listen for the application's onsettings event (the &amp;quot;app&amp;quot; variable here = &lt;code&gt;WinJS.Application&lt;/code&gt;) and open the &lt;code&gt;options.html&lt;/code&gt; file in the href above.  The title is what you want the user to see on the app's Settings pane.  Clicking it will open your view where they can change values.  The &amp;quot;options&amp;quot; part on the left side is the ID of the div it will look for in the options.html file.&lt;/p&gt;
&lt;p&gt;At this point, you should be able to run your app and type Windows + I and see the app's settings pane, then click Options and see your app's options and the options.html input controls.  Nothing will be reading or writing any data yet, so let's do that next.&lt;/p&gt;
&lt;h2 id="save-and-recall-user-settings-for-your-app"&gt;Save and recall user settings for your app&lt;/h2&gt;
&lt;p&gt;There are &lt;a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx"&gt;three built-in storage areas for your Windows 8 app&lt;/a&gt;:  local storage, roaming storage, and temporary storage.  You can  also use &lt;a href="http://msdn.microsoft.com/en-us/library/live/hh826521.aspx"&gt;SkyDrive&lt;/a&gt;, &lt;a href="https://www.windowsazure.com/en-us/develop/mobile/"&gt;Windows Azure Mobile Services&lt;/a&gt;, or your own homemade JSON API that reads and writes to your own database.&lt;/p&gt;
&lt;p&gt;For app settings, I think roaming makes the most sense.  Users will expect your app to remember their settings across different devices, and that's what roaming provides with no extra work on your part.  The real difference between roaming and local you have to consider is, roaming storage is limited to 100k and can't hold binary data. If that won't work for your app, look into local storage, SkyDrive for files or photos, or Azure Mobile Services for structured data.&lt;/p&gt;
&lt;p&gt;Here's the &lt;code&gt;options.js&lt;/code&gt; file that pulls values from options.html and reads and writes values from the inputs:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;(function() {
    &amp;quot;use strict&amp;quot;;
&lt;pre&gt;&lt;code&gt;var appData = Windows.Storage.ApplicationData.current.roamingSettings;

WinJS.UI.Pages.define(&amp;amp;quot;/pages/settings/options.html&amp;amp;quot;, {
    // This function is called whenever a user navigates to this page. It
    // populates the page elements with the app's data.
    ready: function (element, options) {
        var feetRadio = document.getElementById(&amp;amp;quot;feet&amp;amp;quot;),
            metersRadio = document.getElementById(&amp;amp;quot;meters&amp;amp;quot;),
            refreshIntervalRange = document.getElementById(&amp;amp;quot;refreshInterval&amp;amp;quot;),
            movementThresholdRange = document.getElementById(&amp;amp;quot;movementThreshold&amp;amp;quot;);

        // Set settings to existing values
        if (appData.values.size &amp;amp;gt; 0) {
            if (appData.values[&amp;amp;quot;feetOrMeters&amp;amp;quot;]) {
                setFeetOrMetersValue();
            }
            if (appData.values[&amp;amp;quot;refreshInterval&amp;amp;quot;]) {
                refreshIntervalRange.value = appData.values[&amp;amp;quot;refreshInterval&amp;amp;quot;];
            }
            if (appData.values[&amp;amp;quot;movementThresholdInFeet&amp;amp;quot;]) {
                movementThresholdRange.value = appData.values[&amp;amp;quot;movementThresholdInFeet&amp;amp;quot;];
            }
        }

        // Wire up on change events for settings controls
        feetRadio.onchange = function () {
            appData.values[&amp;amp;quot;feetOrMeters&amp;amp;quot;] = getFeetOrMetersValue();
        };
        metersRadio.onchange = function () {
            appData.values[&amp;amp;quot;feetOrMeters&amp;amp;quot;] = getFeetOrMetersValue();
        };
        refreshIntervalRange.onchange = function() {
            appData.values[&amp;amp;quot;refreshInterval&amp;amp;quot;] = refreshIntervalRange.value;
        };
        movementThresholdRange.onchange = function() {
            appData.values[&amp;amp;quot;movementThresholdInFeet&amp;amp;quot;] = movementThresholdRange.value;
        };
    },

    unload: function() {
        // Respond to navigations away from this page.
    },

    updateLayout: function(element, viewState, lastViewState) {
        // Respond to changes in viewState.
    }
});

function getFeetOrMetersValue() {
    var feetOrMetersRadio = document.getElementsByName(&amp;amp;quot;feetOrMeters&amp;amp;quot;);
    for (var i = 0; i &amp;amp;lt; feetOrMetersRadio.length; i++) {
        if (feetOrMetersRadio[i].checked) {
            return feetOrMetersRadio[i].value;
        }
    }
}

function setFeetOrMetersValue() {
    var feetOrMetersRadio = document.getElementsByName(&amp;amp;quot;feetOrMeters&amp;amp;quot;);
    for (var i = 0; i &amp;amp;lt; feetOrMetersRadio.length; i++) {
        if (feetOrMetersRadio[i].value === appData.values[&amp;amp;quot;feetOrMeters&amp;amp;quot;]) {
            feetOrMetersRadio[i].checked = true;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;})();
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I'm using the &lt;code&gt;Windows.Storage.ApplicationData.current.roamingSettings&lt;/code&gt; (shortened to the appData variable) to read and write from roaming settings with the syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;appData.values[&amp;quot;theKey&amp;quot;] = theValue;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's a key value store, so if you've worked with cookies in the past, this will seem familiar.&lt;/p&gt;
&lt;p&gt;The existing values (if there are any) are pushed into the input controls.  Next, the onchange events on the options.html inputs are wired up to write the new values.  You may also have other things you have to do in your app when the user changes a setting value, like redraw or hide something, etc.&lt;/p&gt;
</description>
      <pubDate>Tue, 23 Oct 2012 00:39:49 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/push-your-logic-to-the-core</guid>
      <link>https://volaresoftware.com/nl/technical-posts/push-your-logic-to-the-core</link>
      <title>Push your logic to the core</title>
      <description>&lt;h2 id="creeping-logic"&gt;Creeping logic&lt;/h2&gt;
&lt;p&gt;Developers struggle with where to put their business logic.  We all know at an intellectual level that we should be keeping business rules and logic in some kind of a business layer, but I don't see it in practice that often.  I do see a lot of business layers that turn around and call data layers.  There's often nothing business-y about them.&lt;/p&gt;
&lt;p&gt;Instead, the logic is sprinkled throughout the other layers, sometimes to take advantage of a technology, sometimes because of the strengths of the developer who wrote the code.&lt;/p&gt;
&lt;p&gt;Validation controls in ASP.NET Web Forms are an example of business logic in the UI layer.  Another is an ASP.NET Web Forms code behind event that calculate discounts for preferred customers on Page_Load.&lt;/p&gt;
&lt;p&gt;ASP.NET MVC isn't immune from this either, although the validation logic story is better with Data Annotations letting validation rules flow up to the UI.  Controller actions can be mistreated just like code-behind and often contain more business logic than they should.&lt;/p&gt;
&lt;p&gt;And putting more logic in stored procs doesn't make your app dev teams more agile.  It makes the data team the bottleneck for logic changes.&lt;/p&gt;
&lt;h2 id="journey-to-the-center-of-the-app"&gt;Journey to the Center of the App&lt;/h2&gt;
&lt;p&gt;A better approach is to lift that logic out of those layers and put it in your business/domain/core layer in C# &lt;a href="http://en.wikipedia.org/wiki/Plain_Old_CLR_Object"&gt;POCOs&lt;/a&gt;.  In many apps, this logic is what makes the app worthwhile.  Sometimes, it's what gives the company a competitive advantage.  It should be clear, expressive, and long lived code.  It should not be coupled to any particular technology.&lt;/p&gt;
&lt;p&gt;These can be tricky changes to make once an app is partly finished or already up and working in production.  There can be a lot of refactoring.  But the effort can pay off in making the code more clear to anyone working on it and letting you make complex changes much faster because the logic is centralized and expressive.&lt;/p&gt;
&lt;h2 id="how-do-you-do-this"&gt;How do you do this?&lt;/h2&gt;
&lt;p&gt;One test I like to use for where the logic goes is, &amp;quot;What if the technology changed?&amp;quot;  What if I wasn't able to use Web Forms or MVC, but had to use Silverlight or any other future technology?  What if SQL Server went away?  What if we switched from stored procs to NHibernate and then again to Entity Framework?  If we've got business logic wrapped up in our tools, no matter what the tools are, we can be sure the logic will need to be rewritten when the technology changes.&lt;/p&gt;
&lt;p&gt;It's great to take advantage of new tools, but your code needs to keep it's distance where possible.  Wrap the tool with an interface or something so the tool is decoupled from your logic, and you can replace the technology if you need to. I've written about this &lt;a href="https://volaresoftware.com/en/technical-posts/unit-testing-untestable-code"&gt;interface wrapping technique&lt;/a&gt; before.&lt;/p&gt;
&lt;p&gt;Another great technique is using &lt;a href="http://en.wikipedia.org/wiki/Test_driven_development"&gt;TDD&lt;/a&gt; or other test-first approaches because your code will be written with an eye toward how it will be consumed. You'll end up with lots of small classes and methods with expressive names. This outside-in approach to coding really guides you toward creating a clean API for the app's first customer - your test code.&lt;/p&gt;
</description>
      <pubDate>Thu, 30 Dec 2010 01:40:30 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/generated-unit-tests-are-a-net-negative</guid>
      <link>https://volaresoftware.com/nl/technical-posts/generated-unit-tests-are-a-net-negative</link>
      <title>Generated unit tests are a net negative</title>
      <description>&lt;p&gt;One of the most common misunderstandings for developers new to unit testing is the value of code coverage.  We intuitively know that if coverage is low, we don't have enough tests, and if coverage is high, we probably do.  Some IT shops even set minimum code coverage percentages, so if you check in code that drops the coverage metric below 80%, you fail the build.&lt;/p&gt;
&lt;p&gt;One way to get higher code coverage is to generate the tests.  Visual Studio has versions that can do this for you.  Point the code at a class, click OK a few times, and all your code in the class under test can be covered.  In fact, the generated test usually check for things you might not bother to, like what if there is a negative value passed in to a method, what if a zero passed in, what about a null, etc.  How can this be bad?  We're exercising the API of our class more fully, right?&lt;/p&gt;
&lt;h2 id="what-not-to-test"&gt;What not to test&lt;/h2&gt;
&lt;p&gt;I think the focus needs to be on testing the &lt;strong&gt;right&lt;/strong&gt; code in the &lt;strong&gt;right&lt;/strong&gt; way.  There is no point in testing the .NET framework.  If you have a auto property that is an int, you don't need to test -1, 0, 1, and null.  If int stops working, everyone using .NET has a bug.  But int isn't going to fail, and even if it does, it's not your code anyway (unless you work at Microsoft on the .NET framework team).&lt;/p&gt;
&lt;p&gt;So the first rule is be sure you're testing &lt;strong&gt;your&lt;/strong&gt; code.  That means testing your methods that do real stuff.  If you have a method in your class that just wraps a call to another class, there really isn't anything worth testing.  All you can test is that the class can be created and the method can be accessed and has those parameters and they are of that type.  But you can do that better by testing the underlying class instead of the pass-through method.&lt;/p&gt;
&lt;h2 id="go-faster-when-refactoring"&gt;Go faster when refactoring&lt;/h2&gt;
&lt;p&gt;In fact, testing these properties and pass-through methods and no arg constructors increases your code coverage numbers without adding anything meaningful to the test suite.  The net negative comes into play when it's time to refactor, whether it's adding or removing properties, renaming, moving things to different classes, etc.  Generated tests can really slow you down here as the new code stops building and the generated tests have to be removed and regenerated.&lt;/p&gt;
&lt;p&gt;A better way is to write the tests you need first, then add the code to implement that business rule or feature.  Whether you're using TDD, BDD or something else, you'll end up with tests that express the intent of the code rather than its implementation.  Tests should emphasize the features of the application, not the coding artifacts.  These are the kind of tests that add real value to your project.&lt;/p&gt;
</description>
      <pubDate>Tue, 12 Oct 2010 00:40:38 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/mvc-2-electric-boogaloo-whats-new-in-mvc-2</guid>
      <link>https://volaresoftware.com/nl/technical-posts/mvc-2-electric-boogaloo-whats-new-in-mvc-2</link>
      <title>MVC 2: Electric Boogaloo - What's new in MVC 2</title>
      <description>&lt;p&gt;The MVC team loves their rec center, but an evil real estate developer wants to bulldoze it to build a hipster bar named Ruby's.  The team has been coding their butts off with MVC 2, but will the new features be enough to save the rec center?  Will the cynical real estate developer cackle and complain that it's still not enough?&lt;/p&gt;
&lt;p&gt;Will the MVC team get areas right?  Will the new templated HtmlHelpers strike the right balance of rapid development and fine control?  Will validation concerns get muddled up with UI concerns?  Will more web forms developers make the switch to MVC?&lt;/p&gt;
&lt;h2 id="new-areas"&gt;New Areas&lt;/h2&gt;
&lt;p&gt;Areas are an organizing tool for large web sites.  If you've got lots of view and lots of controllers plus some shared content, areas can work as a top-level routing mechanism.&lt;/p&gt;
&lt;p&gt;Example areas might be Admin for an administrative site, Store for a ecommerce site, etc.  They can be either folders or separate web projects.  Use the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.arearegistration%28VS.100%29.aspx"&gt;AreaRegistration&lt;/a&gt; class to set up your routes in your Global.asax (taken from &lt;a href="http://msdn.microsoft.com/en-us/library/ee307987%28VS.100%29.aspx"&gt;MSDN article&lt;/a&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute(&amp;quot;{resource}.axd/{*pathInfo}&amp;quot;);
&lt;pre&gt;&lt;code&gt;AreaRegistration.RegisterAllAreas();

routes.MapRoute(
    &amp;amp;quot;Default&amp;amp;quot;,                                              // Route name
    &amp;amp;quot;{controller}/{action}/{id}&amp;amp;quot;,                           // URL with parameters
    new { controller = &amp;amp;quot;Home&amp;amp;quot;, action = &amp;amp;quot;Index&amp;amp;quot;, id = &amp;amp;quot;&amp;amp;quot; }  // Parameter defaults
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then override AreaRegistration in the area's folder or in the root of the area web project (also taken from &lt;a href="http://msdn.microsoft.com/en-us/library/ee307987%28VS.100%29.aspx"&gt;MSDN article&lt;/a&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
&lt;p&gt;namespace Store
{
public class Routes : AreaRegistration
{
public override string AreaName
{
get { return &amp;quot;Store&amp;quot;; }
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            &amp;amp;quot;Store_Default&amp;amp;quot;,
            &amp;amp;quot;Store/{controller}/{action}/{id}&amp;amp;quot;,
            new { controller = &amp;amp;quot;Products&amp;amp;quot;, action = &amp;amp;quot;List&amp;amp;quot;, id = &amp;amp;quot;&amp;amp;quot; }
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.sharparchitecture.net/"&gt;Sharp Architecture&lt;/a&gt; has had areas since its first release.  I remember hearing rumors about areas coming in MVC for version 1.0, but I guess it wasn't ready.  The biggest difference between the Microsoft version and the Sharp Architecture version is that the Microsoft version lets you register different web projects.&lt;/p&gt;
&lt;p&gt;Theoretically, multiple teams can work on multiple web projects, then these web projects can be rolled into the same solution and AreaRegistration can make them appear as one big web site to a browser.  I don't know how much of a need that is, but I guess if you have distributed teams that can't get to the same source code repository, it might be useful.  I prefer multiple folders in one web project over multiple web projects to keep build times down and Visual Studio responsiveness up.  I wouldn't break out each logical web site section to its own web project until the folder approach stopped working.&lt;/p&gt;
&lt;h2 id="new-htmlhelpers"&gt;New HtmlHelpers&lt;/h2&gt;
&lt;p&gt;I'm not sure if &lt;a href="http://code.google.com/p/codecampserver/"&gt;Code Camp Server&lt;/a&gt; pushed the MVC team into this or just showed how it was possible to take HtmlHelpers to this extreme, but I'm glad to see the same concepts getting rolled into the base class libraries.&lt;/p&gt;
&lt;p&gt;I think the new HtmlHelpers do give a nice range of control over your markup.  You can use:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;%= Html.LabelFor(x =&amp;gt; x.FirstName) %&amp;gt;
&amp;lt;%= Html.EditorFor(x =&amp;gt; x.FirstName) %&amp;gt;
&amp;lt;%= Html.LabelFor(x =&amp;gt; x.LastName) %&amp;gt;
&amp;lt;%= Html.EditorFor(x =&amp;gt; x.LastName) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;if you want to be fairly explicit for each form element.  Or you can save a lot of keystrokes with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;%= Html.EditorFor(x =&amp;gt; x) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if that's not enough, you can decorate your models with some &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.uihintattribute%28VS.100%29.aspx"&gt;UI hint attributes&lt;/a&gt; and roll your own rendering.  I think this is something large web projects will take advantage of for consistent markup and control rendering.  Seems like this has the advantages of homemade server controls without some of the hassles (&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.inamingcontainer%28VS.100%29.aspx"&gt;INamingContainer&lt;/a&gt;, I'm looking at you).&lt;/p&gt;
&lt;h2 id="new-validation"&gt;New Validation&lt;/h2&gt;
&lt;p&gt;I did worry for a little bit about the UI stuff bleeding into the model with these new attributes.  Seems like we've got a leaky abstraction there.  But these days I think of the MVC model as the view model, not the domain model.  The view model is married to the view it works with.  It has no other purpose than to represent the data in that view.  Well, now it also validates the data in that view, at least initially.  Oh, and it now controls some of the view rendering.  Damn.  That's three responsibilities for my little view model.&lt;/p&gt;
&lt;p&gt;But I don't have an alternative proposal to attribute-heavy view models either.  I don't want partial classes.  I haven't seen much benefit to the buddy class approach.  And I do want to reuse some of my UI hints across view models (like a date picker for DateTime types).  Plus, I want to take advantage of the new client and server side validation of my view model before it gets into the action method.  MVC 2 has this built in.&lt;/p&gt;
&lt;p&gt;I guess I'll grin and bear it and work on a new blog post about the Triple Responsibility Principal for View Models (as opposed to &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;SRP&lt;/a&gt;). :D&lt;/p&gt;
&lt;h2 id="future"&gt;Future&lt;/h2&gt;
&lt;p&gt;I've already talked about &lt;a href="https://volaresoftware.com/en/technical-posts/evolution-of-a-view-in-aspnet-mvc"&gt;where MVC views are now and where they are going&lt;/a&gt;, and the view engine is definitely getting better. I still think views will continue to be the most in-flux part of the MVC framework.  I know people that are very happy with &lt;a href="http://sparkviewengine.com/"&gt;Spark&lt;/a&gt; as a view engine, and &lt;a href="http://www.hanselman.com/blog/HanselminutesPodcast192TheSparkViewEngineForASPNETMVCWithLouisDeJardin.aspx"&gt;Louis DeJardin, the guy who wrote Spark, is now working for Microsoft&lt;/a&gt; on the ASP.NET team.  I don't have any inside scoop, but I wouldn't be surprised if the web forms view engine got a little.&amp;quot;sparkier&amp;quot;.&lt;/p&gt;
&lt;p&gt;Views may also be the area with the most room for improvement, depending on who you talk to.  When I visit with people about MVC and explain that runat=&amp;quot;server&amp;quot; is gone and you can go ahead and close your Visual Studio toolbox, most get a glazed look.  They don't want to hand code the HTML.  They don't want to see a property sheet that doesn't know anything about their current mouse selection.  They don't want to give up their current productivity.&lt;/p&gt;
&lt;p&gt;I get that, but I think you can be faster without the designers and toolboxes and property sheets.  It takes a while to get used to using the keyboard more than the mouse, but I think it's worth pushing yourself over that learning curve.&lt;/p&gt;
&lt;h2 id="time-to-switch-from-web-forms-to-mvc"&gt;Time to switch from Web Forms to MVC?&lt;/h2&gt;
&lt;p&gt;I push MVC on projects where I have influence on that decision.  In your world, it's your call.  You may have environment constraints, in-flight projects, etc.&lt;/p&gt;
&lt;p&gt;But it also doesn't have to be all or nothing.  You don't have to wait for a &lt;a href="http://en.wikipedia.org/wiki/Greenfield_project"&gt;greenfield project&lt;/a&gt; to fall in your lap.  You &lt;strong&gt;can&lt;/strong&gt; run MVC inside your current Web Forms project.  It's just another set of HttpHandlers living under ASP.NET.  Here is &lt;a href="http://www.hanselman.com/blog/PlugInHybridsASPNETWebFormsAndASPMVCAndASPNETDynamicDataSideBySide.aspx"&gt;some&lt;/a&gt; &lt;a href="http://www.codeproject.com/KB/aspnet/webformmvcharmony.aspx"&gt;guidance&lt;/a&gt; for getting your current project set up to do this.&lt;/p&gt;
&lt;p&gt;I encourage you to give it a try and see what you think.  It will take a while to get used to the paradigm.  It's not hard - just different.  But I think once you're used to it, you'll like the separation of concerns, the easier testing, and the more natural flow for web development.&lt;/p&gt;
&lt;p&gt;By natural flow, I mean embracing the world of GET and POST.  I mean when you need to expose &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.jsonresult.aspx"&gt;JSON&lt;/a&gt;, an &lt;a href="http://www.wduffy.co.uk/blog/rssresult-aspnet-mvc-rss-actionresult/"&gt;RSS&lt;/a&gt; feed, or something else (XML, PDF, file, etc.), &lt;a href="http://msdn.microsoft.com/en-us/library/dd410269.aspx"&gt;Controller Actions&lt;/a&gt; are ready to go.  Stop writing custom HttpHandlers or fighting &lt;a href="http://msdn.microsoft.com/en-us/library/ms731734.aspx"&gt;WCF configuration&lt;/a&gt; for this stuff.  It should be simpler, and it is with Controller Actions and the right &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionresult.aspx"&gt;ActionResult&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Make it a goal to get some real-world MVC experience in 2010.  Think of the kids on the MVC team and their beloved rec center.  Don't let their dream die.  They've come too far.  And remember the tag line from Breakin' 2 - &amp;quot;If you can't beat the system&lt;em&gt;break it!&lt;/em&gt;&amp;quot;.&lt;/p&gt;
</description>
      <pubDate>Mon, 18 Jan 2010 01:41:07 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/setting-default-values-for-kendo-ui-and-datatables-controls</guid>
      <link>https://volaresoftware.com/nl/technical-posts/setting-default-values-for-kendo-ui-and-datatables-controls</link>
      <title>Setting default values for Kendo UI and DataTables controls</title>
      <description>&lt;p&gt;Most JavaScript controls take a JSON object for their settings.  Here's how you initialize a &lt;a href="http://demos.kendoui.com/web/grid/index.html"&gt;Kendo UI grid&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;$(&amp;quot;#myGrid&amp;quot;).kendoGrid({
    pageable: true,
    sortable: { mode: &amp;quot;multiple&amp;quot;, allowUnsort: true },
    filterable: true,
    dataSource: {
        data: myData,
        pageSize: 10
    }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here's how you initialize a &lt;a href="http://www.datatables.net/"&gt;DataTables&lt;/a&gt; grid:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;$(&amp;quot;#myGrid&amp;quot;).dataTable({
    &amp;quot;bSort&amp;quot;: true,
    &amp;quot;bAutoWidth&amp;quot;: false,
    &amp;quot;bProcessing&amp;quot;: true,
    &amp;quot;bJQueryUI&amp;quot;: true,
    &amp;quot;bPaginate&amp;quot;: true,
    &amp;quot;bServerSide&amp;quot;: true,
    &amp;quot;bSortCellsTop&amp;quot;: true,
    &amp;quot;sPaginationType&amp;quot;: &amp;quot;full_numbers&amp;quot;,
    &amp;quot;iDisplayLength&amp;quot;: 25,
    &amp;quot;aLengthMenu&amp;quot;: [[5, 10, 25, 100], [5, 10, 25, 100]],
    &amp;quot;aaSorting&amp;quot;: [],
    &amp;quot;sAjaxSource&amp;quot;: &amp;quot;/Api/MyData&amp;quot;,
    &amp;quot;sAjaxDataProp&amp;quot;: &amp;quot;Data&amp;quot;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both controls take an object literal with all the settings to style how the control looks, works, etc.&lt;/p&gt;
&lt;p&gt;But look at all those settings!  We have to set all that sorting and paging and filtering every time if we want non-default behavior?  And what if we change our mind later and want to use virtual paging instead of page numbers or another application-wide change?&lt;/p&gt;
&lt;p&gt;If there was only a way to centralize the common settings and reuse them with each call…&lt;/p&gt;
&lt;h2 id="reuse-common-settings"&gt;Reuse common settings&lt;/h2&gt;
&lt;p&gt;Here's a snippet of JavaScript to store common settings for a Kendo UI grid:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;var kendoGridDefaults = {
    filterable: {
        pageable: true,
        sortable: { mode: &amp;quot;multiple&amp;quot;, allowUnsort: true },
        filterable: true
    },
    nonFilterable: {
        pageable: true,
        sortable: { mode: &amp;quot;multiple&amp;quot;, allowUnsort: true },
        filterable: false
    },
    extend: function (defaults, settings) {
        return $.extend(true, {}, this[defaults], settings);
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here are some common settings for a DataTables grid:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;var dataTableDefaults = {
    serverSide: {
        &amp;quot;bSort&amp;quot;: true,
        &amp;quot;bAutoWidth&amp;quot;: false,
        &amp;quot;bProcessing&amp;quot;: true,
        &amp;quot;bJQueryUI&amp;quot;: true,
        &amp;quot;bPaginate&amp;quot;: true,
        &amp;quot;bServerSide&amp;quot;: true,
        &amp;quot;bSortCellsTop&amp;quot;: true,
        &amp;quot;sPaginationType&amp;quot;: &amp;quot;full_numbers&amp;quot;,
        &amp;quot;iDisplayLength&amp;quot;: 25,
        &amp;quot;aLengthMenu&amp;quot;: [[5, 10, 25, 100], [5, 10, 25, 100]],
        &amp;quot;aaSorting&amp;quot;: []
    },
    extend: function(defaults, settings) {
        return $.extend(true, {}, this[defaults], settings);
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In both cases, you build up an object literal with with the common settings you want to reuse, then create an &amp;quot;extend&amp;quot; function (or another name, if you like) using the &lt;a href="http://api.jquery.com/jQuery.extend/"&gt;jQuery $.extend function&lt;/a&gt;, which merges your default settings with any new settings you pass in.&lt;/p&gt;
&lt;h2 id="more-than-one-set-of-common-settings"&gt;More than one set of common settings&lt;/h2&gt;
&lt;p&gt;You will likely have more than one set of reusable settings (server-side grid and client side grid, filterable and non-filterable grids, etc.).  Just define new objects in your settings object.  Above, I've got &amp;quot;filterable&amp;quot;, &amp;quot;nonFilterable&amp;quot;, and &amp;quot;serverSide&amp;quot; as property sets.&lt;/p&gt;
&lt;h2 id="usage"&gt;Usage&lt;/h2&gt;
&lt;p&gt;To take advantage of the default settings, call your control code and pass in the common settings object, then call the extend function with your overrides and/or additional settings:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;$(&amp;quot;#myGrid&amp;quot;).kendoGrid(kendoGridDefaults.extend(&amp;quot;filterable&amp;quot;, {
    dataSource: {
        data: myData,
        pageSize: 10
    }
}));
&lt;p&gt;$(&amp;quot;#myGrid&amp;quot;).dataTable(dataTableDefaults.extend(&amp;quot;serverSide&amp;quot;, {
&amp;quot;sAjaxSource&amp;quot;: &amp;quot;/api/myData&amp;quot;,
&amp;quot;sAjaxDataProp&amp;quot;: &amp;quot;Data&amp;quot;
}));
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This technique isn't limited to grids, or to Kendo UI or DataTables.  It can be used with any controls that set their properties with a JavaScript object literal.&lt;/p&gt;
</description>
      <pubDate>Mon, 01 Apr 2013 05:57:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/sessionless-mvc-3</guid>
      <link>https://volaresoftware.com/nl/technical-posts/sessionless-mvc-3</link>
      <title>Sessionless MVC 3</title>
      <description>&lt;p&gt;If you've done much ASP.NET development, you know you shouldn't use &lt;a href="http://msdn.microsoft.com/en-us/library/ms178581.aspx"&gt;session&lt;/a&gt; for high performance web sites that require web farms and load balancers.  You can centralize session to be on one web server or move it to the database, but what if you want to avoid it altogether?&lt;/p&gt;
&lt;p&gt;MVC 3 introduces a new controller attribute called &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.sessionstateattribute%28v=VS.98%29.aspx"&gt;SessionStateAttribute&lt;/a&gt;.  You can decorate your controller with this attribute to disable session, make it read-only, or turn it on for full read-write access.  Note that &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.tempdatadictionary%28v=VS.90%29.aspx"&gt;TempData&lt;/a&gt;, which uses session to store values between requests, is also disabled if session is disabled.  That makes sense, but since it's called &lt;code&gt;TempData[]&lt;/code&gt; instead of &lt;code&gt;Session[]&lt;/code&gt;, it's not obvious.&lt;/p&gt;
&lt;p&gt;Here's how you can use this on a controller.  Note this attribute is at the controller level, not the action level.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web.Mvc;
using System.Web.SessionState;
&lt;p&gt;namespace MvcApplication1.Controllers
{
[SessionState(SessionStateBehavior.Disabled)]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = &amp;quot;Welcome to ASP.NET MVC!&amp;quot;;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        return View();
    }

    public ActionResult About()
    {
        return View();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strike&gt;And here's how you can set it as a &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.globalfiltercollection%28v=vs.98%29.aspx"&gt;Global Filter&lt;/a&gt;&lt;strike&gt; to turn it off for all controllers. The attribute is being set in the &lt;code&gt;RegisterGloablFilters&lt;/code&gt; method in the &lt;code&gt;Global.asax&lt;/code&gt; and is called in &lt;code&gt;Application_Start&lt;/code&gt;.&lt;/strike&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; This doesn't work as a global action filter.  However, you can turn off session for your whole application with code in your &lt;code&gt;web.config&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;system.web&amp;gt;
    ...
    &amp;lt;sessionState mode=&amp;quot;Off&amp;quot; /&amp;gt;
    ...
&amp;lt;/system.web&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Fri, 21 Jan 2011 01:40:25 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/handling-exceptions-in-asp-net-mvc</guid>
      <link>https://volaresoftware.com/nl/technical-posts/handling-exceptions-in-asp-net-mvc</link>
      <title>Handling Exceptions in ASP.NET MVC</title>
      <description>&lt;p&gt;Here is a quick run down of the various approaches for handling exceptions.  I use a combination of these that I'll show at the end.&lt;/p&gt;
&lt;h2 id="try-catch-everywhere"&gt;Try-Catch everywhere&lt;/h2&gt;
&lt;p&gt;You've seen this code before, right?&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public void DoSomething()
{
    try
    {
        var x = 1;
    } 
    catch (Exception ex) 
    {
        ShowExceptionToUser(ex.Message);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The approach of putting try-catch block around every ounce of code seems like a good idea intuitively.  Sure, you're showing the user an ugly error message, but it's better than crashing the server.&lt;/p&gt;
&lt;p&gt;But what is the user supposed to do with the information you show them?  How are they supposed to fix &lt;em&gt;your&lt;/em&gt; null reference exception?&lt;/p&gt;
&lt;p&gt;The other knock on this approach is there is so much &lt;a href="http://msdn.microsoft.com/en-us/magazine/dvdarchive/dd419655.aspx"&gt;ceremony code&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id="generic-error-page"&gt;Generic error page&lt;/h2&gt;
&lt;p&gt;This approach goes the other way with a generic error page displayed to the user for any unhandled error.  It's easy to implement in the &lt;code&gt;Web.config&lt;/code&gt; file, and the user never sees a null reference exception or stack trace.&lt;/p&gt;
&lt;p&gt;Here's what I'm using:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;customErrors mode=&amp;quot;RemoteOnly&amp;quot; defaultRedirect=&amp;quot;~/Error&amp;quot;&amp;gt;
  &amp;lt;error statusCode=&amp;quot;403&amp;quot; redirect=&amp;quot;~/Error&amp;quot; /&amp;gt;
  &amp;lt;error statusCode=&amp;quot;404&amp;quot; redirect=&amp;quot;~/Error&amp;quot; /&amp;gt;
&amp;lt;/customErrors&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are two problems with the generic error page approach.  First, the user has &lt;em&gt;no&lt;/em&gt; information about what happened.  Maybe it's something they could have resolved?  Maybe they should try again later?  Just saying &amp;quot;Pardon our mess&amp;quot; doesn't give them any details.&lt;/p&gt;
&lt;p&gt;Second, it doesn't give &lt;em&gt;you&lt;/em&gt; any details either.  The next time you talk to the user, they will tell you they got an error in your app.  &amp;quot;Oh, what happened?&amp;quot; you'll ask.&lt;/p&gt;
&lt;p&gt;&amp;quot;Uh, it was on that screen with the customer info.  I forgot what I was doing, but it just showed the error screen, so I rebooted and went home for the day.&amp;quot;  Not much to go on.  Something about the customer screen?  This will be a fun one to try to reproduce!&lt;/p&gt;
&lt;h2 id="just-log-it"&gt;Just log it&lt;/h2&gt;
&lt;p&gt;The last approach is to log all errors.  You collect as much detail as you need.  The date and time the exception was thrown, which user/IP address, which server they were on, the stack trace, etc.&lt;/p&gt;
&lt;p&gt;Error logging can be extensive and can be stored in rolling text files or database tables.  I prefer using the database so I don't need to grant write permissions to the ASP.NET process running that web app.&lt;/p&gt;
&lt;p&gt;Here's an &lt;code&gt;Application_Error&lt;/code&gt; event from a couple projects back:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;protected void Application_Error(object sender, EventArgs e) 
{
    var ctx = HttpContext.Current;
    var ex = ctx.Server.GetLastError();
    if (ex != null) 
    {
        _logService.LogExceptionToDatabase(ex);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I've done lots of applications like this, where the &lt;code&gt;Application_Error&lt;/code&gt; event in &lt;code&gt;Global.asax&lt;/code&gt; calls into a logger like &lt;a href="http://logging.apache.org/log4net/index.html"&gt;log4net&lt;/a&gt; or &lt;a href="http://www.codeplex.com/entlib"&gt;Enterprise Library&lt;/a&gt; to store exception details.  It works great.  You get the details you need to fix the bug.&lt;/p&gt;
&lt;p&gt;But what about the user?  What are the users looking at when this exception is thrown?&lt;/p&gt;
&lt;h2 id="combo-platter"&gt;#3 Combo Platter&lt;/h2&gt;
&lt;p&gt;Today, I'm using bits and pieces of all of these.&lt;/p&gt;
&lt;p&gt;I show the user a generic error page for all &lt;strong&gt;unhandled&lt;/strong&gt; exceptions.  It may not have much info, but something weird just happened in the app and I wasn't expecting it.  I need more information about what happened so I can decide what needs to be done.&lt;/p&gt;
&lt;p&gt;That's why I'm also using &lt;a href="http://code.google.com/p/elmah/"&gt;ELMAH&lt;/a&gt; to log all &lt;strong&gt;unhandled&lt;/strong&gt; exceptions.  The exception details get stored in my database and I even get a fancy exception viewer since ELMAH works as an &lt;code&gt;HttpHandler&lt;/code&gt;.  My favorite ELMAH feature is you can usually see the yellow screen you would have seen if running locally on your box.&lt;/p&gt;
&lt;p&gt;Finally, sometimes there are &lt;strong&gt;handled&lt;/strong&gt; exceptions.  This is where an exception occurred before in the code (database is down, file not found, etc.), it might occur again, and I've got some thoughts about what to do next time it happens.&lt;/p&gt;
&lt;p&gt;In my view, the only place you need try-catch blocks is when you are worried that an exception might happen and you want to give the user some information, give the user instructions, or silently fix the problem yourself.  If I can't do one of these, I just show the &amp;quot;Oops&amp;quot; page try to come up with a plan later.&lt;/p&gt;
&lt;p&gt;For instance, if the database is down, I'd tell the user to try again later, but I couldn't save their record right now.  If the user is trying to upload a file and it's not there, they can try to correct the file upload input box and resubmit.&lt;/p&gt;
&lt;h2 id="how-to-wire-this-up-in-asp.net-mvc"&gt;How to wire this up in ASP.NET MVC&lt;/h2&gt;
&lt;h3 id="set-up-elmah"&gt;Set up ELMAH&lt;/h3&gt;
&lt;p&gt;First, &lt;a href="http://code.google.com/p/elmah/downloads/list"&gt;download ELMAH binaries&lt;/a&gt;, add a reference to the ELMAH assembly in your web project, and follow the &lt;a href="http://code.google.com/p/elmah/wiki/MVC"&gt;instructions to get your Web.config set up correctly&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now test out ELMAH.  You should be able to browse to elmah.axd and see the list of exceptions.  Try throwing one in your code somewhere and see if ELMAH logs it.&lt;/p&gt;
&lt;p&gt;You can make the elmah.axd page secure, log to a database, etc.&lt;/p&gt;
&lt;h3 id="set-up-the-generic-error-page"&gt;Set up the Generic Error Page&lt;/h3&gt;
&lt;p&gt;Once ELMAH is logging, wire up your Web.config to show the generic error page:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;customErrors mode=&amp;quot;RemoteOnly&amp;quot; defaultRedirect=&amp;quot;~/Error&amp;quot;&amp;gt;
  &amp;lt;error statusCode=&amp;quot;403&amp;quot; redirect=&amp;quot;~/Error&amp;quot; /&amp;gt;
  &amp;lt;error statusCode=&amp;quot;404&amp;quot; redirect=&amp;quot;~/Error&amp;quot; /&amp;gt;
&amp;lt;/customErrors&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'm using an Error controller with a single Index action so I can send the user to the root and to the Error route to show the error page.  Here's the controller:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class ErrorController : Controller
{
    public ActionResult Index() 
    {
        return View(&amp;quot;Error&amp;quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's calling a view also called &amp;quot;Error&amp;quot; that is in &lt;code&gt;~\Views\Shared\Error.aspx&lt;/code&gt;.  Make your version of that page.  Remember, this is the page for unhandled exceptions.&lt;/p&gt;
&lt;p&gt;Next, you need to register this route.  I've moved my route registration out of my &lt;code&gt;Global.asax&lt;/code&gt;, but if you have a default ASP.NET MVC install, look for your routing registrations in &lt;code&gt;Application\_Start&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;routes.MapRoute(&amp;quot;UnhandledExceptions&amp;quot;, &amp;quot;Error&amp;quot;, new { controller = &amp;quot;Error&amp;quot;, action = &amp;quot;Index&amp;quot; });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is just setting up some defaults in the route to simplify redirects to the generic error page.  At this point, you should be able to browse to any controller with a thrown exception in the action and see your generic error page displayed.&lt;/p&gt;
&lt;h3 id="set-up-the-elmahhandleerror-attribute"&gt;Set up the ElmahHandleError attribute&lt;/h3&gt;
&lt;p&gt;There's one step left!  You've now got two ways of dealing with unhandled exceptions.  We need to consolidate these so the generic page is show AND the ELMAH logging is called.&lt;/p&gt;
&lt;p&gt;You know how you have to add the &lt;code&gt;HandleError&lt;/code&gt; attribute to your controller classes to get the generic error page to appear?  This attribute doesn't call ELMAH.  This is by design, since the &lt;code&gt;HandleError&lt;/code&gt; attribute is, well, &lt;em&gt;handling&lt;/em&gt; the error.  ELMAH is for &lt;strong&gt;unhandled&lt;/strong&gt; errors and doesn't log otherwise.&lt;/p&gt;
&lt;p&gt;But you can have it both ways and use ELMAH as your handled exception logging tool as well.  Follow these steps to &lt;a href="http://stackoverflow.com/questions/766610/how-to-get-elmah-to-work-with-asp-net-mvc-handleerror-attribute"&gt;create an ElmahHandleError attribute&lt;/a&gt; and replace the &lt;code&gt;HandleError&lt;/code&gt; attribute on your controllers with this new attribute.&lt;/p&gt;
&lt;p&gt;That's it!  You should be all set with an exception handling strategy.&lt;/p&gt;
</description>
      <pubDate>Sun, 23 Aug 2009 09:24:27 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/combining-javascript-bundling-minification-cache-busting-and-easier-debugging</guid>
      <link>https://volaresoftware.com/nl/technical-posts/combining-javascript-bundling-minification-cache-busting-and-easier-debugging</link>
      <title>Combining JavaScript bundling, minification, cache busting, and easier debugging</title>
      <description>&lt;p&gt;ASP.NET MVC has had server-side bundling and minification for a couple versions now.  You can use this to reduce HTTP requests from the client browser to the web server.  This optimization is a must when you get lots of small JavaScript files, which is what most large web applications have these days.&lt;/p&gt;
&lt;p&gt;Here's the default BundleConfig.cs in an MVC4 default project:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web;
using System.Web.Optimization;
&lt;p version=""&gt;namespace BundlingSample
{
public class BundleConfig
{
// For more information on Bundling, visit &lt;a href="http://go.microsoft.com/fwlink/?LinkId=254725"&gt;http://go.microsoft.com/fwlink/?LinkId=254725&lt;/a&gt;
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle(&amp;quot;&lt;sub&gt;/bundles/jquery&amp;quot;).Include(
&amp;quot;&lt;/sub&gt;/Scripts/jquery-.js&amp;quot;));&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        bundles.Add(new ScriptBundle(&amp;amp;quot;~/bundles/jqueryui&amp;amp;quot;).Include(
                    &amp;amp;quot;~/Scripts/jquery-ui-{version}.js&amp;amp;quot;));

        bundles.Add(new ScriptBundle(&amp;amp;quot;~/bundles/jqueryval&amp;amp;quot;).Include(
                    &amp;amp;quot;~/Scripts/jquery.unobtrusive*&amp;amp;quot;,
                    &amp;amp;quot;~/Scripts/jquery.validate*&amp;amp;quot;));

        // Use the development version of Modernizr to develop with and learn from. Then, when you're
        // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
        bundles.Add(new ScriptBundle(&amp;amp;quot;~/bundles/modernizr&amp;amp;quot;).Include(
                    &amp;amp;quot;~/Scripts/modernizr-*&amp;amp;quot;));

        bundles.Add(new StyleBundle(&amp;amp;quot;~/Content/css&amp;amp;quot;).Include(&amp;amp;quot;~/Content/site.css&amp;amp;quot;));

        bundles.Add(new StyleBundle(&amp;amp;quot;~/Content/themes/base/css&amp;amp;quot;).Include(
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.core.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.resizable.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.selectable.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.accordion.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.autocomplete.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.button.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.dialog.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.slider.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.tabs.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.datepicker.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.progressbar.css&amp;amp;quot;,
                    &amp;amp;quot;~/Content/themes/base/jquery.ui.theme.css&amp;amp;quot;));
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This approach works well for 3rd party libraries (jQuery, jQuery validation, knockout, etc.), and it has a cache-busting hash in the URL that keeps you from caching an old version of the bundled and minified script in your browser.&lt;/p&gt;
&lt;p&gt;Here you can see jquery and modernizr have a query string after the file name with the unique key:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_48.png" alt="image_48.png" /&gt;&lt;/p&gt;
&lt;p&gt;So we've got bundling of scripts, minification, and cache-busting.  What's not to love?&lt;/p&gt;
&lt;h2 id="where-do-i-put-my-application-scripts"&gt;Where do I put my application scripts?&lt;/h2&gt;
&lt;p&gt;The default MVC project gives you a \Scripts folder.  You could put your application scripts there.  NuGet would like you to leave 3rd party scripts there, and it's the convention, but I prefer to move scripts I didn't write for the current app into a \Scripts\lib folder, and scripts for the app go in a \Scripts\app folder.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_49.png" alt="image_49.png" /&gt;&lt;/p&gt;
&lt;p&gt;You'll have some moving around to do when you update a JavaScript via NuGet to get it in your preferred folder, but it's a little easier to find the stuff you'll really be working on for your app.  You'll also need to update your BundleConfig.cs to point to the new \Scripts\lib folder.&lt;/p&gt;
&lt;p&gt;So how to we bundle these app scripts?  You could bundle them all in one file.  Everything in that folder gets put in a &amp;quot;~/bundles/myApp&amp;quot; bundle.  The problem is, you'll likely end up with lots of sequencing problems in the scripts and see &amp;quot;undefined&amp;quot; errors.  This could work if you only have a small amount of JavaScript in your app, but it's not recommended.&lt;/p&gt;
&lt;p&gt;You could also create a Razor section in the _Layout.cshtml and call it &amp;quot;scripts&amp;quot;, then each view can list the scripts it needs to work in that Razor section.  The default MVC4 _Layout.cshtml file already has this Razor section set up for you.  This approach works, but now we're not bundling or minifying the JavaScript, and we don't have any cache busting going on with our app scripts.&lt;/p&gt;
&lt;h2 id="so-i-have-to-debug-minified-files-yuck"&gt;So I have to debug minified files? Yuck.&lt;/h2&gt;
&lt;p&gt;The other drawback of using the built-in ASP.NET optimizations for bundling and minification is debugging minified files.  You've probably dealt with this when your JavaScript throws an exception and you're in the middle of a jQuery file.  JQuery almost certainly doesn't have a bug, but you sent it some values it wasn't expecting.  Have fun sorting that out.&lt;/p&gt;
&lt;p&gt;![[image_thumb_11.png](https://cdn.volaresoftware.com/images/posts/2013/3/image_thumb_11.png)&lt;/p&gt;
&lt;p&gt;IE10 and Chrome have JavaScript pretty print tools that can make the minified script a little easier to read than one long line, but the variable names will all still be a, b, c, and whatever the minifier hadn't already used.&lt;/p&gt;
&lt;p&gt;Using map files is a better way to go, and in Chrome, you turn this on in dev tools and click the gear at the bottom right, then check &amp;quot;Enable source maps&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_50.png" alt="image_50.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now each minified file can have a map file that points to the original, unminified source code.  The built-in ASP.NET optimizations don't work with map files yet.&lt;/p&gt;
&lt;h2 id="web-essentials-bundling-to-the-rescue"&gt;Web Essentials bundling to the rescue&lt;/h2&gt;
&lt;p&gt;If you are a Visual Studio web developer and you don't have &lt;a href="http://visualstudiogallery.msdn.microsoft.com/07d54d12-7133-4e15-becb-6f451ea3bea6"&gt;Web Essentials&lt;/a&gt;, go get it now.  You'll love it.  It's a Visual Studio extension created my &lt;a href="https://twitter.com/mkristensen"&gt;Mads Kristensen&lt;/a&gt;, who works for Microsoft for the Web Platform and Tools group.&lt;/p&gt;
&lt;p&gt;One of the features is bundling and minification.  You select the files you want to bundle, right click, then choose Web Essentials &amp;gt; Create JavaScript bundle file.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_51.png" alt="image_51.png" /&gt;&lt;/p&gt;
&lt;p&gt;Name your bundle, and several files will be created.  The first is the *.bundle file:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
    &amp;lt;bundle minify=&amp;quot;true&amp;quot; runOnBuild=&amp;quot;true&amp;quot;&amp;gt;
    &amp;lt;!--The order of the &amp;lt;file&amp;gt; elements determines the order of them when bundled.--&amp;gt;
    &amp;lt;file&amp;gt;/Scripts/app/script1.js&amp;lt;/file&amp;gt;
    &amp;lt;file&amp;gt;/Scripts/app/script2.js&amp;lt;/file&amp;gt;
&amp;lt;/bundle&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This file lists each script in the bundle and has flags for minify (default is &amp;quot;true&amp;quot;) and runOnBuild (default is &amp;quot;true&amp;quot;).  You may need to rearrange the order of the bundle files if there are functions defined in one file and called in another.&lt;/p&gt;
&lt;p&gt;Any change you make to script1.js or script2.js, the *.bundle file, or building your app, will regenerate the files underneath the *.bundle file:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_52.png" alt="image_52.png" /&gt;&lt;/p&gt;
&lt;p&gt;These three files are 1) the combined bundle without minification, 2) the bundle with minification, and 3) the map file for debugging the original script.  The first is a giant concatenation of the two files and isn't that interesting.&lt;/p&gt;
&lt;p&gt;The minified file looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;function add(n,t){return n+t}function subtract(n,t){return n-t}function showMessage(n){alert(n)}
//@ sourceMappingURL=myAppBundle.min.js.map
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the map file looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
    &amp;quot;version&amp;quot;:3,
    &amp;quot;file&amp;quot;:&amp;quot;myAppBundle.min.js&amp;quot;,
    &amp;quot;lineCount&amp;quot;:1,
    &amp;quot;mappings&amp;quot;:&amp;quot;AAAAA,SAASA,GAAG,CAACC,CAAC,CAAEC,CAAJ,CAAO,CACf,OAAOD,CAAE,CAAEC,CADI,CAInBC,SAASA,QAAQ,CAACF,CAAC,CAAEC,CAAJ,CAAO,CACpB,OAAOD,CAAE,CAAEC,CADS,CCJxBE,SAASA,WAAW,CAACC,CAAD,CAAM,CACtBC,KAAK,CAACD,CAAD,CADiB&amp;quot;,
    &amp;quot;sources&amp;quot;:[&amp;quot;/Scripts/app/script1.js&amp;quot;,&amp;quot;/Scripts/app/script2.js&amp;quot;],
    &amp;quot;names&amp;quot;:[&amp;quot;add&amp;quot;,&amp;quot;x&amp;quot;,&amp;quot;y&amp;quot;,&amp;quot;subtract&amp;quot;,&amp;quot;showMessage&amp;quot;,&amp;quot;msg&amp;quot;,&amp;quot;alert&amp;quot;]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the minified file gives the browser instructions on how to get to the map file, which gives the browser instructions on how to render in unminified, made-for-humans format.&lt;/p&gt;
&lt;h2 id="using-the-bundles"&gt;Using the bundles&lt;/h2&gt;
&lt;p&gt;I create a bundle of app scripts for each view (usually I name it after the view, like register.bundle, login.bundle, etc.) and use the Razor &amp;quot;scripts&amp;quot; section in the _Layout.cshtml file to place those scripts at the bottom of the html, just before the closing &lt;body&gt; tag.  The script reference points to the minified file.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;@section scripts {
    &amp;lt;script src=&amp;quot;~/Scripts/app/myAppBundle.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Chrome, the end result is this for the minified file:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_53.png" alt="image_53.png" /&gt;&lt;/p&gt;
&lt;p&gt;And this for the mapped file:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_54.png" alt="image_54.png" /&gt;&lt;/p&gt;
&lt;p&gt;This human-readable script can have breakpoints, etc.  It looks like the original file, but the browser has not created new HTTP requests to pull down the originals.  It's map file magic.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_55.png" alt="image_55.png" /&gt;&lt;/p&gt;
&lt;p&gt;Setting up view-specific bundles seems lighter weight to me than always editing the BundleConfig.cs file, plus you get the mapping files.  Now we just need to solve for the cache busting we lost with this approach.&lt;/p&gt;
&lt;h2 id="cache-busting"&gt;Cache busting&lt;/h2&gt;
&lt;p&gt;Ever send your product owner to the CI web server to check out a new feature, only to have them tell you they got JavaScript errors on that page?  Did you tell them to type CTRL-F5 to force a refresh of the page?  If so, you have a caching problem where the browser is caching the file even though it has changed.&lt;/p&gt;
&lt;p&gt;Mads has &lt;a href="https://madskristensen.net/blog/cache-busting-in-aspnet/"&gt;a blog post on cache busting&lt;/a&gt; that works well.  It's based on getting the last changed date of the file and appending that date in ticks to the path of the request for the script or css.  His solution involves having URL rewriting working on IIS.&lt;/p&gt;
&lt;p&gt;In my case, I didn't want to mess with URL rewriting, so I went with the somewhat less optimal but simpler solution of using a query string instead.  Here's my Razor helper:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.IO;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
&lt;p&gt;namespace BundlingSample.Extensions
{
public static class StaticFile
{
public static string Version(string rootRelativePath)
{
if (HttpRuntime.Cache[rootRelativePath] == null)
{
var absolutePath = HostingEnvironment.MapPath(rootRelativePath);
var lastChangedDateTime = File.GetLastWriteTime(absolutePath);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;            if (rootRelativePath.StartsWith(&amp;amp;quot;~&amp;amp;quot;))
            {
                rootRelativePath = rootRelativePath.Substring(1);
            }

            var versionedUrl = rootRelativePath + &amp;amp;quot;?v=&amp;amp;quot; + lastChangedDateTime.Ticks;

            HttpRuntime.Cache.Insert(rootRelativePath, versionedUrl, new CacheDependency(absolutePath));
        }

        return HttpRuntime.Cache[rootRelativePath] as string;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;and how it's used in the Razor view:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;@section scripts {
    &amp;lt;script src=&amp;quot;@StaticFile.Version(&amp;quot;~/Scripts/app/myAppBundle.min.js&amp;quot;)&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the resulting file name in the browser:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/3/image_56.png" alt="image_56.png" /&gt;&lt;/p&gt;
&lt;p&gt;The query string pattern matches the built-in ASP.NET optimization pattern.  I say this is sub-optimal because some page speed tools will fuss at you for using query strings.  Google PageSpeed says, &amp;quot;Enabling public caching in the HTTP headers for static resources allows the browser to download resources from a nearby proxy server rather than from a remote origin server.&amp;quot;  I'm not too worried about that, but you'll want to use Mads' URL rewrite approach if you want a better PageSpeed score.&lt;/p&gt;
&lt;p&gt;So there you have it.  Bundling, minification, debugging, and cache busting when you need it!&lt;/p&gt;
</description>
      <pubDate>Mon, 18 Mar 2013 01:12:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/prefiltering-a-kendo-ui-grid-with-an-odata-data-source</guid>
      <link>https://volaresoftware.com/nl/technical-posts/prefiltering-a-kendo-ui-grid-with-an-odata-data-source</link>
      <title>Prefiltering a Kendo UI grid with an OData data source</title>
      <description>&lt;p&gt;If you're using &lt;a href="http://demos.kendoui.com/web/grid/index.html"&gt;Kendo UI's grid&lt;/a&gt;, you know you can &lt;a href="https://volaresoftware.com/en/technical-posts/using-kendo-ui-grid-with-web-api-and-odata"&gt;plug it into a Web API OData data source&lt;/a&gt;.  The nice thing about using an OData end point is you don't have to parse all the possible filter values in your Web API code.  You'd have to plan for column names, values, different operators, and'ing and or'ing of values, etc.  Instead, with OData, just keep the data IQueryable, mark the method with a [Queryable] attribute, and you're all set.&lt;/p&gt;
&lt;p&gt;But what if you want some client-side filtering to start off with?  You could hack up the OData URL sent back to Web API, or you could set a filter on the grid's data source (extending the &lt;a href="https://volaresoftware.com/en/technical-posts/using-kendo-ui-grid-with-web-api-and-odata"&gt;example here&lt;/a&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;$(function () {
    var dataSource = new kendo.data.DataSource({
        type: &amp;quot;odata&amp;quot;,
        transport: {
            read: {
                url: &amp;quot;/api/Cats&amp;quot;,
                dataType: &amp;quot;json&amp;quot;
            },
        },
        schema: {
            data: function (data) {
                return data[&amp;quot;value&amp;quot;];
            },
            total: function (data) {
                return data[&amp;quot;odata.count&amp;quot;];
            },
            model: {
                fields: {
                    Id: { type: &amp;quot;number&amp;quot; },
                    Name: { type: &amp;quot;string&amp;quot; },
                    Color: { type: &amp;quot;string&amp;quot; }
                }
            }
        },
        pageSize: 10,
        serverPaging: true,
        serverFiltering: true,
        serverSorting: true,
        filter: { field: &amp;quot;Color&amp;quot;, operator: &amp;quot;eq&amp;quot;, value: &amp;quot;black&amp;quot; }
    });
&lt;pre&gt;&lt;code&gt;$(&amp;amp;quot;#grid&amp;amp;quot;).kendoGrid({
    dataSource: dataSource,
    filterable: true,
    sortable: true,
    pageable: true,
    columns: [
        { field: &amp;amp;quot;Id&amp;amp;quot; },
        { field: &amp;amp;quot;Name&amp;amp;quot; },
        { field: &amp;amp;quot;Color&amp;amp;quot; }
    ]
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;});
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;See the &amp;quot;filter&amp;quot; setting on the data source?  That will tell OData to search for &lt;code&gt;/api/Cats/?&amp;lt;other OData stuff&amp;gt;&amp;amp;amp;$filter=Color eq ‘black'&lt;/code&gt; on the URL (you will probably get a &lt;code&gt;+&lt;/code&gt; symbol instead of a space from URL encoding).  This URL stuff will become part of the query's where clause and filter your data.  Since this is just a grid filter, your user can go in and edit it, clear it, etc.&lt;/p&gt;
&lt;p&gt;But what if you have more complex filtering needs?  What if you have multiple values or &amp;quot;or&amp;quot; logic instead of &amp;quot;and&amp;quot; logic?&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;filter: {
    logic: &amp;quot;or&amp;quot;,
    filters: [
        { field: &amp;quot;Name&amp;quot;, operator: &amp;quot;contains&amp;quot;, value: &amp;quot;fluffy&amp;quot; },
        { field: &amp;quot;Color&amp;quot;, operator: &amp;quot;eq&amp;quot;, value: &amp;quot;black&amp;quot; }
    ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will let you &amp;quot;or&amp;quot; your columns, so you are looking for Names containing &amp;quot;fluffy&amp;quot; &lt;strong&gt;or&lt;/strong&gt; Colors equal to &amp;quot;black&amp;quot;.  The URL will look like &lt;code&gt;/api/Cats/?&amp;lt;other OData stuff&amp;gt;&amp;amp;amp;$filter=(substringof(‘fluffy',Name) or Color eq ‘black')&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What if your filtering needs are more complex than this?  What if you have both &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot; logic you want to pass through to filter your OData?&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;filter: [
    {
        logic: &amp;quot;or&amp;quot;,
        filters: [
            { field: &amp;quot;Name&amp;quot;, operator: &amp;quot;contains&amp;quot;, value: &amp;quot;fluffy&amp;quot; },
            { field: &amp;quot;Color&amp;quot;, operator: &amp;quot;eq&amp;quot;, value: &amp;quot;black&amp;quot; }
        ]
    },
    {
        logic: &amp;quot;and&amp;quot;,
        filters: [
            { field: &amp;quot;Active&amp;quot;, operator: &amp;quot;eq&amp;quot;, value: true }
        ]
    }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The grid's filter property is smart enough to handle more complex JavaScript objects thrown at it, as long as is matches the filter pattern.  Take advantage of this to prefilter your grid data so those fancy OData queries don't send down values that aren't helpful for your end users.&lt;/p&gt;
</description>
      <pubDate>Wed, 22 May 2013 23:28:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/push-to-appharbor-on-every-push-to-github</guid>
      <link>https://volaresoftware.com/nl/technical-posts/push-to-appharbor-on-every-push-to-github</link>
      <title>Push to AppHarbor on every push to GitHub</title>
      <description>&lt;p&gt;If you're using &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt; as your shared, online, git repository and you're using &lt;a href="https://appharbor.com/"&gt;AppHarbor&lt;/a&gt; for continuous integration and deployment, you really have two git repositories – the GitHub one and the AppHarbor one.&lt;/p&gt;
&lt;p&gt;AppHarbor instructions help you set up a remote to this git repository so you can push to it whenever you like, but that means you have two steps on most commits:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-git"&gt;git push origin master
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to push your code up to your GitHub repo, and:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-git"&gt;git push appharbor master
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to push your code up to the AppHarbor repo.  Because AppHarbor doesn't support SSH yet (only HTTPS is supported now), you also have to enter your password.  Not a giant hassle, but what if you could get rid of that last little bit of friction?&lt;/p&gt;
&lt;h2 id="github-service-hooks"&gt;GitHub Service Hooks&lt;/h2&gt;
&lt;p&gt;GitHub Service Hooks run after a push to GitHub, and there is one to fire off your AppHarbor build/test/deploy.  It's under your GitHub repo &amp;gt; Admin &amp;gt; Service Hooks.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2011/10/image19.png" alt="image19.png" /&gt;&lt;/p&gt;
&lt;p&gt;Once you're there, the instructions are pretty simple.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to your application's main page on AppHarbor and find the &amp;quot;Create build URL&amp;quot;. Example: &lt;a href="https://appharbor.com/application/%7Bapplication_slug%7D/build?authorization=%7Btoken%7D"&gt;https://appharbor.com/application/{application_slug}/build?authorization=&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;quot;token&amp;quot; is the value of the &amp;quot;authorization&amp;quot; parameter.&lt;/li&gt;
&lt;li&gt;&amp;quot;application_slug&amp;quot; is your application's unique identifier.&lt;/li&gt;
&lt;li&gt;If your GitHub repository is private you need to add the &amp;quot;apphb&amp;quot; GitHub user as a collaborator. This enables AppHarbor to download the source code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here's where you can find the values for steps 1-3 in AppHarbor:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2011/10/image35.png" alt="image35.png" /&gt;&lt;/p&gt;
&lt;p&gt;Step #4 can be skipped if you have a public repo.  If you're using private repos, add the &amp;quot;apphb&amp;quot; GitHub user to a GitHub team with &amp;quot;pull&amp;quot; grants.&lt;/p&gt;
&lt;h2 id="all-done"&gt;All done!&lt;/h2&gt;
&lt;p&gt;Next time you do&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-git"&gt;git push origin master
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;your code will be pushed up to GitHub and AppHarbor will grab the latest code from GitHub (not from the AppHarbor repo anymore), build it, test it, and if the tests pass, deploy it.  All in one step!&lt;/p&gt;
</description>
      <pubDate>Wed, 12 Oct 2011 00:40:07 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/whats-new-in-mvc-2</guid>
      <link>https://volaresoftware.com/nl/technical-posts/whats-new-in-mvc-2</link>
      <title>What's New in MVC 2?</title>
      <description>&lt;p&gt;Thanks to all the folks who attended the &lt;a href="http://www.southcolorado.net/"&gt;South Colorado .NET User Group&lt;/a&gt; Visual Studio 2010 launch on May 6th.  We went through a giant buffet of new things in Visual Studio, Entity Framework, SharePoint, Silverlight, and ASP.NET.  &lt;a href="https://github.com/VolareSoftware/Presentations/tree/master/What%27s%20New%20in%20MVC%202%20-%20Colorado%20Springs%20.NET%20Group"&gt;Slides from my talk on the new features in MVC 2 can be downloaded here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Big thanks also to &lt;a href="http://twitter.com/benhnet"&gt;Ben Hoelting&lt;/a&gt; for putting the event together.  I liked the mini code camp format!  It was a lot of info, but it was a great survey of most of the new features.&lt;/p&gt;
</description>
      <pubDate>Wed, 12 May 2010 04:00:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/faster-karma-test-runs-that-work-in-vsts-with-chrome-headless-browser</guid>
      <link>https://volaresoftware.com/nl/technical-posts/faster-karma-test-runs-that-work-in-vsts-with-chrome-headless-browser</link>
      <title>Faster Karma test runs that work in VSTS with Chrome headless browser</title>
      <description>&lt;p&gt;&lt;a href="https://karma-runner.github.io/1.0/index.html"&gt;Karma&lt;/a&gt; is a well known framework-agnostic test runner. It's the glue between your JavaScript tests and your test results.&lt;/p&gt;
&lt;p&gt;Because Karma doesn't care what test framework, assertion library, or browser you use, configuration can be a bit of a headache. You have to specify everything.&lt;/p&gt;
&lt;p&gt;Most examples I've seen use &lt;a href="http://phantomjs.org/"&gt;PhantomJS&lt;/a&gt; as a headless browser, and it works ok. But on my current project, we have 4,700+ JavaScript tests written with Jasmine. When I run those tests manually through Chrome using the Jasmine stock HTML test runner, the tests run in just over 15 seconds.  When I run those same tests from the command line or the build server using Karma and PhantomJS, the tests run in about 1.5 minutes – much slower.&lt;/p&gt;
&lt;p&gt;I was looking for something faster that would work well both locally and on the build server, and the new-ish Chrome headless browser sounded promising. After getting it set up and working, the Karma tests with Chrome headless as the browser now run in under 10 seconds. Yay!&lt;/p&gt;
&lt;p&gt;Here's a step-by-step to getting it set up with the minimum configuration.&lt;/p&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;p&gt;To install, first make sure you've got &lt;a href="https://nodejs.org/en/download/"&gt;Node installed&lt;/a&gt; and then run:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;npm install karma --save-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This installs &lt;code&gt;karma&lt;/code&gt; for this project. Then:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;npm install karma-cli -g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This installs the &lt;code&gt;karma-cli&lt;/code&gt; globally for this computer. Next:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;npm install karma-jasmine karma-chrome-launcher jasmine-core --save-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This installs common plugins we'll need for this project: &lt;code&gt;karma-jasmine&lt;/code&gt;, &lt;code&gt;karma-chrome-launcher&lt;/code&gt; and &lt;code&gt;jasmine-core&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, we will install &lt;a href="https://github.com/GoogleChrome/puppeteer"&gt;Puppeteer&lt;/a&gt;, an API for Chrome's headless browser. If you are not running your JavaScript tests on your build server, you can skip this step. I was able to get my local Chrome headless browser running without this, but I needed this installed for my build server, Visual Studio Team Services (VSTS).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;npm install puppeteer --save-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once &lt;code&gt;puppeteer&lt;/code&gt; is installed for this project, it's time to configure things.&lt;/p&gt;
&lt;h3 id="configuration"&gt;Configuration&lt;/h3&gt;
&lt;p&gt;You need to specify all the settings for Karma because it doesn't know anything about your project.  It's like the opposite of zero-config - it's infinite-config.&lt;/p&gt;
&lt;p&gt;Recognizing this, the Karma team came up with a bunch of simple questions to get most of what you need added to your config file.  From the command line, run:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;karma init karma.conf.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pick &lt;code&gt;jasmine&lt;/code&gt; for the testing framework, &lt;code&gt;no&lt;/code&gt; for RequireJS (unless you need that), &lt;code&gt;Chrome&lt;/code&gt; for the browser (we'll adjust this later), and &lt;code&gt;src/**/*.js&lt;/code&gt; and &lt;code&gt;tests/**/*-tests.js&lt;/code&gt; for the source and test files (unless you prefer a different folder/filename pattern), and &lt;code&gt;yes&lt;/code&gt; that we'll let the watcher keep an eye on file changes.&lt;/p&gt;
&lt;p&gt;This is what mine looked like:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/2/karma-conf-js_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/2/karma-conf-js_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;Next, open &lt;code&gt;package.json&lt;/code&gt; in the project root and &lt;code&gt;scripts&lt;/code&gt; section if you don't already have one at the top level.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;&amp;quot;scripts&amp;quot;: {
  &amp;quot;test&amp;quot;: &amp;quot;karma start&amp;quot;
},
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This addition let's us run the tests from the command line with &lt;code&gt;npm test&lt;/code&gt; or &lt;code&gt;karma start&lt;/code&gt;. This is very helpful for build servers, like VSTS, which know about Node and npm, but not about Karma. Running &lt;code&gt;npm test&lt;/code&gt; as an npm task on VSTS works nicely.&lt;/p&gt;
&lt;h3 id="write-a-sample-test"&gt;Write a sample test&lt;/h3&gt;
&lt;p&gt;We won't know if it's working until we write a test and see it fail and then see it pass.  Let's do that now.&lt;/p&gt;
&lt;p&gt;Add a new file under &lt;code&gt;/tests&lt;/code&gt; named &lt;code&gt;sample-tests.js&lt;/code&gt;. This file should get picked up by our glob pattern in &lt;code&gt;karma.conf.js&lt;/code&gt;. Add this code to it:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;describe(&amp;quot;Testing Karma with Chrome headless&amp;quot;, () =&amp;gt; {
&lt;pre&gt;&lt;code&gt;it(&amp;amp;quot;Should work if configuration is correct&amp;amp;quot;, () =&amp;amp;gt; {
  expect(false).toBeTruthy();
}); 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;});
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You would never write this kind of test for a real project, but we just want to know if we've got everything working. This test should fail. Let's run it and see. From the command line, enter:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;karma start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see a failing test like this.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/2/failing_test_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/2/failing_test_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;You can use CTRL-C to break from the watch if you need to. Change the test so the assert is:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;expect(true).toBeTruthy();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and save. As soon as you save the changes in the test file, the watcher should re-run the tests and you should see this.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/2/passing_test_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/2/passing_test_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you don't have a passing test this point, go back and see if you missed a step or download from the &lt;a href="https://github.com/VolareSoftware/KarmaWithChromeHeadless"&gt;GitHub repository&lt;/a&gt; and try running from that code.&lt;/p&gt;
&lt;h3 id="chrome-headless"&gt;Chrome Headless&lt;/h3&gt;
&lt;p&gt;When the tests run, Karma creates a web server, opens Chrome, and runs the tests using the Chrome browser. You can see it running. But we want the headless Chrome browser for speed and to keep that extra browser out of the way.&lt;/p&gt;
&lt;p&gt;Use CTRL-C to cancel the watch Karma is running so we can kick it off again when we've made our changes. Open &lt;code&gt;karma.conf.js&lt;/code&gt; and find the &lt;code&gt;browsers&lt;/code&gt; section.  Change it to:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;browsers: ['ChromeHeadless'],
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the token used to specify the headless (not visible) version of Chrome. There are &lt;a href="https://npmjs.org/browse/keyword/karma-launcher"&gt;a lot more browsers you can choose from&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next, find the &lt;code&gt;singleRun&lt;/code&gt; section and change it to:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;singleRun: true,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and save. This is needed for your build server, or at least if your build server is VSTS.&lt;/p&gt;
&lt;p&gt;Re-run with &lt;code&gt;karma start&lt;/code&gt;. You should get similar results, with a passing test, but now it says the browser is &lt;code&gt;HeadlessChrome&lt;/code&gt;. Also, the test stops and returns to the command prompt when completed instead of staying in watch mode.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://volaresystems.com/blog/image.axd?picture=chrome_headless.png"&gt;![chrome_headless_thumb.png](https://cdn.volaresoftware.com/images/posts/2018/2/chrome_headless_thumb.png)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I don't really care for the watch running all the time on tests, as I prefer to run my tests manually, so I usually turn&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;autoWatch: false,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;in &lt;code&gt;karma.conf.js&lt;/code&gt;. I also don't like a lot of chatter in my test output, so I also set&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;logLevel: config.LOG_ERROR,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when I run the tests, I get just the last line from above. That's more like it!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/2/final_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/2/final_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;All the code for this post can be found on &lt;a href="https://github.com/VolareSystems/KarmaWithChromeHeadless"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Mon, 12 Feb 2018 08:30:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/specflow-isnt-just-a-watin-wrapper</guid>
      <link>https://volaresoftware.com/nl/technical-posts/specflow-isnt-just-a-watin-wrapper</link>
      <title>SpecFlow isn't just a WatiN Wrapper</title>
      <description>&lt;p&gt;I have been using &lt;a href="http://specflow.org/"&gt;SpecFlow&lt;/a&gt; with &lt;a href="http://watin.sourceforge.net/"&gt;WatiN&lt;/a&gt; for about 9 months now.  It's a great combination for driving the features you want in a web site and verifying they work as expected.  SpecFlow takes care of the &lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;BDD&lt;/a&gt; framework and application features side, while WatiN drives the browser to verify behavior.&lt;/p&gt;
&lt;p&gt;I've gotten used to the the pattern of writing a SpecFlow scenario, then writing the WatiN code in the step definition to open a browser and perform the task or look for the expected HTML.  Once you get the hang of the tools and the process, it's a very sustainable workflow for the developer.&lt;/p&gt;
&lt;p&gt;But today I ran into something that I couldn't test with WatiN.  I wanted to check that an XML sitemap was coming up correctly on a web site.  WatiN was able to open the XML document in the browser, but there was no Body tag because the XML is not an HTML document, so WatiN couldn't read the XML.  All I needed to do was verify that an expected value was in the XML sitemap.  If the value was found, the test would pass.&lt;/p&gt;
&lt;p&gt;I spent about 15 minutes trying out different WatiN commands to find the text, but with no Body tag, there was nothing loaded into the WatiN object model, so nothing was working.  I also tried looking through the WatiN Elements collection and a few other dead ends, but it was only showing me the previous web page or null.&lt;/p&gt;
&lt;p&gt;Finally, the obvious answer occurred to me.  I'm looking at an XML document and I want to verify that it has a value in it.  I'm in a SpecFlow step definition and I've got the entire .NET framework at my disposal, not just WatiN.  Five minutes later, I've got it coded to load and examine an XDocument for the value I needed so the test can pass.&lt;/p&gt;
&lt;p&gt;This was a good lesson for me.  Being on a development workflow roll is no excuse to not keep your head up for alternative strategies that would better solve your problem.  SpecFlow isn't just a wrapper for WatiN calls.  It can be used to verify any behavior it can invoke.&lt;/p&gt;
</description>
      <pubDate>Wed, 05 Jan 2011 01:40:28 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/fix-for-cisco-anyconnect-hanging-on-hostscan-is-waiting-for-the-next-scan</guid>
      <link>https://volaresoftware.com/nl/technical-posts/fix-for-cisco-anyconnect-hanging-on-hostscan-is-waiting-for-the-next-scan</link>
      <title>Fix for Cisco AnyConnect hanging on Hostscan is waiting for the next scan</title>
      <description>&lt;p&gt;Welcome Coronavirus work-from-home folks trying to get their Cisco AnyConnect VPN working! I wrote this article about a year and a half ago but have recently refreshed it.&lt;/p&gt;
&lt;p&gt;If solution below still works for you, please leave a comment below. Thanks, and happy social distancing! :)&lt;/p&gt;
&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;If you use Fiddler to watch network traffic on your computer, it creates personal certificates that interfere with Cisco AnyConnect VPN.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Inside Fiddler, choose &lt;code&gt;Tools&lt;/code&gt; &amp;gt; &lt;code&gt;Fiddler Options&lt;/code&gt; &amp;gt; &lt;code&gt;HTTPS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click the certificate maker. Click &amp;quot;Clear server certificates on Exit.&amp;quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You may have to reboot to clear memory, but you should be able to use  your VPN normally after that.&lt;/p&gt;
&lt;h2 id="backstory"&gt;Backstory&lt;/h2&gt;
&lt;p&gt;I use Cisco AnyConnect to connect to a client's VPN. Lately, it started hanging with the status message &amp;quot;Hostscan is waiting for the next scan&amp;quot;.&lt;/p&gt;
&lt;p&gt;The logs show a loop that lasts a little over 10 minutes where it scans and starts over until it finally gives up.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-batch"&gt;9:42:46 AM Hostscan state idle
9:42:48 AM Hostscan is waiting for the next scan
9:43:50 AM Hostscan is performing system scan
9:43:51 AM Hostscan is performing software scan
9:43:58 AM Hostscan state idle
9:44:00 AM Hostscan is waiting for the next scan
9:45:03 AM Hostscan is performing system scan
9:45:04 AM Hostscan is performing software scan
9:45:19 AM Hostscan state idle
9:45:22 AM Hostscan is waiting for the next scan
9:46:24 AM Hostscan is performing system scan
9:46:24 AM Hostscan is performing software scan
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I read something about removing personal certificates helping with this, but I only have a few personal certificates, and they are my machine name, &lt;code&gt;localhost&lt;/code&gt;, local development, and something NVIDIA put on there.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/12/image_thumb_46.png" alt="https://cdn.volaresoftware.com/images/posts/2018/12/image_thumb_46.png" /&gt;&lt;/p&gt;
&lt;h2 id="solution"&gt;Solution&lt;/h2&gt;
&lt;p&gt;But then I read something else about personal certificates in IE11.  Sure enough, under Tools (or the gear icon) &amp;gt; Internet Options &amp;gt; Content there is a button for Certificates.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/12/image_thumb_47.png" alt="https://cdn.volaresoftware.com/images/posts/2018/12/image_thumb_47.png" /&gt;&lt;/p&gt;
&lt;p&gt;After clicking that, I saw something very different from the machine certificates. They were there, plus some other certificates for local development, but there were HUNDREDS like &lt;code&gt;*.somewebsite.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I sorted by the name, selected them, and removed them. Then I tried Cisco AnyConnect again, and it finally connected.&lt;/p&gt;
&lt;p&gt;The wildcard certificates I saw in the IE11 Internet Options were created by &lt;a href="https://www.telerik.com/fiddler"&gt;Fiddler&lt;/a&gt;, which I use to watch network traffic and inspect web requests and responses. Fiddler acts as a proxy between your computer and your internet connection, and I guess it creates a personal wildcard certificate for every site you visit, or when Dropbox syncs, or your email does a send/receive, etc.&lt;/p&gt;
&lt;p&gt;Since I must use Cisco AnyConnect for the VPN and I only use Fiddler sometimes, I removed the wildcard certificates and uninstalled Fiddler and I've been able to connect to the VPN reliably for a week now.&lt;/p&gt;
</description>
      <pubDate>Wed, 11 Mar 2020 13:34:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/stop-wasting-time-with-enums-in-c</guid>
      <link>https://volaresoftware.com/nl/technical-posts/stop-wasting-time-with-enums-in-c</link>
      <title>Stop wasting time with enums in C#</title>
      <description>&lt;p&gt;Enums in C# can make you code easier to read:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;private enum Status
{
    Awesome = 1,
    Cool = 2
};
&lt;p&gt;public void Sample()
{
var lego = new Lego();&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;lego.Everything = Status.Awesome;
if (lego.PartOfTeam == true)
{
    lego.Everything = Status.Cool;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;But enums don't cross in and out of C# easily.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Have you ever tried to save an enum to SQL?  It becomes an &lt;code&gt;int&lt;/code&gt; and you're right back to, &amp;quot;Wait, what does a Status of 2 mean again?&amp;quot;.&lt;/p&gt;
&lt;p&gt;It's easy convert the enum to a &lt;code&gt;string&lt;/code&gt; before sending it to SQL, but then you have to convert it back to an enum in C# when you read it in, and that code is gross:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public string ConvertEnumToString(Status status)
{
   return status.ToString();
}
&lt;p&gt;public Status ConvertStringToEnum(string status)
{
return (Status) Enum.Parse(typeof (Status), status);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;What about sending the value down to the client in JSON?  Again, by default you get an &lt;code&gt;int&lt;/code&gt; that looses the point of having the enum in the first place.&lt;/p&gt;
&lt;p&gt;That is, unless you want to add enum converters from Json.NET to your &lt;code&gt;JsonSerializer&lt;/code&gt; to turn them into strings:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="thats-not-so-bad.plus-whats-the-alternative"&gt;That's not so bad.  Plus, what's the alternative?&lt;/h2&gt;
&lt;p&gt;The simplest alternatives are primitive types that convert across all layers, like &lt;code&gt;ints&lt;/code&gt; and &lt;code&gt;strings&lt;/code&gt;.  I prefer &lt;code&gt;strings&lt;/code&gt; so I can immediately know what the value represents and code around that (e.g., the Status is &amp;quot;Cool&amp;quot; instead of 2).&lt;/p&gt;
&lt;p&gt;&amp;quot;But this is using magic &lt;code&gt;strings&lt;/code&gt;, and those are bad.&amp;quot;  Maybe.  But 1) everyone likes magic, and 2) what's the risk?&lt;/p&gt;
&lt;p&gt;That you mistype the &lt;code&gt;string&lt;/code&gt;? There is type-safety risk, but it's a mild one and only applies to C#.  Let's say you're in JavaScript and looking for that status of &amp;quot;Coll&amp;quot; instead of &amp;quot;Cool&amp;quot;.  That code will fail.  How long until you figure that out? You'll have tests and/or run the code yourself and see it doesn't work, right?&lt;/p&gt;
&lt;p&gt;Also, if you work with a dynamic language, you know you can type in any nonsense and your compiler won't help you. It's up to you to test it. I see magic &lt;code&gt;strings&lt;/code&gt; the same way. Yes, you might make a mistake the compiler doesn't catch, but that's why we test our code.&lt;/p&gt;
&lt;p&gt;What about the risk that the value changes in the future.  Let's say management decides that statuses of &amp;quot;Awesome&amp;quot; are too strong.  They want you to change all occurrences of &amp;quot;Awesome&amp;quot; to &amp;quot;Good&amp;quot; throughout the app.  What's the damage here?&lt;/p&gt;
&lt;p&gt;Well if you have C# enums, you change &lt;code&gt;Status.Awesome&lt;/code&gt; to &lt;code&gt;Status.Good&lt;/code&gt; everywhere, then you update you SQL data so old records are correct (only needed if you converted the enum values to &lt;code&gt;strings&lt;/code&gt; before storing them), then you update your JavaScript so it doesn't look for or branch on the wrong &lt;code&gt;string&lt;/code&gt; (again, only needed if you serialized your C# enums to strings).&lt;/p&gt;
&lt;p&gt;If you didn't use enums at all, and just used &lt;code&gt;strings&lt;/code&gt; in C#, you would have the same SQL and JavaScript updating to do, but maybe more C# &lt;code&gt;strings&lt;/code&gt; to find/replace throughout the project. But I don't think you can reasonably say that's a lot more work. Maybe a few minutes more?&lt;/p&gt;
&lt;p&gt;On top of that, what's the risk that enums change in the future like this. It's not zero, but it's really low. Enum values should be immutable and usually represent the type or state of something, so enum values don't change their meanings very often.&lt;/p&gt;
&lt;p&gt;So why go to the trouble to store C# values in a special type that SQL and JavaScript can't work with? A magic &lt;code&gt;string&lt;/code&gt; is just as easy to read as the enum, and it works up and down the stack.&lt;/p&gt;
&lt;p&gt;Here's the original code, but with magic &lt;code&gt;string&lt;/code&gt;s instead of enums. I don't think it loses any clarity:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public void Sample()
{
    var lego = new Lego();
&lt;pre&gt;&lt;code&gt;lego.Everything = &amp;amp;quot;Awesome&amp;amp;quot;;
if (lego.PartOfTeam == true)
{
    lego.Everything = &amp;amp;quot;Cool&amp;amp;quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="concerns-with-this-approach"&gt;Concerns with this approach&lt;/h2&gt;
&lt;p&gt;This post has generated a lot of comments! It's been a good discussion on the tradeoffs of using C# enums. Some people have agreed with me that it is simpler to use magic &lt;code&gt;strings&lt;/code&gt; because they work across languages.&lt;/p&gt;
&lt;p&gt;Some have worried about database space used storing &lt;code&gt;strings&lt;/code&gt; vs. &lt;code&gt;ints&lt;/code&gt;. &lt;code&gt;Strings&lt;/code&gt; do take up more disk space, but I'd argue we're living in the age of not worrying about that, so take advantage of it. Others have pointed out databases can sort, index, and pull &lt;code&gt;ints&lt;/code&gt; faster than &lt;code&gt;strings&lt;/code&gt;. If storage costs or milliseconds matter in your situation, you'll need to factor that in.&lt;/p&gt;
&lt;p&gt;Others have agreed with the point that enum conversions can be messy, but think I've gone too far with magic &lt;code&gt;strings&lt;/code&gt; everywhere. The consensus with this crowd seems to be maybe skip enums, but &lt;em&gt;at least&lt;/em&gt; use C# static classes. I like this, and that's what I'm doing these days:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public static class Status
{
    public const string Awesome = &amp;quot;Awesome&amp;quot;;
    public const string Cool = &amp;quot;Cool&amp;quot;;
}
lego.Everything = Status.Awesome;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Still others want their C# enums just like they are and don't mind converting in JavaScript and SQL if needed.&lt;/p&gt;
&lt;p&gt;It's up to you to decide what makes the most sense for your project.&lt;/p&gt;
</description>
      <pubDate>Sun, 12 Apr 2020 04:29:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/using-crm-auto-filtering-in-custom-reports-with-complex-sql</guid>
      <link>https://volaresoftware.com/nl/technical-posts/using-crm-auto-filtering-in-custom-reports-with-complex-sql</link>
      <title>Using CRM auto filtering in custom reports with complex SQL</title>
      <description>&lt;p&gt;Report prefiltering in Microsoft CRM 4.0 is a very cool feature - when it works.  The normal ways of setting up this auto filtering feature in your custom CRM reports are 1) special aliases, and 2) SQL strings.&lt;/p&gt;
&lt;h2 id="special-aliases"&gt;Special aliases&lt;/h2&gt;
&lt;p&gt;The alias approach is the simplest one to use.  If you have a report that needs prefiltering, change your SQL from this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;select firstname, lastname 
from FilteredContact
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;select firstname, lastname 
from FilteredContact AS CRMAF_FilteredContact
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The trick is the alias.  All you need to do is add an alias with &lt;code&gt;CRMAF\_&lt;/code&gt; in front of the view name, and CRM will rip out your SQL at report runtime and replace it with a custom SQL statement.  I think the acronym must stand for CRM Auto Filter.  By using a special alias CRM recognizes, the actual SQL run on your server will be similar to this, where contacts are prefiltered for city = 'Denver'.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;select firstname, lastname 
from (select contact0.* 
      from FilteredContact as contact0 
      where address1_city  = 'Denver') AS CRMAF_FilteredContact
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="sql-strings"&gt;SQL strings&lt;/h2&gt;
&lt;p&gt;The other route you can go is mash together SQL strings and get a parameter from CRM that is the prefilter SQL statement.  You've probably done this kind of this kind of thing before:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;declare @sqlstring varchar(max)
set @sqlstring = 'select firstname, lastname 
from (' + @CRM_FilteredContact + ') AS MyFilteredContacts '
exec (@sqlstring)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This really isn't bad when you have a small SQL statement, but you probably wouldn't need to create a custom CRM report if it was a simple SQL statement, right?  The CRM users could create their own simple report inside CRM for that.&lt;/p&gt;
&lt;p&gt;When the SQL statement gets complex, you have quote and string bugs.  When the SQL gets lengthy, you can't have over a certain number of characters in the SQL string or you have to split it and you end up with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;exec (@sqlstring1 + @sqlstring2 + @sqlstring3)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can get it to work, but it's pretty yucky.&lt;/p&gt;
&lt;h2 id="the-problem"&gt;The problem&lt;/h2&gt;
&lt;p&gt;I much prefer the alias approach.  It's much easier to read, and the aliases are not too much trouble to add in and get prefiltering in CRM for free.&lt;/p&gt;
&lt;p&gt;The problem is, the alias technique breaks down when the queries get more complex or you need multiple datasets in your report using the same prefiltering.  Here are the cases I've found and the workarounds.&lt;/p&gt;
&lt;h2 id="dataset-based-on-a-union-query"&gt;Dataset based on a union query&lt;/h2&gt;
&lt;p&gt;If you have a query with a union statement, like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;select firstname, lastname 
from FilteredContact AS CRMAF_FilteredContact
where address1_city = 'Denver'
union
select firstname, lastname 
from FilteredContact AS CRMAF_FilteredContact
where address1_city = 'Highlands Ranch'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;CRM will do the alias filtering trick, &lt;strong&gt;but only for the first select&lt;/strong&gt;.  The second select in this query will not be filtered at all.&lt;/p&gt;
&lt;p&gt;The fix I've come up with uses SQL temp tables.  Maybe not the best approach, but I had a lot of reports that were not auto filtering as expected, and this has worked so far:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;select * 
into #FilteredContact
from FilteredContact AS CRMAF_FilteredContact
&lt;p&gt;select firstname, lastname
from #FilteredContact
where address1_city = 'Denver'
union
select firstname, lastname
from #FilteredContact
where address1_city = 'Highlands Ranch'&lt;/p&gt;
&lt;p&gt;drop table #FilteredContact
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This let's CRM do what it wants to, and swaps out your SQL where it finds the &lt;code&gt;CRMAF\_FilteredContact&lt;/code&gt; alias the first time.  It also let's you leave the rest of your SQL pretty much intact.&lt;/p&gt;
&lt;h2 id="dataset-based-on-multiple-queries-selecting-into-a-temp-table"&gt;Dataset based on multiple queries selecting into a temp table&lt;/h2&gt;
&lt;p&gt;I had another query that was suffering the same problem, but this query was a little different.  I needed the data displayed in columns, so I created a temp table and populated it with selects.  There were multiple selects in the query filling up the columns in this temp table.  Everything ran great without auto filtering.&lt;/p&gt;
&lt;p&gt;But with auto filtering, the same thing happened.  The first select statement got filtered.  The ones after that were untouched.  The fix I used was the same.  I created a temp table, populated it with the auto filtered data, then selected off that temp table throughout.&lt;/p&gt;
&lt;p&gt;To be a good TempDB citizen, I dropped the temp table at the end of the query.  SQL Server does the temp table drop for you when the table is out of scope, but it helps to have the drop statement in there when testing the query in SQL Server Management Studio and running it multiple times in the same query window.&lt;/p&gt;
&lt;h2 id="reports-with-multiple-datasets"&gt;Reports with multiple datasets&lt;/h2&gt;
&lt;p&gt;This technique works if you have a complex query that needs auto filtering.  But what if you have multiple datasets in your report, and they all need to be auto filtered?&lt;/p&gt;
&lt;p&gt;In one report, the queries were very similar.  I had two datasets that were identical expect one used report parameter A and one used report parameter B.  This was to compare two funnels for two different time periods.  Auto filtering worked fine on the first dataset and funnel, but didn't do anything on the second dataset or funnel.&lt;/p&gt;
&lt;p&gt;The fix in this case was to create one dataset that didn't filter on either report parameter A or parameter B.  Then in the report, have the funnel controls themselves do the filtering based on the report parameters.  Most SQL Server Reporting Services data controls have a filter property.  I've never really used them before now, since it almost never makes sense to pull all the data from the database and then filter inside the report.  I'd rather filter on the database first.  However, in this case, the control filters helped and I got the result I wanted because there was one dataset with one &lt;code&gt;CRMAF\_ alias&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On another report, there were three charts built using three different datasets.  The datasets were the same except for the group by clause.  I was able to use the same approach and condense these to one dataset with no group by clause, then do the grouping in the chart controls.  Again, it made me feel a little bad that the data wasn't already summed and grouped when it got to the chart control, but at least it was working.&lt;/p&gt;
</description>
      <pubDate>Mon, 14 Feb 2011 01:40:20 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/rest-like-behavior-with-mvc-instead-of-wcf</guid>
      <link>https://volaresoftware.com/nl/technical-posts/rest-like-behavior-with-mvc-instead-of-wcf</link>
      <title>REST-like behavior with MVC instead of WCF</title>
      <description>&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms735119.aspx"&gt;WCF&lt;/a&gt; is a very cool framework for adding an abstraction layer over your services.  You can have .asmx, .svc, and now, &lt;a href="http://msdn.microsoft.com/en-us/netframework/cc950529.aspx"&gt;REST&lt;/a&gt; URLs with no extension.  These endpoints can even return &lt;a href="http://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt; to the caller, which is useful if you're using &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; or another JavaScript library.&lt;/p&gt;
&lt;p&gt;The knock on WCF?  The configuration story!  It's &lt;a href="http://microsoftpdc.com/Sessions/FT13"&gt;getting&lt;/a&gt; &lt;a href="http://blogs.microsoft.co.il/blogs/stiller/archive/2009/11/19/pdc-2009-day-3-what-s-new-in-wcf-4-0.aspx"&gt;better&lt;/a&gt; in WCF 4, which is scheduled for release in a month or so.  It will have a bunch of defaults so you don't have to be as explicit in your config file.  Finally, some &lt;a href="http://en.wikipedia.org/wiki/Convention_over_configuration"&gt;convention over configuration&lt;/a&gt; in the WCF space!  Now someone needs to create a fluent, code-based configuration tool for the exceptions to the default conventions…&lt;/p&gt;
&lt;h2 id="dont-be-afraid-of-json"&gt;Don't be afraid of JSON!&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2010/3/jason_thumb.jpg" alt="https://cdn.volaresoftware.com/images/posts/2010/3/jason_thumb.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;But if you need to return JSON to a caller today, you don't need scary WCF config files to do it.  You can get the same URL and the same data payload with a lot less hassle using MVC controller actions.&lt;/p&gt;
&lt;p&gt;The steps are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new action in a controller.&lt;/li&gt;
&lt;li&gt;Grab your data or whatever you want to return.&lt;/li&gt;
&lt;li&gt;Parse your data to JSON.&lt;/li&gt;
&lt;li&gt;Throw it back out to the requestor.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The trick is to use &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.jsonresult.aspx"&gt;JsonResult&lt;/a&gt; as the return type for your controller action and convert your output to a JSON string with the base controller's &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.json.aspx"&gt;Json&lt;/a&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public JsonResult GetAllDepartments()
{
    var departments = _repository.GetAllDepartments();
    return Json(departments);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now if I browse to this controller action (I'm using the HomeController in this example):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;u&amp;gt;http://localhost/Home/GetAllDepartments&amp;lt;/u&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I get a pop-up to save the response stream, which I can open with Notepad:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;[{&amp;quot;Name&amp;quot;:&amp;quot;Human Resources&amp;quot;},{&amp;quot;Name&amp;quot;:&amp;quot;Accounting&amp;quot;},{&amp;quot;Name&amp;quot;:&amp;quot;IT&amp;quot;},{&amp;quot;Name&amp;quot;:&amp;quot;Pencil Sharpening&amp;quot;}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yeah, JSON!  And there was no gory config setup needed!&lt;/p&gt;
&lt;h2 id="using-jquery-with-json"&gt;Using jQuery with JSON&lt;/h2&gt;
&lt;p&gt;Now we can use jQuery in the MVC view to take advantage of this returned JSON.&lt;/p&gt;
&lt;p&gt;Here's a view that has a button and a div tag.  jQuery is being used to tie the button click to a call to the controller and action we set up above.  It then gets the JSON coming back, loops through it, and puts it in the div tag so it's visible to the user.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&amp;lt;script src=&amp;quot;../../Scripts/jquery-1.3.2.min.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;p&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
$(function() {
$(&amp;quot;#btnShowDepartments&amp;quot;).click(function() {
$.getJSON(&amp;quot;/Home/GetAllDepartments&amp;quot;, null, function(data) {
for (item in data) {
var department = data[item];
$(&amp;quot;#divDepartments&amp;quot;).append(department.Name, &amp;quot;, &amp;quot;);
}
});&lt;br /&gt;
});
});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;p&amp;gt;
&amp;lt;input id=&amp;quot;btnShowDepartments&amp;quot; type=&amp;quot;button&amp;quot; value=&amp;quot;Show Departments&amp;quot; /&amp;gt;
&amp;lt;div id=&amp;quot;divDepartments&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This is probably not the best jQuery in the world.  I'm still new to it.  But the point is to show that you can put a URL in, parse the JSON, and use the data however your app needs it.&lt;/p&gt;
</description>
      <pubDate>Mon, 08 Mar 2010 01:40:57 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/is-aspnet-relevant-to-modern-web-development</guid>
      <link>https://volaresoftware.com/nl/technical-posts/is-aspnet-relevant-to-modern-web-development</link>
      <title>Is ASP.NET relevant to modern web development?</title>
      <description>&lt;p&gt;ASP.NET has a &lt;a href="http://www.asp.net/vnext"&gt;new version coming out soon&lt;/a&gt;.  ASP.NET vNext will have a new project file management system (long overdue) and a lot of integration points with modern front-end web development tooling, like Grunt and Bower.&lt;/p&gt;
&lt;p&gt;I'm a web developer, and all of the back-end systems I work with are Microsoft based (ASP.NET MVC and Web API, SQL Server, Azure, etc.).  I must be super excited about this new stuff coming soon, right?&lt;/p&gt;
&lt;p&gt;Nah, not really.&lt;/p&gt;
&lt;p&gt;Like most web developers, I spend a lot of time in HTML5 and CSS3 and tons of time in JavaScript.  I spend most of my energy getting front-end libraries to work together, making web pages responsive, dealing with cross-browser and cross-device issues, and debugging with browser tools.  Over the last several years, MVC, Web API, and even SQL Server have been less a part of my day-to-day coding, so changes and new versions matter less to me.&lt;/p&gt;
&lt;h3 id="just-another-back-end"&gt;Just another back end?&lt;/h3&gt;
&lt;p&gt;If you are a front-end web developer, you need your AJAX request to hit a back-end endpoint and give you a response.  That kind of framing of the back-end, that it can be encapsulated or black-boxed, also means its implementation could be changed and you wouldn't really care.  Why should it matter if the back end is written with node.js, Ruby on Rails, Java, Azure Mobile Services, or ASP.NET?  From the front-end web developer perspective, I just want a response.  Obviously, it needs to be fast, scalable, robust, secure, and that kind of thing, but all major server-side frameworks have that figured out.&lt;/p&gt;
&lt;p&gt;It seems to me that back-end tooling is becoming a commodity.  Here's what I mean.  Quick - which cloud provider is the best one?  I don't know.  Aren't they all about the same? Maybe they have different SLAs, or broader or narrower service offerings, but just to get a web app running with a database, they are all about the same.  If one was $5/month cheaper, wouldn't you switch to them?  Unless the support or extra services or the hassle of changing cloud providers were worth an extra $5/month to you, you'd switch.&lt;/p&gt;
&lt;p&gt;I think of ASP.NET and SQL Server the same way.  It's back-end tooling.  It involves maybe 10-25% of my coding week.  I'm not dissatisfied with the tools.  I just don't use them that much.  I guess they could get a little better, but that won't make me need to use them more or care more about how they are implemented.&lt;/p&gt;
&lt;p&gt;I don't send view models down with my MVC views anymore.  I just let MVC serve up a view-model-less view and let JavaScript and AJAX calls go get anything else the page needs.  This means the initial page loads fast, but it doesn't fully work until the JavaScript has finished putting everything in its place.&lt;/p&gt;
&lt;p&gt;Once you start spending a lot of time in JavaScript and pulling in data with AJAX, and you have to write it that way so the user can interact with the page, then why write it twice with 1) the Razor-template-populated-with-initial-view-model way, and 2) the HTML-template-populated-with-AJAX-data way?  Writing the same functionality with two templating languages and two data sources isn't going to get your project done faster or reduce maintenance costs.&lt;/p&gt;
&lt;p&gt;Plus, the user gets to see most of the page, just maybe without all the data yet or with empty drop downs while the data is still on its way to the page.  I think that gives the user a sense that we're getting you the parts of the page as soon as we can, instead of building everything up on the server as one big ball of templated data while you look at a white, empty browser window.&lt;/p&gt;
&lt;p&gt;So why not just dump the whole thing and code HTML, CSS, and JavaScript with any old text editor?&lt;/p&gt;
&lt;h3 id="where-does-the-microsoft-ecosystem-add-value-in-modern-web-development"&gt;Where does the Microsoft ecosystem add value in modern web development?&lt;/h3&gt;
&lt;h4 id="ide"&gt;IDE&lt;/h4&gt;
&lt;p&gt;In spite of its limitations for front-end development, Visual Studio is still a very good IDE.  Different colors for keywords and navigation within and across files is very good.  But most of the value I get from continuing to use Visual Studio is a result of the &lt;a href="http://vswebessentials.com/"&gt;Web Essentials&lt;/a&gt; extension.  It's nice to run JSHint with every save and to get pointers in the IDE about CSS rules, potential browser issues, and unclosed HTML tags.  If I switched to Notepad, I'd be giving up some things that really do make my coding day a little brighter.&lt;/p&gt;
&lt;p&gt;Working with the current Visual Studio project system has been more than just an annoyance; it's been a source of real pain.  Looks like the new project/file system may help in vNext.&lt;/p&gt;
&lt;p&gt;I can't say that Intellisense is very useful to me these days.  It's never really worked right with JavaScript.  Maybe that will get a little better, but I've gotten used to it pulling up every JavaScript symbol when I type &amp;quot;.&amp;quot;.&lt;/p&gt;
&lt;h4 id="local-web-server"&gt;Local Web Server&lt;/h4&gt;
&lt;p&gt;Simple and unobtrusive, IIS Express is a great place to test run your web app, and the integration with Visual Studio is limited but sufficient.&lt;/p&gt;
&lt;p&gt;The alternative would be HTML files that you double click to open and debug in the browser.  It would work, but you'd have to keep you file system and text editor open all the time, and you wouldn't have server-side debugging of your API layer.&lt;/p&gt;
&lt;h4 id="security"&gt;Security&lt;/h4&gt;
&lt;p&gt;Security is probably the main thing that has kept me from dumping ASP.NET and using HTML files instead.  I've never worked on a web app where security wasn't important.  You need a way to know who's knocking on the server's door, and when that request is bouncing around on the back-end servers, you need to know what group/role that user is in so you can turn features on and off.&lt;/p&gt;
&lt;p&gt;I still use MVC and Web API for their security, and I'm glad their namespaces are finally going to be merged in vNext.  That means I won't have any more code that filters MVC requests one way and Web API requests another way.&lt;/p&gt;
&lt;h4 id="api-layer"&gt;API layer&lt;/h4&gt;
&lt;p&gt;Web API is totally relevant for modern web development.  All web apps need a way of interacting with a back end, and Web API sets up as a simple, thin transport layer so you can do whatever back-end stuff you need to do on the server. Content negotiation is nice if you have a public API, but I've only written internal APIs that send/receive JSON.&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I guess I am looking forward to some of the improvements in ASP.NET vNext.&lt;/p&gt;
&lt;p&gt;If I was building a new web app today, would I use ASP.NET as the back end?  Probably, but it would be the same way I've used it the last 4-5 years: minimal MVC page serving, an API service layer, and a security layer.&lt;/p&gt;
&lt;p&gt;The most interesting, highest customer value web development stuff is happening on the front end, and I don't see that changing anytime soon.&lt;/p&gt;
</description>
      <pubDate>Mon, 29 Dec 2014 05:04:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/working-with-the-latest-javascript-syntax-on-your-project-today</guid>
      <link>https://volaresoftware.com/nl/technical-posts/working-with-the-latest-javascript-syntax-on-your-project-today</link>
      <title>Working with the latest JavaScript syntax on your project today</title>
      <description>&lt;p&gt;Are you working in an existing code base with tons of ES5 JavaScript, and you're jealous of your friends working on greenfield projects using ES6/ES7/ES8+ or ES2015/ES2016/ES2017+ JavaScript?  Here's how we moved our code base forward to start using newer features of JavaScript without losing our minds.&lt;/p&gt;
&lt;p&gt;I've made a sample project using the ASP.NET MVC default project (and removing some of the noise). You can &lt;a href="https://github.com/VolareSoftware/ECMAScriptWithBabelAndWebpack"&gt;see all the code&lt;/a&gt; if you want to follow along or fork this on GitHub.&lt;/p&gt;
&lt;h3 id="install-npm-packages"&gt;Install NPM packages&lt;/h3&gt;
&lt;p&gt;First, &lt;a href="https://nodejs.org/en/download/"&gt;install node and npm&lt;/a&gt;, then install &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt; and &lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt; from the command line in the web project root.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;npm install --save-dev babel-core babel-loader babel-preset-env
npm install --save-dev webpack webpack-cli
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you are done, you should have a  &lt;code&gt;devDependencies&lt;/code&gt; section in your &lt;code&gt;package.json&lt;/code&gt; file, also in the web root, that looks something like this. You will almost certainly have different versions, and you will probably have more than just this in your  &lt;code&gt;devDependencies&lt;/code&gt; section, and that's fine.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;&amp;quot;devDependencies&amp;quot;: {
  &amp;quot;babel-core&amp;quot;: &amp;quot;^6.26.0&amp;quot;,
  &amp;quot;babel-loader&amp;quot;: &amp;quot;^7.1.4&amp;quot;,
  &amp;quot;babel-preset-env&amp;quot;: &amp;quot;^1.6.1&amp;quot;,
  &amp;quot;webpack&amp;quot;: &amp;quot;^4.4.1&amp;quot;,
  &amp;quot;webpack-cli&amp;quot;: &amp;quot;^2.0.13&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="set-up-visual-studio"&gt;Set up Visual Studio&lt;/h2&gt;
&lt;p&gt;The plan is to leave old JavaScript files with the &lt;code&gt;*.js&lt;/code&gt; extension and create new ES2015+ JavaScript files with the &lt;code&gt;*.es6&lt;/code&gt; extension.  You can use &lt;code&gt;*.es2015&lt;/code&gt; or any other extension not already in use if you prefer.  We just need some file marker so webpack knows which files need Babel transpilation and which don't.&lt;/p&gt;
&lt;p&gt;In Visual Studio, you'll need to set up this new extension to use the JavaScript editor.  You can do that in Tools &amp;gt; Options &amp;gt; Text Editor &amp;gt; File Extension. If you skip this step, Visual Studio will treat &lt;code&gt;*.es6&lt;/code&gt; like text files instead of JavaScript files.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/4/image_thumb_42.png" alt="https://cdn.volaresoftware.com/images/posts/2018/4/image_thumb_42.png" /&gt;&lt;/p&gt;
&lt;h3 id="configure-webpack-and-babel"&gt;Configure webpack and Babel&lt;/h3&gt;
&lt;p&gt;Let's set up the &lt;code&gt;webpack.config.js&lt;/code&gt; file in the web root to work with the newer JavaScript syntax.&lt;/p&gt;
&lt;p&gt;Below, the &lt;code&gt;resolve&lt;/code&gt; section tells webpack we are using these two extensions for JavaScript files, and webpack should be looking for both &lt;code&gt;*.js&lt;/code&gt; and &lt;code&gt;*.es6&lt;/code&gt; files when making bundles.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;rules&lt;/code&gt; section tells webpack that it needs to use Babel to load &lt;code&gt;*.es6&lt;/code&gt; extension files. There are a lot more Babel options you can add here. For example, want to use async/await in your &lt;code&gt;*.es6&lt;/code&gt; files? Add a Babel &lt;code&gt;plugin&lt;/code&gt; for &lt;code&gt;syntax-async-functions&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;isRelease&lt;/code&gt; flag is used to toggle between development and production settings for the build. This is using webpack 4's new &lt;code&gt;mode&lt;/code&gt; setting, which should set up most things correctly. The &lt;code&gt;devtool&lt;/code&gt; option uses either a quick and dirty source map or a more production-ready one.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const path = require(&amp;quot;path&amp;quot;);
&lt;p&gt;module.exports = env =&amp;gt; {
const isRelease = env === &amp;quot;RELEASE&amp;quot;;
return {
mode: isRelease ? &amp;quot;production&amp;quot; : &amp;quot;development&amp;quot;,
devtool: isRelease ? &amp;quot;source-map&amp;quot; : &amp;quot;cheap-module-source-map&amp;quot;,
entry: {
index: &amp;quot;index.es6&amp;quot;,
about: &amp;quot;about.js&amp;quot;
},
output: {
filename: &amp;quot;[name].js&amp;quot;,
path: path.resolve(__dirname, &amp;quot;dist&amp;quot;),
publicPath: &amp;quot;/dist&amp;quot;
},
resolve: {
extensions: [&amp;quot;.js&amp;quot;, &amp;quot;.es6&amp;quot;],
modules: [&amp;quot;Scripts&amp;quot;, &amp;quot;node_modules&amp;quot;]
},
module: {
rules: [
{
test: /.es6$/,
exclude: /(node_modules)/,
use: {
loader: &amp;quot;babel-loader&amp;quot;,
options: {
presets: [&amp;quot;env&amp;quot;]
}
}
}
]
}
};
};
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="single-page-vs.multi-page-applications"&gt;Single-Page vs. Multi-Page applications&lt;/h3&gt;
&lt;p&gt;In the &lt;code&gt;entry&lt;/code&gt; section above, I've got two values for the two pages in this sample. &lt;code&gt;index&lt;/code&gt; will be built using the &lt;code&gt;index.es6&lt;/code&gt; file as an entry point, and &lt;code&gt;about&lt;/code&gt; will be built using &lt;code&gt;about.js&lt;/code&gt; as the entry point. If your whole app is a SPA, you will have just one entry. If you have a multi-page application, you'll need an entry for each page. Webpack crawls the entry to bundle up all the dependencies.&lt;/p&gt;
&lt;p&gt;We are outputting our files to a &lt;code&gt;/dist&lt;/code&gt; folder. For simplicity, the file name will be the entry name plus &amp;quot;.js&amp;quot;.&lt;/p&gt;
&lt;h3 id="scripts"&gt;Scripts&lt;/h3&gt;
&lt;p&gt;We needs some scripts to test out the different JavaScript syntax styles.&lt;/p&gt;
&lt;p&gt;Here is &lt;code&gt;index.es6&lt;/code&gt;, using the new JavaScript &lt;code&gt;import&lt;/code&gt; and templated string options.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import $ from &amp;quot;jquery&amp;quot;;
&lt;p&gt;$(&amp;quot;#setInCode&amp;quot;).text(&lt;code&gt;This value was set in code using jQuery at ${new Date().toLocaleString()}.&lt;/code&gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And here is &lt;code&gt;about.js&lt;/code&gt;, using older AMD-style modules and ES5 style JavaScript.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;define([&amp;quot;jquery&amp;quot;], function($) {
    $(&amp;quot;#setInCode&amp;quot;).text(&amp;quot;This value was set in code using jQuery at &amp;quot; + new Date().toLocaleString() + &amp;quot;.&amp;quot;);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These scripts both find an element with jQuery and set some text to it and add the date/time. We want something simple to test if our pages are working with both old and new-style JavaScript.&lt;/p&gt;
&lt;h3 id="script-references"&gt;Script references&lt;/h3&gt;
&lt;p&gt;Since I'm using a boilerplate ASP.NET MVC project template, the &lt;code&gt;_Layout.cshtml&lt;/code&gt; file already has:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;@RenderSection(&amp;quot;scripts&amp;quot;, required: false)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each page, such as &lt;code&gt;Index.cshtml&lt;/code&gt; and &lt;code&gt;About.cshtml&lt;/code&gt; will then reference the built-by-webpack scripts in the &lt;code&gt;/dist&lt;/code&gt; folder with. &lt;code&gt;Index.cshtml&lt;/code&gt; will reference &lt;code&gt;/dist/index.js&lt;/code&gt;, and &lt;code&gt;About.cshtml&lt;/code&gt; will reference &lt;code&gt;/dist/about.js&lt;/code&gt; like this.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;@section scripts
{
    &amp;lt;script src=&amp;quot;/dist/index.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="build-it"&gt;Build it&lt;/h3&gt;
&lt;p&gt;So we've got our npm packages installed, the &lt;code&gt;webpack.config.js&lt;/code&gt; file is set up, our pages call our webpack-built scripts in the&lt;code&gt;/dist&lt;/code&gt; folder . Let's run it and test it out.&lt;/p&gt;
&lt;p&gt;Add a new section for &lt;code&gt;scripts&lt;/code&gt; to your &lt;code&gt;package.json&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;&amp;quot;scripts&amp;quot;: {
  &amp;quot;build&amp;quot;: &amp;quot;webpack --colors --watch&amp;quot;,
  &amp;quot;build:release&amp;quot;: &amp;quot;webpack --colors --env RELEASE&amp;quot;
},
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allows us to run &lt;code&gt;npm build&lt;/code&gt; and &lt;code&gt;npm build:release&lt;/code&gt; as shortcuts for running webpack commands. You can name the commands anything you like.&lt;/p&gt;
&lt;p&gt;The options show colors in the console, and for the &lt;code&gt;build&lt;/code&gt; script, it sets up a watch on the files to re-run the build if anything changes. You'll want to use this for development. For the &lt;code&gt;build:release&lt;/code&gt; script, we pass in &lt;code&gt;—env RELEASE&lt;/code&gt; so the &lt;code&gt;webpack.config.js&lt;/code&gt; script knows we want the build optimized for production.&lt;/p&gt;
&lt;p&gt;You can also add another section to &lt;code&gt;package.json&lt;/code&gt; to link up these build commands to the Visual Studio Task Runner Explorer.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;&amp;quot;-vs-binding&amp;quot;: {
  &amp;quot;ProjectOpened&amp;quot;: [
    &amp;quot;build&amp;quot;
  ]
},
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will run your new &lt;code&gt;build&lt;/code&gt; command when the project opens. Since it keeps a watch running, that should be all you need to development.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/4/task_runner_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/4/task_runner_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;For production, you'll want to stop the &lt;code&gt;build&lt;/code&gt; task and manually run the &lt;code&gt;build:release&lt;/code&gt; task in the Task Runner Explorer (or run it from command line, or as a before/after build script for your ASP.NET project, or on your build server…).&lt;/p&gt;
&lt;h3 id="run-it"&gt;Run it&lt;/h3&gt;
&lt;p&gt;Run the web app after the &lt;code&gt;build&lt;/code&gt; command completes and you should be able to browse to the Index and About pages and see the jQuery execute in both pages the same way, even though the syntax for importing jQuery was very different for each page.&lt;/p&gt;
&lt;h3 id="debug-it"&gt;Debug it&lt;/h3&gt;
&lt;p&gt;Note we are referencing &lt;code&gt;index.js&lt;/code&gt; in &lt;code&gt;Index.cshtml&lt;/code&gt; and not the source code file name &lt;code&gt;index.es6&lt;/code&gt;. That's because we're not referencing the source code. We're referencing the webpack built code in the &lt;code&gt;/dist&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;Don't worry. You can still set breakpoints and watches and debug with your favorite browser dev tools when referencing the built code through source maps. When opening a file, look for the one served by &lt;code&gt;webpack://&lt;/code&gt;. It will be the original source code seen through the source map. The other file will be the bundled/minified one.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/4/open_this_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/4/open_this_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/debug_minified_javascript.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/debug_minified_javascript.png" /&gt;&lt;/p&gt;
&lt;h3 id="now-what"&gt;Now what?&lt;/h3&gt;
&lt;p&gt;If you are on a project that isn't using the newer JavaScript syntax and features, talk with your team. Chances are good they would like to be using the new stuff, too.&lt;/p&gt;
&lt;p&gt;You don't need to wait until you get put on a new project. You can start coding with the latest JavaScript syntax today, but still keep backward compatibility for your project's ES5 script.&lt;/p&gt;
</description>
      <pubDate>Tue, 03 Apr 2018 05:17:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/deploying-reports-built-with-ssrs-2008-r2-to-ssrs-2008-non-r2</guid>
      <link>https://volaresoftware.com/nl/technical-posts/deploying-reports-built-with-ssrs-2008-r2-to-ssrs-2008-non-r2</link>
      <title>Deploying Reports Built with SSRS 2008 R2 to SSRS 2008 non-R2</title>
      <description>&lt;p&gt;I've got SQL Server 2008 R2 Express installed on my primary development machine, and I create SSRS reports on this box.  The problem is, I've got one customer with SQL Server 2008.  And yes, Microsoft changed the RDL file format between SSRS 2008 and SSRS 2008 R2, so SSRS 2008 can't read SSRS 2008 R2 RDL files.&lt;/p&gt;
&lt;p&gt;So how you you get around this without setting up VMs with both?  It's not elegant, but here's what I do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On your SSRS project properties with all your reports, change the Target Server Version to SQL Server 2008 (and not SQL Server 2008 R2).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/3/snaghtmlab90e1b.png" alt="snaghtmlab90e1b.png" /&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Get your local dev box SSRS R2 server running if it's not already.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/3/snaghtmlabb1913.png" alt="snaghtmlabb1913.png" /&gt;&lt;/p&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Deploy the report project to your local SSRS R2 server.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/3/image_12.png" alt="image_12.png" /&gt;&lt;/p&gt;
&lt;ol start="4"&gt;
&lt;li&gt;Go to your report management site (usually http://localhost:Reports) and download the report.  This will save out the RDL for you.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/3/image6.png" alt="image6.png" /&gt;&lt;/p&gt;
&lt;ol start="5"&gt;
&lt;li&gt;Now when you deploy this report to the non-R2 SSRS server, it will be the correct, non-R2 format!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The crucial steps are setting that Target Server Version and deploying.  That's where the Visual Studio report project converts the RDL file to the format you need it to be.  After that, the downloading is just a way to get a copy of the report in the non-R2 format.&lt;/p&gt;
&lt;p&gt;Now you can deploy the RDL to the customer's non-R2 SSRS server, without changing your dev box.&lt;/p&gt;
</description>
      <pubDate>Mon, 19 Mar 2012 00:40:02 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/moving-a-vm-to-another-machine</guid>
      <link>https://volaresoftware.com/nl/technical-posts/moving-a-vm-to-another-machine</link>
      <title>Moving a VM to another machine</title>
      <description>&lt;p&gt;I've got a work laptop with a &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt; virtual machine.  But I wanted to move it to my slightly faster personal rig, with the nicer keyboard, mouse, dual monitors, etc.&lt;/p&gt;
&lt;p&gt;So I shut down the VM on the work laptop and copied it over to the personal machine.  Then I downloaded and installed the &lt;a href="http://www.vmware.com/download/player/download.html"&gt;VMware Player&lt;/a&gt; to the new machine, copied the VM to it, and opened it up.  I got a prompt asking if I &amp;quot;moved&amp;quot; or &amp;quot;copied&amp;quot; the VM.  I chose &amp;quot;copied&amp;quot;.&lt;/p&gt;
&lt;p&gt;The VM spun for a little while, and then there was some gibberish message about VT being possible but disabled on the host.  VT = Vermont?  VT = Virginia Tech? VT = WTF?  I did what professional developers are trained to do in these situations.  I ignored it and clicked OK.&lt;/p&gt;
&lt;p&gt;The VM said &amp;quot;Windows in Loading Files.&amp;quot; but it kept rebooting over, and over, and over.&lt;/p&gt;
&lt;p&gt;I got a tip from &lt;a href="http://blog.davidyack.com/"&gt;David Yack&lt;/a&gt; to check the BIOS settings.  I have a &lt;a href="http://www.dell.com/latitude"&gt;Dell Latitude&lt;/a&gt;, so your mileage may vary here, but in &lt;strong&gt;my&lt;/strong&gt; BIOS settings, I go to &lt;code&gt;Post Behavior&lt;/code&gt;, then &lt;code&gt;Virtualization&lt;/code&gt;, then set it to &lt;code&gt;Enabled&lt;/code&gt;, then save settings and reboot.&lt;/p&gt;
&lt;p&gt;That worked!&lt;/p&gt;
</description>
      <pubDate>Tue, 17 Nov 2009 01:41:16 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/a-quick-look-at-ndepend</guid>
      <link>https://volaresoftware.com/nl/technical-posts/a-quick-look-at-ndepend</link>
      <title>A quick look at NDepend</title>
      <description>&lt;p&gt;&lt;a href="https://www.ndepend.com/"&gt;NDepend&lt;/a&gt; is a Visual Studio extension designed to help you improve your code quality and reduce your technical debt. It sells for €399 per developer, which is about $462 U.S.&lt;/p&gt;
&lt;p&gt;I gave it a try a very small project and a very large project. You open your project in Visual Studio, point NDepend at it, and wait a minute or so for the reports.&lt;/p&gt;
&lt;p&gt;NDepend spits out a lot of reports and a lot of metrics, from dependency graphs to tree maps with hot spots showing too much cyclomatic complexity in red.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/ndepend_diagrams.jpg" alt="https://cdn.volaresoftware.com/images/posts/2019/12/ndepend_diagrams.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Here are the small project application metrics:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/ndepend_application_metrics.jpg" alt="https://cdn.volaresoftware.com/images/posts/2019/12/ndepend_application_metrics.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;NDepend gives some basic counts and rule and quality checks, but the most interesting data is the technical debt. Here, both apps get an &amp;quot;A&amp;quot;, but they have 3.69% and 4.81% tech debt. This didn't print out as nicely on my projects as the demo report from NDepend shown below.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/ndepend_stats.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/ndepend_stats.png" /&gt;&lt;/p&gt;
&lt;p&gt;Here you can see the estimated time to bring your tech debt up a letter grade, from a C to a B, is 14 days and 2 hours. The estimated annual interest on your tech debt is 47 days, and that's up 17 days and 4 hours from the last time the analysis was run.&lt;/p&gt;
&lt;p&gt;When you drill into the errors and warnings NDepend shows you, you can also see the cost of fixing or leaving that tech debt.  Here is one of the rules I broke in my project with a class that has too many methods (48!). In this case, it's a test class, so I'm not worried about it. Neither is NDepend, since it estimates this tech debt will cost me 4 minutes and 13 seconds a year.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/ndepend_rule_violation.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/ndepend_rule_violation.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you want to tackle your tech debt but don't know where to start, NDepend can help you asses where your project is today, show your progress, and help you decide which tech debt is most costly and needs to be addressed soonest.&lt;/p&gt;
</description>
      <pubDate>Tue, 04 Sep 2018 04:00:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/adding-and-styling-dynamic-content-in-jquery-mobile-pages</guid>
      <link>https://volaresoftware.com/nl/technical-posts/adding-and-styling-dynamic-content-in-jquery-mobile-pages</link>
      <title>Adding and styling dynamic content in jQuery Mobile pages</title>
      <description>&lt;p&gt;&lt;a href="http://jquerymobile.com/"&gt;jQuery Mobile&lt;/a&gt; does great job styling your web app to look kind of like a native phone app.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/10/snaghtml246ff343.png" alt="snaghtml246ff343.png" /&gt;&lt;/p&gt;
&lt;p&gt;It injects lots of classes like &amp;quot;ui-link&amp;quot;, &amp;quot;ui-content&amp;quot;, &amp;quot;ui-listview&amp;quot;, &amp;quot;ui-shadow&amp;quot;, etc. to make your page look pretty.&lt;/p&gt;
&lt;p&gt;But if you're using &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; to dynamically load content from another source on document ready, jQuery Mobile is already done with its styling changes.  I searched and found lots of suggestions for refreshing the styles in the new section of the page, but .page(), .page(&amp;quot;refresh&amp;quot;), and .trigger(&amp;quot;enhance&amp;quot;) didn't add the styles.  You can see people &lt;a href="http://stackoverflow.com/questions/6297470/forcing-jquery-mobile-to-re-evaluate-styles-theme-on-dynamically-inserted-conten"&gt;struggling&lt;/a&gt; &lt;a href="http://stackoverflow.com/questions/7999436/jquery-mobile-does-not-apply-styles-after-dynamically-adding-content"&gt;with&lt;/a&gt; &lt;a href="http://stackoverflow.com/questions/4844738/dynamic-pages-with-jquery-mobile"&gt;this&lt;/a&gt; &lt;a href="http://stackoverflow.com/questions/9456809/proper-formatting-when-adding-dynamic-content-in-jquery-mobile"&gt;question&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I finally found the answer in &lt;a href="http://blog.stikki.me/2011/08/18/loading-dynamic-content-in-jquery-mobile-with-jquerys-load-function/"&gt;this blog post&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;$(function () {
    $(&amp;quot;#dynamicSection&amp;quot;).load(&amp;quot;/api/dynamicContent&amp;quot;, function () {
        $(this).trigger(&amp;quot;create&amp;quot;);
    });
})
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Wed, 11 Jan 2012 01:39:56 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/using-kendo-ui-grid-with-web-api-and-odata</guid>
      <link>https://volaresoftware.com/nl/technical-posts/using-kendo-ui-grid-with-web-api-and-odata</link>
      <title>Using Kendo UI grid with Web API and OData</title>
      <description>&lt;p&gt;The &lt;a href="http://demos.kendoui.com/web/grid/index.html"&gt;Kendo UI grid&lt;/a&gt; is a snazzy little thing:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/2/image_36.png" alt="image_36.png" /&gt;&lt;/p&gt;
&lt;p&gt;The grid works natively with OData, but &lt;a href="http://demos.kendoui.com/web/grid/remote-data.html"&gt;the examples from the Kendo team are of OData services driven by WCF back ends&lt;/a&gt;.  I wanted to get the grid working with Web API and minimal coding to implement server-side sorting, filtering, and paging.&lt;/p&gt;
&lt;p&gt;Until earlier this week, if you wanted to do that, you were on your own.  There was a partial OData implementation in Web API via a NuGet package, but it didn't support $inlinecount, which is what the grid needs to know how many items there are total (e.g., the $inlinecount for the grid above is 830).&lt;/p&gt;
&lt;p&gt;A more fully supported Web API OData implementation was &lt;a href="http://weblogs.asp.net/scottgu/archive/2013/02/18/announcing-release-of-asp-net-and-web-tools-2012-2-update.aspx"&gt;rolled out this week&lt;/a&gt; and is &lt;a href="https://nuget.org/packages/Microsoft.AspNet.WebApi.OData/4.0.0"&gt;available via NuGet&lt;/a&gt;.  Here are the steps to get it working with a Kendo UI grid.&lt;/p&gt;
&lt;h2 id="server-side"&gt;Server side&lt;/h2&gt;
&lt;p&gt;Open your existing Web API project and install the Web API OData NuGet update:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/2/image_37.png" alt="image_37.png" /&gt;&lt;/p&gt;
&lt;p&gt;Decide what data you want to send to the browser and model it.  I've got a Cat entity and a Dog entity:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;namespace KendoGridWebApiOdata.Models
{
    public class Cat
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Color { get; set; }
    }
}
&lt;p&gt;namespace KendoGridWebApiOdata.Models
{
public class Dog
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Update your WebApiConfig.Register() method (in the &lt;code&gt;App\_Start&lt;/code&gt; folder):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web.Http;
using System.Web.Http.OData.Builder;
using KendoGridWebApiOdata.Models;
&lt;p&gt;namespace KendoGridWebApiOdata.App_Start
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet&amp;lt;Cat&amp;gt;(&amp;quot;Cats&amp;quot;);
modelBuilder.EntitySet&amp;lt;Dog&amp;gt;(&amp;quot;Dogs&amp;quot;);
var model = modelBuilder.GetEdmModel();&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        config.Routes.MapODataRoute(
            routeName: &amp;amp;quot;OData&amp;amp;quot;,
            routePrefix: &amp;amp;quot;api&amp;amp;quot;,
            model: model
            );

        config.Routes.MapHttpRoute(
            name: &amp;amp;quot;DefaultApi&amp;amp;quot;,
            routeTemplate: &amp;amp;quot;api/{controller}/{id}&amp;amp;quot;,
            defaults: new { id = RouteParameter.Optional }
            );

        // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable&amp;amp;lt;T&amp;amp;gt; return type.
        // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
        // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
        config.EnableQuerySupport();

        // To disable tracing in your application, please comment out or remove the following line of code
        // For more information, refer to: http://www.asp.net/web-api
        config.EnableSystemDiagnosticsTracing();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You'll define the OData models you want to expose and set up special OData routes for them.  You can add multiple EntitySets to the model builder as needed for your OData endpoints.  Here, I'm adding Cat and Dog to the model builder.&lt;/p&gt;
&lt;p&gt;The MapODataRoute uses the model builder values to create an OData route.  Note this is not exactly a Web API route, but you can use the same &lt;code&gt;/api/{controller}&lt;/code&gt; convention if you like (or &lt;code&gt;/odata/{controller}&lt;/code&gt; if you prefer) by setting the routePrefix to whatever you like.&lt;/p&gt;
&lt;p&gt;I tried toggling &lt;code&gt;config.EnableQuerySupport&lt;/code&gt; on and off, and it worked in both cases, so I don't know if that matters any more after the Web API OData update.&lt;/p&gt;
&lt;p&gt;For more details about what is going on here, check out &lt;a href="http://blogs.msdn.com/b/webdev/archive/2013/01/29/getting-started-with-asp-net-webapi-odata-in-3-simple-steps.aspx"&gt;Youssef Moussaoui's blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, you'll need a controller, but this isn't a Web API controller, it's an ODataContoller.  That's kinda close, and it inherits from the Web API controller, but it's specifically designed for the OData calls you just set up in routing.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Linq;
using System.Web.Http;
using System.Web.Http.OData;
using FizzWare.NBuilder;
using KendoGridWebApiOdata.Models;
&lt;p&gt;namespace KendoGridWebApiOdata.Controllers
{
public class CatsController : ODataController
{
[Queryable]
public IQueryable&amp;lt;Cat&amp;gt; Get()
{
return BuildTestData();
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    private IQueryable&amp;amp;lt;Cat&amp;amp;gt; BuildTestData()
    {
        return Builder&amp;amp;lt;Cat&amp;amp;gt;
            .CreateListOfSize(100)
            .Build()
            .AsQueryable();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here, I've got a CatsController inheriting from the ODataController.  I also have a [Queryable] attribute over the Get() action method.  This is another piece you supposedly need, and this was used in the older version of the Web API OData NuGet package, but I found my grid worked whether the attribute was on there or not.  You will likely want to leave it as &lt;a href="http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-security-guidance"&gt;a place to lock down incoming requests&lt;/a&gt;, since this is where you can disallow certain query parameters, limit records returned, etc.&lt;/p&gt;
&lt;p&gt;The BuildTestData() method is using &lt;a href="http://nbuilder.org/"&gt;NBuilder&lt;/a&gt; to crank out 100 Cat entities and pretend like it's queryable.&lt;/p&gt;
&lt;h2 id="test-it-out"&gt;Test it out&lt;/h2&gt;
&lt;p&gt;That should do it for the server side.  Let's test the route setup and see if we get data back.  I like using the Chrome plugin &lt;a href="https://www.google.com/url?sa=t&amp;amp;rct=j&amp;amp;q=&amp;amp;esrc=s&amp;amp;source=web&amp;amp;cd=1&amp;amp;cad=rja&amp;amp;ved=0CEMQFjAA&amp;amp;url=https%3A%2F%2Fchrome.google.com%2Fwebstore%2Fdetail%2Fadvanced-rest-client%2Fhgmloofddffdnphfgcellkdfbfbjeloo%3Fhl%3Den-US&amp;amp;ei=3UMkUe2rOZHtqAGi4YC4Ag&amp;amp;usg=AFQjCNEkroM42vfwzL0_5_3WgPLuFCnAZg"&gt;Advanced REST Client&lt;/a&gt;, but since we're testing GET requests, you can also just type the URL in your browser.&lt;/p&gt;
&lt;p&gt;For the URL &lt;code&gt;/api/Cats&lt;/code&gt;, the JSON coming back looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  &amp;quot;odata.metadata&amp;quot;: &amp;quot;http://localhost:56126/api/$metadata#Cats&amp;quot;,
  &amp;quot;value&amp;quot;: [
    {
      &amp;quot;Id&amp;quot;: 1,
      &amp;quot;Name&amp;quot;: &amp;quot;Name1&amp;quot;,
      &amp;quot;Color&amp;quot;: &amp;quot;Color1&amp;quot;
    },
    {
      &amp;quot;Id&amp;quot;: 2,
      &amp;quot;Name&amp;quot;: &amp;quot;Name2&amp;quot;,
      &amp;quot;Color&amp;quot;: &amp;quot;Color2&amp;quot;
    },
  ...]}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To add some OData parameters to the URL, let's try &lt;code&gt;/api/Cats?$inlinecount=allpages&lt;/code&gt;.  Now the JSON has &lt;code&gt;odata.count&lt;/code&gt; for the &lt;code&gt;$inlinecount&lt;/code&gt; value:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  &amp;quot;odata.metadata&amp;quot;: &amp;quot;http://localhost:56126/api/$metadata#Cats&amp;quot;,
  &amp;quot;odata.count&amp;quot;: &amp;quot;100&amp;quot;,
  &amp;quot;value&amp;quot;: [
    {
      &amp;quot;Id&amp;quot;: 1,
      &amp;quot;Name&amp;quot;: &amp;quot;Name1&amp;quot;,
      &amp;quot;Color&amp;quot;: &amp;quot;Color1&amp;quot;
    },
    {
      &amp;quot;Id&amp;quot;: 2,
      &amp;quot;Name&amp;quot;: &amp;quot;Name2&amp;quot;,
      &amp;quot;Color&amp;quot;: &amp;quot;Color2&amp;quot;
    },
...]}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See how the records are coming across in the &lt;code&gt;value&lt;/code&gt; array?  We'll need that and the &lt;code&gt;odata.count&lt;/code&gt; to help the grid know how to parse this JSON.&lt;/p&gt;
&lt;h2 id="client-side"&gt;Client side&lt;/h2&gt;
&lt;p&gt;The HTML for the grid is minimal:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div id=&amp;quot;grid&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the JavaScript isn't bad:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;$(function () {
    var dataSource = new kendo.data.DataSource({
        type: &amp;quot;odata&amp;quot;,
        transport: {
            read: {
                url: &amp;quot;/api/Cats&amp;quot;,
                dataType: &amp;quot;json&amp;quot;
            },
        },
        schema: {
            data: function (data) {
                return data[&amp;quot;value&amp;quot;];
            },
            total: function (data) {
                return data[&amp;quot;odata.count&amp;quot;];
            },
            model: {
                fields: {
                    Id: { type: &amp;quot;number&amp;quot; },
                    Name: { type: &amp;quot;string&amp;quot; },
                    Color: { type: &amp;quot;string&amp;quot; }
                }
            }
        },
        pageSize: 10,
        serverPaging: true,
        serverFiltering: true,
        serverSorting: true
    });
&lt;pre&gt;&lt;code&gt;$(&amp;amp;quot;#grid&amp;amp;quot;).kendoGrid({
    dataSource: dataSource,
    filterable: true,
    sortable: true,
    pageable: true,
    columns: [
        { field: &amp;amp;quot;Id&amp;amp;quot; },
        { field: &amp;amp;quot;Name&amp;amp;quot; },
        { field: &amp;amp;quot;Color&amp;amp;quot; }
    ]
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;});
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the dataSource variable, we're setting the type as &lt;code&gt;odata&lt;/code&gt;.  Seems like that would be enough, but you have to also set the read transport's dataType to &amp;quot;json&amp;quot; or your request will go to the server like &lt;code&gt;/api/Cats?$callback=jQuery183021786115039139986_1361332885733&amp;amp;amp;$inlinecount=allpages&amp;amp;amp;$format=json&amp;amp;amp;$top=10&lt;/code&gt;.  This is a JSONP request.  We want the &lt;code&gt;$callback&lt;/code&gt; and &lt;code&gt;$format&lt;/code&gt; parameters to go away, and setting the dataType to &amp;quot;json&amp;quot; does that and sets the request's Accept headers to &amp;quot;application/json&amp;quot;.&lt;/p&gt;
&lt;p&gt;There is also some extra stuff going on in the schema section.  Normally, this is where you tell Kendo UI what your data types are so it can sort and filter correctly.  Here, we've added data and total to pull the values out of the JSON response so the grid needs can render correctly.  The data function is returning the &lt;code&gt;value&lt;/code&gt; from the JSON we saw above, and the total function is returning the &lt;code&gt;odata.count&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The rest of the dataSource properties are to force things to be done server side and to set the page size.  The remainder of the JavaScript is firing up the grid with this dataSource and setting properties of the grid.&lt;/p&gt;
&lt;p&gt;When you run this, you get a Kendo UI grid working with server-side OData.  In this case, only 10 records are sent per request instead of the 100 Cat records we created on the server.  The OData handling works with sorting, filtering, and paging on the grid.&lt;/p&gt;
&lt;p&gt;If you get it running on your machine, check the XHRs to see the OData query string parameters getting added to the request and the response coming back with just the records requested.&lt;/p&gt;
&lt;h2 id="other-nifty-things"&gt;Other nifty things&lt;/h2&gt;
&lt;p&gt;You can hit a URL to get the schemas of the entities you can query with &lt;code&gt;/api/$metadata&lt;/code&gt;.  You'll get back some XML like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;
&amp;lt;edmx:Edmx Version=&amp;quot;1.0&amp;quot;&amp;gt;
 &amp;lt;edmx:DataServices m:DataServiceVersion=&amp;quot;3.0&amp;quot; m:MaxDataServiceVersion=&amp;quot;3.0&amp;quot;&amp;gt;
   &amp;lt;Schema Namespace=&amp;quot;KendoGridWebApiOdata.Models&amp;quot;&amp;gt;
     &amp;lt;EntityType Name=&amp;quot;Cat&amp;quot;&amp;gt;
      &amp;lt;Key&amp;gt;
        &amp;lt;PropertyRef Name=&amp;quot;Id&amp;quot; /&amp;gt;
      &amp;lt;/Key&amp;gt;
      &amp;lt;Property Name=&amp;quot;Id&amp;quot; Type=&amp;quot;Edm.Int32&amp;quot; Nullable=&amp;quot;false&amp;quot; /&amp;gt;
      &amp;lt;Property Name=&amp;quot;Name&amp;quot; Type=&amp;quot;Edm.String&amp;quot; /&amp;gt;
      &amp;lt;Property Name=&amp;quot;Color&amp;quot; Type=&amp;quot;Edm.String&amp;quot; /&amp;gt;
     &amp;lt;/EntityType&amp;gt;
     &amp;lt;EntityType Name=&amp;quot;Dog&amp;quot;&amp;gt;
      &amp;lt;Key&amp;gt;
        &amp;lt;PropertyRef Name=&amp;quot;Id&amp;quot; /&amp;gt;
      &amp;lt;/Key&amp;gt;
      &amp;lt;Property Name=&amp;quot;Id&amp;quot; Type=&amp;quot;Edm.Int32&amp;quot; Nullable=&amp;quot;false&amp;quot; /&amp;gt;
      &amp;lt;Property Name=&amp;quot;Name&amp;quot; Type=&amp;quot;Edm.String&amp;quot; /&amp;gt;
      &amp;lt;Property Name=&amp;quot;Color&amp;quot; Type=&amp;quot;Edm.String&amp;quot; /&amp;gt;
     &amp;lt;/EntityType&amp;gt;
   &amp;lt;/Schema&amp;gt;
  &amp;lt;Schema Namespace=&amp;quot;Default&amp;quot;&amp;gt;
     &amp;lt;EntityContainer Name=&amp;quot;Container&amp;quot; m:IsDefaultEntityContainer=&amp;quot;true&amp;quot;&amp;gt;
      &amp;lt;EntitySet Name=&amp;quot;Cats&amp;quot; EntityType=&amp;quot;KendoGridWebApiOdata.Models.Cat&amp;quot; /&amp;gt;
      &amp;lt;EntitySet Name=&amp;quot;Dogs&amp;quot; EntityType=&amp;quot;KendoGridWebApiOdata.Models.Dog&amp;quot; /&amp;gt;
     &amp;lt;/EntityContainer&amp;gt;
  &amp;lt;/Schema&amp;gt;
 &amp;lt;/edmx:DataServices&amp;gt;
&amp;lt;/edmx:Edmx&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are worried about exposing your data online, read up on &lt;a href="http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-security-guidance"&gt;OData Security Guidance&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="limitations"&gt;Limitations&lt;/h2&gt;
&lt;p&gt;URLs are case sensitive.  If you browse to &lt;code&gt;/api/Cats&lt;/code&gt;, you get data.  If you browse to &lt;code&gt;/api/cats&lt;/code&gt; (lower case &lt;code&gt;C&lt;/code&gt;), you get a 406 error.&lt;/p&gt;
&lt;p&gt;Kendo UI grid allows sorting by more than one column, but the current Web API OData implementation doesn't seem to support it.&lt;/p&gt;
&lt;h2 id="download"&gt;Download&lt;/h2&gt;
&lt;p&gt;You can &lt;a href="https://github.com/VolareSoftware/KendoGridWebApiOdata"&gt;download the code for this project from GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Tue, 19 Feb 2013 13:48:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/convert-callback-javascript-to-async-await</guid>
      <link>https://volaresoftware.com/nl/technical-posts/convert-callback-javascript-to-async-await</link>
      <title>Convert callback JavaScript to async/await</title>
      <description>&lt;p&gt;If you've done much JavaScript, you've run into the &lt;code&gt;.done()&lt;/code&gt; and &lt;code&gt;.then()&lt;/code&gt; callback functions, where your code is executed AFTER an asynchronous call completes.&lt;/p&gt;
&lt;p&gt;Here, &lt;code&gt;myFunction(myParams)&lt;/code&gt; calls &lt;code&gt;makeXhrCall(myParams)&lt;/code&gt;, an asynchronous XHR API call (the most common type of asynchronous call you will run into). The &lt;code&gt;.then()&lt;/code&gt; function waits for the XHR call to complete. When it does, the XHR call returns &lt;code&gt;data&lt;/code&gt;, which is used inside the &lt;code&gt;.then()&lt;/code&gt; function to call another function, &lt;code&gt;doSomething(data)&lt;/code&gt;. The result of the &lt;code&gt;doSomething(data)&lt;/code&gt; call gets returned out to whoever called the outer function when it's done.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;myFunction(myParams) {
    return makeXhrCall(myParams)
        .then(data =&amp;gt;
            doSomething(data)
        );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key thing is, you are using &lt;code&gt;.then()&lt;/code&gt; as a hook to do more work when the asynchronous call completes.&lt;/p&gt;
&lt;p&gt;For a while now, &lt;a href="https://caniuse.com/#feat=async-functions"&gt;you've been able to use &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;&lt;/a&gt; syntax as a way to treat asynchronous functions as synchronous, meaning no code AFTER the XHR call executes until the line with the &lt;code&gt;await&lt;/code&gt; has completed executing.&lt;/p&gt;
&lt;p&gt;If you are new to JavaScript, it can be confusing that making asynchronous calls leaves other lines of code UNDER that asynchronous call executing while the asynchronous call is still running. Changing to &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; makes your code clearer because each step is followed in top-down sequence.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;async myFunction(myParams) {
    const data = await makeXhrCall(myParams);
    return doSomething(data);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;async&lt;/code&gt; keyword tells JavaScript, &amp;quot;this code is going to use &lt;code&gt;await&lt;/code&gt; at least once&amp;quot;. Then you add &lt;code&gt;await&lt;/code&gt; right before the asynchronous call.  Now the &lt;code&gt;data&lt;/code&gt; won't have a value until the XHR completes, and &lt;code&gt;doSomething(data)&lt;/code&gt; won't run until the line with the &lt;code&gt;await&lt;/code&gt; has finished putting a value in &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;
</description>
      <pubDate>Sun, 09 Dec 2018 11:40:03 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/comparison-of-typemock-isolator-and-rhino-mocks</guid>
      <link>https://volaresoftware.com/nl/technical-posts/comparison-of-typemock-isolator-and-rhino-mocks</link>
      <title>Comparison of Typemock Isolator and Rhino Mocks</title>
      <description>&lt;p&gt;I just started a new project using &lt;a href="http://learn.typemock.com/typemock-isolator/"&gt;Typemock Isolator&lt;/a&gt;.  It's a new tool for me, and since I've mostly used &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt;, my learning is from the perspective of &amp;quot;how do you do this with Rhino Mocks&amp;quot;.  These are the differences I see so far.&lt;/p&gt;
&lt;h2 id="general"&gt;General&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Typemock Isolator is a commercial product.  Rhino Mocks is free and open source.  Here's the &lt;a href="http://learn.typemock.com/buy/"&gt;Typemock pricing&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Typemock Isolator can mock just about anything, including not normally mockable things like private methods, static methods, and sealed classes.  Rhino Mocks has traditional mocking from an interface, abstract class, etc.  There has been &lt;a href="http://colinjack.blogspot.com/2007/05/typemock-rhinomocks-designing-for.html"&gt;some hand-wringing&lt;/a&gt;about whether or not Typemock was &lt;em&gt;too&lt;/em&gt; powerful and encouraged untestable software designs.  But I think it's uncommon to create a brand-new stand-alone project, at least in enterprise development.  So you're probably dealing with at least &lt;em&gt;some&lt;/em&gt; code that wasn't written with testing in mind.  You can wrap those static classes and create new default constructors and all kinds of OO jujutsu.  Or you can just leave it alone and mock it as-is with Typemock.&lt;/li&gt;
&lt;li&gt;With Typemock Isolator, everything starts with &amp;quot;Isolate&amp;quot; call.  That's hard to beat for simplicity and discoverability.  You can also use the AAA style syntax.  Rhino Mocks also has AAA style testing in the newer versions.  But there has been some confusion (at least in my mind) over the main entry points, like &lt;code&gt;MockRepository.GenerateMock&amp;lt;ISomeClass&amp;gt;()&lt;/code&gt; and &lt;code&gt;MockRepository.GenerateStub&amp;lt;ISomeClass&amp;gt;()&lt;/code&gt;.  &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/10/05/three-simple-rhino-mocks-rules.aspx"&gt;Once you understand it, you're all set&lt;/a&gt;, but it's kind of a stumbling block for people new to Rhino Mocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OK, let's move on to other syntax differences.  I grouped these by AAA style (arrange, act, assert).  Since the &amp;quot;act&amp;quot; step should be invoking your system under test, the frameworks should look the same there.  They differ in the setup syntax (arrange) and the verify syntax (assert).&lt;/p&gt;
&lt;h2 id="arrange-syntax"&gt;Arrange Syntax&lt;/h2&gt;
&lt;h3 id="simple-mocking"&gt;Simple mocking&lt;/h3&gt;
&lt;p&gt;For simple mock objects, Typemock uses this syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Arrange
var repository = Isolate.Fake.Instance&amp;lt;IContactRepository&amp;gt;();
var contact = new Contact(repository);
&lt;p&gt;// Act
contact.DoSomethingThatUsesARepository();
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;as compared to the Rhino Mocks syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Arrange
var repository = MockRepository.GenerateStub&amp;lt;IContactRepository&amp;gt;();
var contact = new Contact(repository);
&lt;p&gt;// Act
contact.DoSomethingThatUsesARepository();
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Not much here.  Just different ways to do the same thing.&lt;/p&gt;
&lt;h3 id="argument-handling"&gt;Argument handling&lt;/h3&gt;
&lt;p&gt;Method call arguments are ignored by default in Typemock, so you don't have quite as much setup to get to the system under test.  You still need to put the correct type in the argument, but it can be null, string.Empty, 0, etc.&lt;/p&gt;
&lt;p&gt;With Rhino Mocks, you have to be explicit when arguments don't matter:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;theClass.Expect(x =&amp;gt; x.theMethod(null)).IgnoreArguments();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or you can use the newer, more readable but maybe more typing Rhino Mocks syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;theClass.Expect(x =&amp;gt; x.theMethod(Arg&amp;lt;theArgument&amp;gt;.Is.Anything));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Typemock, you use this syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;Isolate.WhenCalled(() =&amp;gt; theClass.theMethod(theArgument)).WithExactArguments();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;only if the arguments &lt;em&gt;are&lt;/em&gt; important to you.&lt;/p&gt;
&lt;p&gt;So you can ignore arguments or use specific arguments with either framework.  They differ on the default setting.&lt;/p&gt;
&lt;h3 id="unmockable-mocking"&gt;Unmockable mocking&lt;/h3&gt;
&lt;p&gt;In Typemock, you can also ignore calls on &amp;quot;live&amp;quot; methods (real instances, not fakes, stubs, or mocks) with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;Isolate.WhenCalled(() =&amp;gt; theClass.theMethod(theArgument)).IgnoreCall();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only way to not call into live code with Rhino Mocks that I'm aware of is to use a stub.  This is the traditional testing approach that injects a stubbed dependency into the class under test.&lt;/p&gt;
&lt;p&gt;So let's assume I need to test a Contact class method that does some stuff and then sends an email using EmailService, but I don't want an email to actually go out.  Here's the Typemock arrange and act:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Arrange
var emailService = new EmailService();
var contact = new Contact(emailService);
Isolate.WhenCalled(() =&amp;gt; emailService.SendContactInfoToSales(contact)).IgnoreCall();
&lt;p&gt;// Act
contact.DoSomethingThatSendsAnEmail();
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And the Rhino Mocks arrange and act:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Arrange
var emailService = MockRepository.GenerateStub&amp;lt;IEmailService&amp;gt;();
var contact = new Contact(emailService);
&lt;p&gt;// Act
contact.DoSomethingThatSendsAnEmail();
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;For the Rhino Mocks approach, my EmailService has to be mockable.  Again, you can write code to do that, and in this sample I am using an interface to EmailService to do that.  But with Typemock, you just tell the test to ignore that call.  You don't need to write more code to make the EmailService test-friendly.&lt;/p&gt;
&lt;p&gt;Suppose EmailService is in some company-owned assembly you have to use and it's a sealed class.  Yes, you can wrap it with an interface, but why not just tell it to skip email sending with Typemock.  That's pretty powerful.  You can focus on the new code you want to test instead of refactoring existing code you don't really care about but are dependent on.&lt;/p&gt;
&lt;h3 id="simulating-exceptions"&gt;Simulating Exceptions&lt;/h3&gt;
&lt;p&gt;Another cool Typemock thing you can do is force existing code to throw an exception so you can test the robustness of your code.  What if I want to make sure my new code works OK if the mail relay is down on that legacy, sealed EmailService:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;Isolate.WhenCalled(() =&amp;gt; emailService.SendContactInfoToSales(contact)).WillThrow(new SmtpException());
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can do the same thing in Rhino Mocks.  Again, just different syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;emailService.Expect(x =&amp;gt; x.SendContactInfoToSales(contact)).Throw(new SmtpException());
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think you would still need to have a mock on an IEmailService to do this with Rhino Mocks.  The Typemock advantage is that it can work around that sealed class.&lt;/p&gt;
&lt;h2 id="assert-syntax"&gt;Assert Syntax&lt;/h2&gt;
&lt;h3 id="simple-verifications"&gt;Simple verifications&lt;/h3&gt;
&lt;p&gt;The interaction testing assert syntax for Rhino Mocks is:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Assert
emailService.AssertWasCalled(x =&amp;gt; x.SendContactInfoToSales(null), opt =&amp;gt; opt.IgnoreArguments());
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And for Typemock:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Assert
Isolate.Verify.WasCalledWithAnyArguments(() =&amp;gt; emailService.SendContactInfoToSales(null));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is just to test that the code got to that line/made that call internally.  If you want to verify it got there &lt;em&gt;and&lt;/em&gt; arrived with your expected arguments with Rhino Mocks:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Assert
emailService.AssertWasCalled(x =&amp;gt; x.SendContactInfoToSales(expectedContact);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with Typemock:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Assert
Isolate.Verify.WasCalled(() =&amp;gt; emailService.SendContactInfoToSales(expectedContact));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So again, both frameworks can get you either assert type, just with different syntax.&lt;/p&gt;
&lt;h2 id="wrap-up"&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;The promise of Typemock Isolator is less time refactoring code that isn't on your roadmap and less setup to get to your system under test.  I've focused here mostly on the arrange syntax for that reason.&lt;/p&gt;
&lt;p&gt;Rhino Mocks can do most of the stuff Typemock can, except for the private, sealed, and static testing.  Some would argue that you shouldn't test that code or if you need to make it testable, you should refactor it anyway.&lt;/p&gt;
&lt;p&gt;Maybe.  But it's also pretty appealing to keep your coding and tests focused on your project mandate, too.&lt;/p&gt;
</description>
      <pubDate>Fri, 16 Oct 2009 00:41:21 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/optimizing-javascript-and-css-files-using-requirejs-and-r-js-in-an-asp-net-mvc-app</guid>
      <link>https://volaresoftware.com/nl/technical-posts/optimizing-javascript-and-css-files-using-requirejs-and-r-js-in-an-asp-net-mvc-app</link>
      <title>Optimizing JavaScript and CSS files using RequireJS and R.js in an ASP.NET MVC app</title>
      <description>&lt;p&gt;In my previous blog post, we discussed &lt;a href="https://volaresoftware.com/en/technical-posts/adding-requirejs-to-an-aspnet-mvc-project"&gt;setting up RequireJS for a multi-page ASP.NET MVC app&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/VolareSoftware/RequireJSWithMVC"&gt;code for the reference app&lt;/a&gt; is on GitHub, and when run, it shows us loading seven JavaScript files (409 KB) and four CSS files (31.1 KB):&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_before_js.png" alt="Optimize Before JS" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_before_css.png" alt="Optimize Before CSS" /&gt;&lt;/p&gt;
&lt;p&gt;We know we can reduce the number of HTTP requests, and reduce network traffic, if we can load fewer files and smaller files at run time.&lt;/p&gt;
&lt;p&gt;There are several ways to do this bundling and minification: use &lt;a href="https://volaresoftware.com/en/technical-posts/combining-javascript-bundling-minification-cache-busting-and-easier-debugging"&gt;MVC's built in tools&lt;/a&gt;, use &lt;a href="http://vswebessentials.com/"&gt;Web Essentials&lt;/a&gt;, or use &lt;a href="http://requirejs.org/docs/optimization.html"&gt;r.js&lt;/a&gt;, the tool that comes with &lt;a href="http://requirejs.org/"&gt;RequireJS&lt;/a&gt;.  The advantage of the later is you can let RequireJS, which is already tracking your dependency graph, decide which files should be bundled together for a specific page.&lt;/p&gt;
&lt;p&gt;You can also use r.js to bundle ALL the scripts in your project together, and for a single-page app, that may make sense.  But for a multi-page app, you want to have a common set of scripts you need on most pages, and an a la cart bundle for each page.  We'll focus on the later here.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;You'll need to download r.js, which comes in the &lt;a href="http://www.nuget.org/packages/RequireJS/2.1.11"&gt;RequireJS nuget package&lt;/a&gt;, and you'll need a local version of &lt;a href="http://nodejs.org/download/"&gt;Node&lt;/a&gt; running.&lt;/p&gt;
&lt;p&gt;You'll also likely want to do this optimization only in Release mode, so be sure your project has a Debug and a Release build config.&lt;/p&gt;
&lt;h2 id="what-to-bundle-for-javascript"&gt;What to bundle for JavaScript?&lt;/h2&gt;
&lt;p&gt;Here are the JavaScript files we have to work with:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_what_to_bundle_js.png" alt="What to bundle JS" /&gt;&lt;/p&gt;
&lt;p&gt;We want page-level bundles, so we can load require.js, then main.js (including common libraries and kickoff.js), then main-currentDateTime.js and anything it needs that we haven't already loaded.&lt;/p&gt;
&lt;p&gt;I usually name the main-*.js file as the name of the main MVC view or controller/action being pulled up on the screen.  Theses main-*.js files are the entry point for firing up the JavaScript for just that page.&lt;/p&gt;
&lt;h2 id="what-to-bundle-for-css"&gt;What to bundle for CSS?&lt;/h2&gt;
&lt;p&gt;We have three CSS files we can combine and a main.css file that references them:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_what_to_bundle_css.png" alt="What to bundel CSS" /&gt;&lt;/p&gt;
&lt;p&gt;The main.css file uses import statements for the three style sheets:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-css"&gt;/* 3rd party stylesheets */
@import url(&amp;quot;lib/bootstrap.css&amp;quot;);
@import url(&amp;quot;lib/bootstrap-theme.css&amp;quot;);
&lt;p&gt;/* Application stylesheets */
@import url(&amp;quot;app/site.css&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This is usually a no-no for web development, because now there is a fourth style sheet, and a fourth HTTP request as the browser loads main.css, then turns around and loads the three style sheets it wants us to load.  In this case, I think it's fine since this will be the way it works in Debug mode when you are working locally.  When you go to Release mode, everything in main.css will be bundled and combined into one file.&lt;/p&gt;
&lt;p&gt;Now change the link in the _Layout.cshtml file to point to main.css:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;link href=&amp;quot;~/Styles/main.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TIP: Be sure your CSS files are listed in main.css in the order in which you want them to override, with your app styles at the bottom.  The last ones listed will take precedence.&lt;/p&gt;
&lt;h2 id="setting-up-r.js-build-scripts.js-build-styles.js"&gt;Setting up r.js, build-scripts.js, build-styles.js&lt;/h2&gt;
&lt;p&gt;I created an App_Build folder at the solution level.  Call yours anything you like.  The point is, this is stuff for building the project, not part of the code that is deployed when running the app.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_app_build_folder.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_app_build_folder.png" /&gt;&lt;/p&gt;
&lt;p&gt;I added the r.js file and two other JavaScript files with build config settings.  One is for the JavaScript code and one is for the CSS.&lt;/p&gt;
&lt;p&gt;The JavaScript config file, &amp;quot;build-scripts.js&amp;quot;, looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;({
    appDir: &amp;quot;../Scripts&amp;quot;,
    dir: &amp;quot;../Scripts-Build&amp;quot;,
    baseUrl: &amp;quot;app&amp;quot;,
    mainConfigFile: &amp;quot;../Scripts/main.js&amp;quot;,
    paths: {
        main: &amp;quot;../main&amp;quot;
    },
    keepBuildDir: false,
    modules: [{
        name: &amp;quot;main&amp;quot;,
        include: [
            // These JS files will be on EVERY page in the main.js file
            // So they should be the files we will almost always need everywhere
            &amp;quot;domReady&amp;quot;,
            &amp;quot;jquery&amp;quot;,
            &amp;quot;jqueryValidate&amp;quot;,
            &amp;quot;jqueryValidateUnobtrusive&amp;quot;,
            &amp;quot;bootstrap&amp;quot;,
            &amp;quot;moment&amp;quot;
        ]
    },
    // These are page-specific bundles, usually named main-*
    { name: &amp;quot;main-currentDateTime&amp;quot;, exclude: [&amp;quot;main&amp;quot;] }
    ],
    onBuildRead: function (moduleName, path, contents) {
        if (moduleName === &amp;quot;main&amp;quot;) {
            return contents.replace(&amp;quot;Scripts&amp;quot;, &amp;quot;Scripts-Build&amp;quot;);
        }
        return contents;
    }
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Most of the paths are relative to the r.js file.  The appDir is the main folder, so the appDir plus the baseUrl is the /Scripts/app folder.  The dir setting is where you want the built scripts to go.  The mainConfigFile is the path to main.js.&lt;/p&gt;
&lt;p&gt;The first argument in the modules section is all the code you want rolled up into main.js.  These are files used on almost every if not every page.  The next argument in modules is each page file.  Here, you need to manually add each page of your app where you want bundling.  I've only got one page/bundle listed here.  RequireJS will inspect that main-*.js file, and its dependencies, and their dependencies, and so on, but it will exclude files already bundled into main.&lt;/p&gt;
&lt;p&gt;For example, the main-currentDateTime module uses &amp;quot;jquery&amp;quot;.  That file is already included in main.js in these build instructions, so it won't be bundled into main-currentDateTime.&lt;/p&gt;
&lt;p&gt;The onBuildRead stuff is for swapping out paths in the built scripts.  More on that down below.&lt;/p&gt;
&lt;p&gt;The CSS config file, &amp;quot;build-styles.js&amp;quot;, looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;({
    keepBuildDir: false,
    optimizeCss: &amp;quot;standard&amp;quot;,
    cssIn: &amp;quot;../Styles/main.css&amp;quot;,
    out: &amp;quot;../Styles-Build/main.css&amp;quot;
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The main configuration settings as the cssIn folder, where the code to bundle comes from, and the out folder, where it's going.&lt;/p&gt;
&lt;p&gt;In both cases, we're outputting to new folders that are cleaned out on every Release build, /Scripts-Build and /Styles-Build.&lt;/p&gt;
&lt;h2 id="bundling-and-minifying-on-release-build"&gt;Bundling and minifying on Release build&lt;/h2&gt;
&lt;p&gt;Open the web project Properties and select Build Events.  In the Pre-build event command line, add:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;if $(ConfigurationName) == Release node &amp;quot;$(ProjectDir)App_Build\r.js&amp;quot; -o &amp;quot;$(ProjectDir)App_Build\build-scripts.js&amp;quot;
if $(ConfigurationName) == Release node &amp;quot;$(ProjectDir)App_Build\r.js&amp;quot; -o &amp;quot;$(ProjectDir)App_Build\build-styles.js&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the call to execute r.js with Node.  You must have Node set up in your Paths on your machine for this to work.  Now the build scripts will run every time the build is executed in Release mode.&lt;/p&gt;
&lt;p&gt;Change your build configuration to Release mode and build the app.  If it worked, the output window should show:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;1&amp;gt;------ Build started: Project: RequireJSWithMVC, Configuration: Release Any CPU ------
1&amp;gt;  
1&amp;gt;  Tracing dependencies for: main
1&amp;gt;  
1&amp;gt;  Tracing dependencies for: main-currentDateTime
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/app/currentDateTime.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/app/kickoff.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/app/main-currentDateTime.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/lib/bootstrap.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/lib/domReady.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/lib/jquery-2.1.1.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/lib/jquery.validate.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/lib/jquery.validate.unobtrusive.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/lib/moment.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/lib/require.js
1&amp;gt;  Uglifying file: C:/RequireJSWithMVC/Scripts-Build/main.js
1&amp;gt;  
1&amp;gt;  main.js
1&amp;gt;  ----------------
1&amp;gt;  app/kickoff.js
1&amp;gt;  main.js
1&amp;gt;  lib/domReady
1&amp;gt;  lib/jquery-2.1.1.js
1&amp;gt;  lib/jquery.validate.js
1&amp;gt;  lib/jquery.validate.unobtrusive.js
1&amp;gt;  lib/bootstrap.js
1&amp;gt;  lib/moment.js
1&amp;gt;  
1&amp;gt;  app/main-currentDateTime.js
1&amp;gt;  ----------------
1&amp;gt;  app/main-currentDateTime.js
1&amp;gt;  
1&amp;gt;  
1&amp;gt;  C:/RequireJSWithMVC/Styles-Build/main.css
1&amp;gt;  ----------------
1&amp;gt;  C:/RequireJSWithMVC/Styles/lib/bootstrap.css
1&amp;gt;  C:/RequireJSWithMVC/Styles/lib/bootstrap-theme.css
1&amp;gt;  C:/RequireJSWithMVC/Styles/app/site.css
1&amp;gt;  C:/RequireJSWithMVC/Styles/main.css
1&amp;gt;  
1&amp;gt;  RequireJSWithMVC -&amp;gt; C:\RequireJSWithMVC\bin\RequireJSWithMVC.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;r.js does a nice job of reporting back what it's done.  Here, you can see it traces dependencies, minifies (uglifies) every JavaScript file, then it reports the files it bundled for main.js, main-currentDateTime.js, and main.css.&lt;/p&gt;
&lt;p&gt;You should be able to show hidden files in Visual Studio and see the new folders and their files.  Open them up and look at the minification changes&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_built_folders.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_built_folders.png" /&gt;&lt;/p&gt;
&lt;h2 id="dealing-with-paths-with-mvc-helpers"&gt;Dealing with paths with MVC Helpers&lt;/h2&gt;
&lt;p&gt;So great!  We've got the files we want in /Scripts-Build and /Styles-Build.  Unfortunately, our code is still pointing to /Scripts and /Styles.  We can fix this with some MVC Helpers.&lt;/p&gt;
&lt;p&gt;Looking at our _Layout.cshtml, we'll need to fix the path to the stylesheets and the path to require.js,:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    …
    &amp;lt;link href=&amp;quot;~/Styles/main.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; /&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    …
    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
        @RenderBody()
    &amp;lt;/div&amp;gt;
&lt;pre&gt;&lt;code&gt;&amp;amp;lt;script src=&amp;amp;quot;/Scripts/lib/require.js&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
@RenderSection(&amp;amp;quot;scripts&amp;amp;quot;, required: false)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here's the C# for the stylesheet and scripts PathHelpers.cs:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web;
using System.Web.Mvc;
&lt;p&gt;namespace RequireJSWithMVC.Extensions
{
public static class PathHelpers
{
public static string ScriptsPath(this HtmlHelper helper, string pathWithoutScripts)
{
#if (DEBUG)
var scriptsPath = &amp;quot;&lt;sub&gt;/Scripts/&amp;quot;;
#else
var scriptsPath = &amp;quot;&lt;/sub&gt;/Scripts-Build/&amp;quot;;
#endif&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        return VirtualPathUtility.ToAbsolute(scriptsPath + pathWithoutScripts);
    }

    public static string StylesPath(this HtmlHelper helper, string pathWithoutStyles)
    {
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#if (DEBUG)
var stylesPath = &amp;quot;&lt;sub&gt;/Styles/&amp;quot;;
#else
var stylesPath = &amp;quot;&lt;/sub&gt;/Styles-Build/&amp;quot;;
#endif
return VirtualPathUtility.ToAbsolute(stylesPath + pathWithoutStyles);
}
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now our _Layout.cshtml can be update to this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;@using RequireJSWithMVC.Extensions
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    ...
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;@Html.StylesPath(&amp;quot;main.css&amp;quot;)&amp;quot; /&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    ...
    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
        @RenderBody()
    &amp;lt;/div&amp;gt;
&lt;pre&gt;&lt;code&gt;&amp;amp;lt;script src=&amp;amp;quot;@Html.ScriptsPath(&amp;amp;quot;lib/require.js&amp;amp;quot;)&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
@RenderSection(&amp;amp;quot;scripts&amp;amp;quot;, required: false)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;We still need to fix the paths within each page.  They still point to the /Scripts folder and need to point to /Scripts-Build in Release mode.  Let's do that by updating our RequireJsHelper.cs from the last post:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
&lt;p&gt;namespace RequireJSWithMVC.Extensions
{
public static class RequireJsHelpers
{
public static MvcHtmlString InitPageMainModule(this HtmlHelper helper, string pageModule)
{
var require = new StringBuilder();&lt;/p&gt;
&lt;p&gt;#if (DEBUG)
var scriptsPath = &amp;quot;&lt;sub&gt;/Scripts/&amp;quot;;
#else
var scriptsPath = &amp;quot;&lt;/sub&gt;/Scripts-Build/&amp;quot;;
#endif&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        var absolutePath = VirtualPathUtility.ToAbsolute(scriptsPath);

        require.AppendLine(&amp;amp;quot;&amp;amp;lt;script&amp;amp;gt;&amp;amp;quot;);
        require.AppendFormat(&amp;amp;quot;    require([\&amp;amp;quot;{0}main.js\&amp;amp;quot;],&amp;amp;quot; + Environment.NewLine, absolutePath);
        require.AppendLine(&amp;amp;quot;        function() {&amp;amp;quot;);
        require.AppendFormat(&amp;amp;quot;            require([\&amp;amp;quot;{0}\&amp;amp;quot;, \&amp;amp;quot;domReady!\&amp;amp;quot;]);&amp;amp;quot; + Environment.NewLine, pageModule);
        require.AppendLine(&amp;amp;quot;        }&amp;amp;quot;);
        require.AppendLine(&amp;amp;quot;    );&amp;amp;quot;);
        require.AppendLine(&amp;amp;quot;&amp;amp;lt;/script&amp;amp;gt;&amp;amp;quot;);

        return new MvcHtmlString(require.ToString());
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Both of these helpers rely on the compiler flag for debug.  If you don't like that, you could always branch off an Environment key in appSettings in your web.config or something.&lt;/p&gt;
&lt;p&gt;Now when the page is loaded for this app, we have three scripts and one stylesheet, so we've gone from eleven HTTP requests to four.  Furthermore, the files requested are much smaller after the minification, and we've gone from 440.1 KB to 223.3 KB total.  You could get that down even more if you removed all the license info from the minified JavaScript in the build-scripts.js config with &amp;quot;preserveLicenseComments: false&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_after_js.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_after_js.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_after_css.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/optimize_after_css.png" /&gt;&lt;/p&gt;
&lt;p&gt;Finally, your users' browsers should cache most of these files after landing on any page on your site. The files require.js, main.js, and main.css will be the same for each page.  Then the user's browser only needs to download the JavaScript for each newly browsed page.&lt;/p&gt;
</description>
      <pubDate>Thu, 29 May 2014 00:39:26 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/sessionless-mvc-without-losing-tempdata</guid>
      <link>https://volaresoftware.com/nl/technical-posts/sessionless-mvc-without-losing-tempdata</link>
      <title>Sessionless MVC without losing TempData</title>
      <description>&lt;p&gt;I've blogged before about &lt;a href="https://volaresoftware.com/en/technical-posts/sessionless-mvc-3"&gt;making your MVC controllers sessionless&lt;/a&gt;.  The knock on sessionless controllers is that TempData is off the table because it uses Session as its data store.&lt;/p&gt;
&lt;p&gt;If you see the &lt;code&gt;TempData&lt;/code&gt; name and dismiss it, thinking it's another dictionary like &lt;code&gt;Session[]&lt;/code&gt; and &lt;code&gt;ViewData[]&lt;/code&gt; and you're waaaay past that since your mister type-safe, take another look.  The neat thing about &lt;code&gt;TempData&lt;/code&gt; is that it lasts for one more page load and then &amp;quot;poof&amp;quot; - it's gone.  It self destructs as soon as it has been read.&lt;/p&gt;
&lt;p&gt;Sure, it's a dictionary with magic string keys, but it's a great place to store message like &amp;quot;Your changes were saved&amp;quot; when you redirect to another page.&lt;/p&gt;
&lt;p&gt;So how do we get the benefits of &lt;code&gt;TempData&lt;/code&gt; as an ephemeral application message store, but go all-in on the web farm with sessionless controllers?&lt;/p&gt;
&lt;h2 id="cookies"&gt;Cookies!&lt;/h2&gt;
&lt;p&gt;I can hear you groaning.  Cookies are old school!  They can't hold much information!  They aren't secure!&lt;/p&gt;
&lt;p&gt;Fine, don't put much in there, and don't put your secret fried chicken recipe in there.  We're just going to use this as a little string to tell the user everything is OK or it's not OK.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;TempData&lt;/code&gt; uses a provider model for the data store, and Session is the default data store.  But you can get a cookie data store, CookieTempDataProvider, with &lt;a href="http://www.nuget.org/List/Packages/Mvc3Futures"&gt;Mvc3Futures&lt;/a&gt; NuGet package:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2011/6/image_11.png" alt="image_11.png" /&gt;&lt;/p&gt;
&lt;p&gt;This should work as a TempData provider, but now it has to be wired into the application.  Here's how you can do that:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class BaseController : Controller
{
    protected override ITempDataProvider CreateTempDataProvider()
    {
        return new CookieTempDataProvider(HttpContext);
    }
}
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Thu, 30 Jun 2011 15:32:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/don-t-mock-httpcontext</guid>
      <link>https://volaresoftware.com/nl/technical-posts/don-t-mock-httpcontext</link>
      <title>Don't mock HttpContext</title>
      <description>&lt;p&gt;HttpContext doesn't like to be mocked!!&lt;/p&gt;
&lt;p&gt;It's so easy to take a direct dependency on &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.aspx"&gt;HttpContext&lt;/a&gt; and not even realize it.  If you're in the code behind in Web Forms or in a controller action in MVC, it's just right there, tempting you to use it to access session variables, application security, etc.&lt;/p&gt;
&lt;p&gt;But don't.&lt;/p&gt;
&lt;p&gt;Some little known facts about HttpContext:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HttpContext is the largest object ever created by humans.&lt;/li&gt;
&lt;li&gt;If you printed out the code for everything in HttpContext, the pages could be stacked end to end to wrap around the Earth's equator 7 times.&lt;/li&gt;
&lt;li&gt;Mocking HttpContext is like trying to calculate the last digit of pi.  There is always a little more to it.&lt;/li&gt;
&lt;li&gt;Chuck Norris gave up trying to mock HttpContext.  He was deep in HttpContext.Response and quit, curled into a ball on the floor, and started whimpering.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sealed-what-object-reference-what"&gt;Sealed what?  Object reference what?&lt;/h2&gt;
&lt;p&gt;Let's say you've got some MVC security stuff you're trying to work with in a controller action.  You've got code like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class OrderController : Controller
{
    [Authorize]
    public ActionResult Process()
    {
        if (User.IsInRole(&amp;quot;Admin&amp;quot;))
        {
            return View(&amp;quot;SecretAdminStuff&amp;quot;);
        }
&lt;pre&gt;&lt;code&gt;    return View(&amp;amp;quot;NotAuthorized&amp;amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;See that &lt;code&gt;User.IsInRole()&lt;/code&gt; code?  That call is really to &lt;code&gt;HttpContext.Current.User.IsInRole()&lt;/code&gt;.  You just took the bait and are tied to &lt;code&gt;HttpContext&lt;/code&gt; now.&lt;/p&gt;
&lt;p&gt;So what? You have to use HttpContext to get that information, right?  Sure, but you don't want to be tied &lt;strong&gt;directly&lt;/strong&gt; to it or you've created untestable code.&lt;/p&gt;
&lt;p&gt;Let's try a couple tests to verify the branching in this action method is returning the correct view based on the user's role.  I'm using &lt;a href="http://www.nunit.org/"&gt;NUnit&lt;/a&gt;, &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt;, and the &lt;a href="http://should.codeplex.com/"&gt;Should&lt;/a&gt; assembly below.  Rhino Mocks has .Stub() and .Return() extension methods to set the expected return values for whether the user is or isn't in the Admin role.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[Test]
public void Should_return_NotAuthorized_view_when_not_Admin_user()
{
    // Arrange
    var mockContext = MockRepository.GenerateMock&amp;lt;HttpContext&amp;gt;();
    mockContext.Stub(x =&amp;gt; x.User.IsInRole(&amp;quot;Admin&amp;quot;)).Return(false);
    var orderController = new OrderController();
&lt;pre&gt;&lt;code&gt;// Act
var result = orderController.Process() as ViewResult;

// Assert
result.ViewName.ShouldEqual(&amp;amp;quot;NotAuthorized&amp;amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;[Test]
public void Should_return_SecretAdminStuff_view_when_Admin_user()
{
// Arrange
var mockContext = MockRepository.GenerateMock&amp;lt;HttpContext&amp;gt;();
mockContext.Stub(x =&amp;gt; x.User.IsInRole(&amp;quot;Admin&amp;quot;)).Return(true);
var orderController = new OrderController();&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Act
var result = orderController.Process() as ViewResult;

// Assert
result.ViewName.ShouldEqual(&amp;amp;quot;SecretAdminStuff&amp;amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;As soon as we run the tests we see &amp;quot;System.NotSupportedException: Can't create mocks of sealed classes&amp;quot;.  Oh yeah, HttpContext is sealed.  That won't work.&lt;/p&gt;
&lt;p&gt;Hmmm.  Aren't there some new classes in System.Web.Abstractions for just this kind of thing?  Let's change HttpContext&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var mockContext = MockRepository.GenerateMock&amp;lt;HttpContext&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontextbase.aspx"&gt;HttpContextBase&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var mockContext = MockRepository.GenerateMock&amp;lt;HttpContextBase&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and see if that helps.&lt;/p&gt;
&lt;p&gt;The new problem is: &amp;quot;System.NullReferenceException: Object reference not set to an instance of an object.&amp;quot;  Mocking &lt;code&gt;HttpContextBase&lt;/code&gt; isn't helping because the test isn't passing the mock context into the controller.  Every call in the action method to &lt;code&gt;User.IsInRole()&lt;/code&gt; will always call the &lt;strong&gt;real&lt;/strong&gt; &lt;code&gt;HttpContext&lt;/code&gt;, which isn't created because the test is not running in the ASP.NET process.&lt;/p&gt;
&lt;p&gt;You can get around this with &lt;a href="http://site.typemock.com/"&gt;Typemock Isolator&lt;/a&gt;, which goes beyond mocking and can intercept the next call to &lt;code&gt;HttpContext.Current.User.IsInRole()&lt;/code&gt; and swap out a result, but isn't there a simpler way to do this without buying another product or waiting for better abstract classes to work with?&lt;/p&gt;
&lt;h2 id="a-better-way"&gt;A better way&lt;/h2&gt;
&lt;p&gt;We can't test something tied to &lt;code&gt;HttpContext&lt;/code&gt; like this.  We need another approach.  The one I favor is wrapping the calls we care about, delegating out to the untestable code in the wrapper class, then passing an interface to the wrapper class into the constructor of the class using it.&lt;/p&gt;
&lt;p&gt;Here's the wrapping class I've created to access a few &lt;code&gt;HttpContext&lt;/code&gt; current user values and the interface for the wrapping class:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class CurrentUser : ICurrentUser
{
    public virtual string Name()
    {
        return HttpContext.Current.User.Identity.Name;
    }
&lt;pre&gt;&lt;code&gt;public bool IsLoggedIn()
{
    return HttpContext.Current.User.Identity.IsAuthenticated;
}

public bool IsGuest()
{
    return HttpContext.Current.User.IsInRole(&amp;amp;quot;Guest&amp;amp;quot;);
}

public bool IsAdmin()
{
    return HttpContext.Current.User.IsInRole(&amp;amp;quot;Admin&amp;amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;public interface ICurrentUser
{
string Name();
bool IsLoggedIn();
bool IsGuest();
bool IsAdmin();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now I need to update the controller to inject this dependency into the constructor so it can be mocked, and use a private field set in the constructor for subsequent calls to _currentUser:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class OrderController : Controller
{
    private readonly ICurrentUser _currentUser;
&lt;pre&gt;&lt;code&gt;public OrderController(ICurrentUser currentUser)
{
    _currentUser = currentUser;
}

[Authorize]
public ActionResult Process()
{
    if (_currentUser.IsAdmin())
    {
        return View(&amp;amp;quot;SecretAdminStuff&amp;amp;quot;);
    }

    return View(&amp;amp;quot;NotAuthorized&amp;amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now we've got a testable action method.  I mock the CurrentUser with &lt;code&gt;MockRepository.GenerateMock&amp;lt;ICurrentUser&amp;gt;&lt;/code&gt;, set its return value with the Rhino Mocks &lt;code&gt;.Stub()&lt;/code&gt; and &lt;code&gt;.Return()&lt;/code&gt; extension methods, and check for the expected results:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[Test]
public void Should_return_NotAuthorized_view_when_not_Admin_user()
{
    // Arrange
    var mockCurrentUser = MockRepository.GenerateMock&amp;lt;ICurrentUser&amp;gt;();
    mockCurrentUser.Stub(x =&amp;gt; x.IsAdmin()).Return(false);
    var orderController = new OrderController(mockCurrentUser);
&lt;pre&gt;&lt;code&gt;// Act
var result = orderController.Process() as ViewResult;

// Assert
result.ViewName.ShouldEqual(&amp;amp;quot;NotAuthorized&amp;amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;[Test]
public void Should_return_SecretAdminStuff_view_when_Admin_user()
{
// Arrange
var mockCurrentUser = MockRepository.GenerateMock&amp;lt;ICurrentUser&amp;gt;();
mockCurrentUser.Stub(x =&amp;gt; x.IsAdmin()).Return(true);
var orderController = new OrderController(mockCurrentUser);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Act
var result = orderController.Process() as ViewResult;

// Assert
result.ViewName.ShouldEqual(&amp;amp;quot;SecretAdminStuff&amp;amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="hey-wait-a-sec"&gt;Hey, wait a sec&lt;/h2&gt;
&lt;p&gt;If you're thinking to yourself: I've just tested the code in the action method and not whether &lt;code&gt;HttpContext&lt;/code&gt; really works, you're exactly right.  The tests should cover the branching in the controller action and are unit tests.  They are &lt;strong&gt;not&lt;/strong&gt; integration tests that check to see if &lt;code&gt;HttpContext&lt;/code&gt; is returning the right values.&lt;/p&gt;
&lt;p&gt;I'm OK with that tradeoff.  I know &lt;code&gt;HttpContext&lt;/code&gt; works.  It's been around forever and it's in a &lt;code&gt;System.&amp;lt;something&amp;gt;&lt;/code&gt; namespace, so I shouldn't be testing it.&lt;/p&gt;
&lt;p&gt;The real question is, do my login and roles and authorization settings work as expected in my application.  That calls for integration testing, and the easiest way to do that is click through those screens and see if it's working.  You can also automate this clicking around with &lt;a href="https://www.nuget.org/packages/WatiN/"&gt;Watin&lt;/a&gt;, or &lt;a href="http://www.specflow.org/"&gt;SpecFlow&lt;/a&gt; (which uses Watin internally to drive the browser).&lt;/p&gt;
</description>
      <pubDate>Thu, 19 Aug 2010 10:40:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/which-ioc-container-should-i-use</guid>
      <link>https://volaresoftware.com/nl/technical-posts/which-ioc-container-should-i-use</link>
      <title>Which IoC container should I use?</title>
      <description>&lt;p&gt;This came up on the &lt;a href="http://tech.groups.yahoo.com/group/altdotnet/"&gt;Alt.Net Yahoo Group/mailing list&lt;/a&gt; today.  There are tons of tools out there for inversion of control.  They have been compared &lt;a href="http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx"&gt;here&lt;/a&gt; and other places online.  Nobody wants their app tied to the &lt;a href="http://en.wikipedia.org/wiki/Betamax"&gt;Betamax&lt;/a&gt; of IoC tools, so people are anxious to pick the best one.&lt;/p&gt;
&lt;p&gt;All containers keep a hash table of your interfaces mapped to your concrete classes.  Most will let you request a specific instance with a string token.  Most will let you control instance creation (singleton, etc.).  The popular IoC containers have fluent configuration and use conventions to figure out that IEmailService maps to EmailService.&lt;/p&gt;
&lt;p&gt;So which one should you pick?  &lt;strong&gt;Go with the one you already know best and/or the one that is easiest for your dev team to configure&lt;/strong&gt;.  That's because with the &lt;a href="http://www.codeplex.com/CommonServiceLocator"&gt;Common Service Locator&lt;/a&gt; wrapping your IoC get instance calls, the provider becomes a moot point.&lt;/p&gt;
&lt;p&gt;This is an old OO principal - encapsulate the stuff that can change.  &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2008/08/16/it-s-time-for-ioc-container-detente.aspx"&gt;Jeremy Miller pointed out the need for a common IoC wrapper&lt;/a&gt; to do just this.  Today's hot new open source IoC container could be tomorrow's dormant project.  If you wrap the calls, you can rip out your IoC provider and most of your code stays the same since it's calling the wrapper.&lt;/p&gt;
&lt;p&gt;Here's how I'm doing this using &lt;a href="http://www.castleproject.org/container/index.html"&gt;Castle Windsor&lt;/a&gt; in a Sharp Architecture project.  First, I create a class to wire up my IoC configurations for my app.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public static class RegisterIoCContainer
{
    public static void AddComponentsTo(IWindsorContainer container)
    {
        AddApplicationConcernsTo(container);
        AddCoreConcernsTo(container);
    }
&lt;pre&gt;&lt;code&gt;private static void AddApplicationConcernsTo(IWindsorContainer container)
{
    container.Register(Component
        .For&amp;amp;lt;IMappingEngine&amp;amp;gt;
        .Instance(Mapper.Engine)
        .LifeStyle.Singleton);

    container.Register(AllTypes.Pick()
        .FromAssemblyNamed(&amp;amp;quot;MyApp.ApplicationServices&amp;amp;quot;)
        .WithService.FirstInterface()
        .Configure(c =&amp;amp;gt; c.LifeStyle.Transient));
}

private static void AddCoreConcernsTo(IWindsorContainer container)
{
    container.Register(AllTypes.Pick()
        .FromAssemblyNamed(&amp;amp;quot;MyApp.Infrastructure&amp;amp;quot;)
        .WithService.FirstNonGenericCoreInterface(&amp;amp;quot;MyApp.Core&amp;amp;quot;)
        .Configure(c =&amp;amp;gt; c.LifeStyle.Transient));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note the use of convention-based mappings between assemblies and the different instance lifestyles.  &lt;code&gt;Mapper.Engine&lt;/code&gt; has a Singleton lifestyle.  Not that there's anything wrong with that. :&amp;gt;&lt;/p&gt;
&lt;p&gt;Next, I create a class to tell Common Service Locator to use Castle Windsor as the provider and to load up those IoC configurations:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public static class RegisterServiceLocator
{
    public static void Register()
    {
        var container = new WindsorContainer();
&lt;pre&gt;&lt;code&gt;    ServiceLocator.SetLocatorProvider(() =&amp;amp;gt; new WindsorServiceLocator(container));

    RegisterIoCContainer.AddComponentsTo(container);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then I call &lt;code&gt;RegisterServiceLocator.Register()&lt;/code&gt; on &lt;code&gt;Application_Start()&lt;/code&gt; in the &lt;code&gt;Global.asax&lt;/code&gt;.  From then on, I can call the Common Service Locator to get my instance from my interface:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var instance = ServiceLocator.Current.GetInstance&amp;lt;IEmailService&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I don't often need to use this syntax, since I'm usually pushing external dependencies into a constructor and letting auto-wiring resolve the dependency chain for me.  But I do use this syntax for testing that Common Service Locator is finding the instance I want.&lt;/p&gt;
</description>
      <pubDate>Sat, 10 Oct 2009 00:41:32 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/adding-requirejs-to-an-aspnet-mvc-project</guid>
      <link>https://volaresoftware.com/nl/technical-posts/adding-requirejs-to-an-aspnet-mvc-project</link>
      <title>Adding RequireJS to an ASP.NET MVC project</title>
      <description>&lt;h2 id="why-requirejs"&gt;Why RequireJS?&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://requirejs.org/"&gt;RequireJS&lt;/a&gt; is a popular JavaScript module loader.  RequireJS solves the problem of needing to invoke some JavaScript code from another file, but not knowing if that file has been loaded yet.&lt;/p&gt;
&lt;p&gt;It does this with either a define or a require declaration, which takes an array of strings and a callback function, then passes in the module names as arguments so you can reference them in your JavaScript code.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;define([&amp;quot;jquery&amp;quot;, &amp;quot;moment&amp;quot;],
    function ($, moment) {
        &amp;quot;use strict&amp;quot;;
&lt;pre&gt;&lt;code&gt;    var init = function () {
        // Requires MomentJS to be loaded. 
        // &amp;amp;quot;moment&amp;amp;quot; is the argument passed in by RequireJS for the MomentJS module, aliased as &amp;amp;quot;moment&amp;amp;quot; in the define/require statement.
        var now = new moment().format(&amp;amp;quot;M/D/YYYY h:mm:ss A&amp;amp;quot;);

        // Requires jQuery to be loaded. 
        // &amp;amp;quot;$&amp;amp;quot; is the argument passed in by RequireJS for the &amp;amp;quot;jquery&amp;amp;quot; module in the define/require statement.
        $(&amp;amp;quot;#currentDateTime&amp;amp;quot;).text(now);
    };

    return {
        init: init
    };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here &amp;quot;moment&amp;quot; is both the name of the module to load, and the argument passed in for that module name.  It could have been &amp;quot;m&amp;quot; throughout, and it would still work.  The same is also true for &amp;quot;jquery at the top in the define, which tells RequireJS what module to load, and &amp;quot;&lt;span class="math"&gt;\(&amp;quot; below that, which tells RequireJS to load that module into an argument named &amp;quot;\)&lt;/span&gt;&amp;quot;.  We're using &amp;quot;moment&amp;quot; and &amp;quot;&lt;span class="math"&gt;\(&amp;quot; inside the function so the code looks conventional, but the &amp;quot;\)&lt;/span&gt;&amp;quot; could have been &amp;quot;j&amp;quot; if you wanted it to be.&lt;/p&gt;
&lt;p&gt;RequireJS guarantees that the external modules are loaded by the time your code runs.  It also keeps track of which modules have already been loaded on the page, so it doesn't pull in the same module twice.&lt;/p&gt;
&lt;h2 id="so-which-is-it-require-or-define"&gt;So which is it – require() or define()?&lt;/h2&gt;
&lt;p&gt;The require and define statement are the main ways you use RequireJS. The API signature is the same for both, but they work differently: &amp;quot;define&amp;quot; is for modules that will be loaded and run by code that uses a &amp;quot;require&amp;quot; statement to pull that module in. So think of &amp;quot;define&amp;quot; as your module definitions, and &amp;quot;require&amp;quot; as the way to execute them.&lt;/p&gt;
&lt;p&gt;As you can see, the RequireJS usage is very simple and clean.  The setup can be a headache, especially around paths, so I'll take you through how I've done it.&lt;/p&gt;
&lt;h2 id="configuring-your-paths-in-main.js"&gt;Configuring your paths in main.js&lt;/h2&gt;
&lt;p&gt;RequireJS needs to be configured.  When we said &amp;quot;jquery&amp;quot; and &amp;quot;moment&amp;quot; above, we have to tell RequireJS where those files are so we can use those aliases.  That's where &lt;code&gt;main.js&lt;/code&gt; and &lt;code&gt;required.config()&lt;/code&gt; come in:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;require.config({
    baseUrl: &amp;quot;/Scripts/app&amp;quot;,
    paths: {
        jquery: &amp;quot;../lib/jquery-2.1.1&amp;quot;,
        jqueryValidate: &amp;quot;../lib/jquery.validate&amp;quot;,
        jqueryValidateUnobtrusive: &amp;quot;../lib/jquery.validate.unobtrusive&amp;quot;,
        bootstrap: &amp;quot;../lib/bootstrap&amp;quot;,
        moment: &amp;quot;../lib/moment&amp;quot;
    },
    shim: {
        jqueryValidate: [&amp;quot;jquery&amp;quot;],
        jqueryValidateUnobtrusive: [&amp;quot;jquery&amp;quot;, &amp;quot;jqueryValidate&amp;quot;]
    }
});
&lt;p&gt;require([&amp;quot;kickoff&amp;quot;], function(kickoff) {
kickoff.init();
}
);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;RequireJS uses the baseUrl setting in main.js if you pass it a script name that is not an alias in the paths section.  In other words, if you call &amp;quot;jquery&amp;quot; in your define/require, it knows from your paths setting where to go.  If you call &amp;quot;myScript&amp;quot; in define/require, it looks for it in the baseUrl path, which is &lt;code&gt;/Scripts/app&lt;/code&gt; in this case.&lt;/p&gt;
&lt;p&gt;Notice there are no &lt;code&gt;.js&lt;/code&gt; extensions to the end of the file names?  This is something RequireJS does to help you.  It's a JavaScript loader; it knows those are JavaScript files.  In my view, this just adds to some of the confusion of configuring this thing.&lt;/p&gt;
&lt;p&gt;Here's how I've got my paths configured under my Scripts folder in Visual Studio:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2014/5/image_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2014/5/image_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;You can set up different folder structures or names based on your preferences, but it probably makes sense for &lt;code&gt;main.js&lt;/code&gt;, which is the entry point of the app, to be at the root of &lt;code&gt;/Scripts&lt;/code&gt;, or at least above your &lt;code&gt;/app&lt;/code&gt; and&lt;code&gt; /lib&lt;/code&gt; script folders.  Also, you don't have to name your file &lt;code&gt;main.js&lt;/code&gt;. that's just a RequireJS convention.&lt;/p&gt;
&lt;p&gt;The shim section in the code above is to tell RequireJS about any dependencies your files have before they can be used.  Here, we are saying if we call &amp;quot;jqueryValidate&amp;quot; to load that module, we have to load &amp;quot;jquery&amp;quot; first.  The &amp;quot;jqueryValidateUnobtrusive&amp;quot; module has to load &amp;quot;jqueryValidate&amp;quot; and &amp;quot;jquery&amp;quot; first, before it can be used.  You could probably shorten the shim for &amp;quot;jqueryValidateUnobtrusive&amp;quot; to just &amp;quot;jqueryValidate&amp;quot;, since that module requires &amp;quot;jquery&amp;quot;, and RequireJS tracks the whole dependency graph for you.  It doesn't hurt to leave it in, either.&lt;/p&gt;
&lt;p&gt;For many apps, it makes sense to call code to load the app or run code on every page from the main.js file, and we've done that here with a call to &amp;quot;kickoff.init()&amp;quot;.&lt;/p&gt;
&lt;h2 id="calling-the-main.js-file"&gt;Calling the main.js file&lt;/h2&gt;
&lt;p&gt;The normal advice for adding RequireJS to an app is to put this line in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of &lt;code&gt;_Layout.cshtml&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script data-main=&amp;quot;Scripts/main&amp;quot; src=&amp;quot;/Scripts/lib/require.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a kind of weird looking script tag.  The src attribute is normal enough for pulling in RequireJS, but the data-main is new.  That's RequireJS's special attribute for getting the path to main.js.  Notice again there is no &amp;quot;.js&amp;quot; in the data-main.  RequireJS knows it's a .js file and appends that automatically.&lt;/p&gt;
&lt;p&gt;This script tag is usually all you need for a single page app, where all modules run inside one full page request.&lt;/p&gt;
&lt;h2 id="set-up-for-multi-page-apps"&gt;Set up for multi-page apps&lt;/h2&gt;
&lt;p&gt;I don't see too many single-page apps in the wild.  More often, they are multi-page apps where each page has a LOT going on.  If you aren't building a single page app, you can still take advantage of RequireJS, but we need to change some things.&lt;/p&gt;
&lt;p&gt;We need to change the code that loads RequireJS and main.js in &lt;code&gt;_Layout.cshtml&lt;/code&gt; from:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script data-main=&amp;quot;Scripts/main&amp;quot; src=&amp;quot;/Scripts/lib/require.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;    &amp;lt;script src=&amp;quot;/Scripts/lib/require.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    @RenderSection(&amp;quot;scripts&amp;quot;, required: false)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can put this right before the closing &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt; tag if you like, but RequireJS will inject &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags with the &lt;code&gt;async&lt;/code&gt; attribute in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/script_before_closing_body_tag.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/script_before_closing_body_tag.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now we've got a common layout, and a hook in each page (the Razor &lt;code&gt;@RenderSection&lt;/code&gt;) where we can load THAT page's scripts.  In each page, you'll then need something like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;@section scripts
{
    &amp;lt;script&amp;gt;
        require([&amp;quot;Scripts/main&amp;quot;],
            function () {
                require([&amp;quot;currentDateTime&amp;quot;],
                    function (currentDateTime) {
                        currentDateTime.init();
                    }
                );
            }
        );
    &amp;lt;/script&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each page will be different, depending on what you need to load and run, but you will always load and run main.js, then when that's done, you'll load the scripts just for that page in the inner require().  Note this inner require() is pulling in the code that was in the define() at the top of this post.&lt;/p&gt;
&lt;p&gt;Now drop this code in on every page in your app, but first…&lt;/p&gt;
&lt;h2 id="what-about-jquery-and-dom-loading"&gt;What about jQuery and DOM loading?&lt;/h2&gt;
&lt;p&gt;What if your JavaScript loads before the DOM is loaded?  With jQuery, we normally call:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;$(function () {
    ...the code to run on DOM ready...
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So how do we know the DOM is loaded before we start touching it in RequireJS world?  We need to use the &lt;a href="http://requirejs.org/docs/download.html#domReady"&gt;domReady plugin&lt;/a&gt; with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;require([&amp;quot;domReady!&amp;quot;],
    function() {
        ...the code to run on DOM ready...
    }
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Download the plugin and put it in the /Scripts/lib folder.  Now we have a new file we want to alias, so we need to add that to our &lt;code&gt;require.config&lt;/code&gt; paths in &lt;code&gt;main.js&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;paths: {
    jquery: &amp;quot;../lib/jquery-2.1.1&amp;quot;,
    jqueryValidate: &amp;quot;../lib/jquery.validate&amp;quot;,
    jqueryValidateUnobtrusive: &amp;quot;../lib/jquery.validate.unobtrusive&amp;quot;,
    bootstrap: &amp;quot;../lib/bootstrap&amp;quot;,
    moment: &amp;quot;../lib/moment&amp;quot;,
    domReady: &amp;quot;../lib/domReady&amp;quot;,
},
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There we go.  We have another piece of our run-on-every-page code snippet.&lt;/p&gt;
&lt;h2 id="mvc-helpers"&gt;MVC Helpers&lt;/h2&gt;
&lt;p&gt;When you start repeating yourself in an MVC view, consider adding an HTML Helper.  What we want generically is:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;require([&amp;quot;Scripts/main&amp;quot;],
    function () {
        require([&amp;quot;...the module to load...&amp;quot;, &amp;quot;domReady!&amp;quot;],
            ...run the module...
        );
    }
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We also don't want to have to think about relative paths.  We want the scripts to find &lt;code&gt;main.js&lt;/code&gt; and the &lt;code&gt;/Scripts/app&lt;/code&gt; and &lt;code&gt;/Scripts/lib&lt;/code&gt; folder whether the page is located at the root (&lt;code&gt;/&lt;/code&gt;) or &lt;code&gt;/Deep/Within/The/Site&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here's the C# to do that:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
&lt;p&gt;namespace RequireJSWithMVC.Extensions
{
public static class RequireJsHelpers
{
public static MvcHtmlString InitPageMainModule(this HtmlHelper helper, string pageModule)
{
var require = new StringBuilder();
var scriptsPath = &amp;quot;~/Scripts/&amp;quot;;
var absolutePath = VirtualPathUtility.ToAbsolute(scriptsPath);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        require.AppendLine(&amp;amp;quot;&amp;amp;lt;script&amp;amp;gt;&amp;amp;quot;);
        require.AppendFormat(&amp;amp;quot;    require([\&amp;amp;quot;{0}main.js\&amp;amp;quot;],&amp;amp;quot; + Environment.NewLine, absolutePath);
        require.AppendLine(&amp;amp;quot;        function() {&amp;amp;quot;);
        require.AppendFormat(&amp;amp;quot;            require([\&amp;amp;quot;{0}\&amp;amp;quot;, \&amp;amp;quot;domReady!\&amp;amp;quot;]);&amp;amp;quot; + Environment.NewLine, pageModule);
        require.AppendLine(&amp;amp;quot;        }&amp;amp;quot;);
        require.AppendLine(&amp;amp;quot;    );&amp;amp;quot;);
        require.AppendLine(&amp;amp;quot;&amp;amp;lt;/script&amp;amp;gt;&amp;amp;quot;);

        return new MvcHtmlString(require.ToString());
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;What we're going for is having several things loaded on every page: 1) require.js, 2) main.js, 3) the DOM, and 4) the main JavaScript module for that page and anything that module needs.  This &amp;quot;main module&amp;quot; concept works well to just run as it's loaded instead of forcing the caller to invoke it with an init() call, so let's change our &amp;quot;currentDateTime.js&amp;quot; module from above to do that and create &amp;quot;main-currentDateTime.js&amp;quot; instead:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;require([&amp;quot;jquery&amp;quot;, &amp;quot;moment&amp;quot;],
    function ($, moment) {
        &amp;quot;use strict&amp;quot;;
&lt;pre&gt;&lt;code&gt;    // Requires MomentJS to be loaded. 
    // &amp;amp;quot;moment&amp;amp;quot; is the argument passed in by RequireJS for the MomentJS module, aliased as &amp;amp;quot;moment&amp;amp;quot; in the require statement.
    var now = new moment().format(&amp;amp;quot;M/D/YYYY h:mm:ss A&amp;amp;quot;);

    // Requires jQuery to be loaded. 
    // &amp;amp;quot;$&amp;amp;quot; is the argument passed in by RequireJS for the &amp;amp;quot;jquery&amp;amp;quot; module in the require statement.
    $(&amp;amp;quot;#currentDateTime&amp;amp;quot;).text(now);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;We've also changed from define() to require() since this is a self-loading module, not one a caller has to invoke.  We got rid of the init() function so this code runs when the module is loaded.&lt;/p&gt;
&lt;h2 id="download"&gt;Download&lt;/h2&gt;
&lt;p&gt;That should do it for adding RequireJS to your MVC mutli-page app.  All the code above is available for &lt;a href="https://github.com/VolareSoftware/RequireJSWithMVC"&gt;view/download on GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Wed, 28 May 2014 00:39:29 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/why-im-using-moq-instead-of-rhino-mocks-these-days</guid>
      <link>https://volaresoftware.com/nl/technical-posts/why-im-using-moq-instead-of-rhino-mocks-these-days</link>
      <title>Why I'm using Moq instead of Rhino Mocks these days</title>
      <description>&lt;p&gt;On my last &lt;a href="http://en.wikipedia.org/wiki/Greenfield_project"&gt;greenfield project&lt;/a&gt; I got to pick the unit testing and mocking tools.  I've been a regular &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt; user for a long time, but I've seen lots of code samples with &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; and liked the syntax, so I gave it a try.&lt;/p&gt;
&lt;p&gt;I have to say, I did prefer Moq slightly to Rhino Mocks.  The newer Arrange, Act, Assert (AAA) style syntax in Rhino Mocks is a huge improvement over the old Record/Replay mess.  But Moq has the benefit of being born at the right time and has AAA style calls without the burden of supporting deprecated syntax.  This means Moq has cleaner documentation, fewer options, and fewer ways to get confused by the API.  I really couldn't find anything I needed to do in Moq that I couldn't do.  I did get a little tripped up having to get the object out of the mock, with myMock.Object calls, but that wasn't a big deal.&lt;/p&gt;
&lt;p&gt;Here's the &lt;a href="http://nuget.org/List/Packages/Moq"&gt;NuGet Moq install package&lt;/a&gt; syntax to add Moq to your unit test project:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2011/3/image7_1.png" alt="image7_1.png" /&gt;&lt;/p&gt;
&lt;p&gt;I'm using mocking frameworks less these days.  Instead, I'll write a fake object myself or just try to avoid interaction testing altogether.  But if I needed to pull one off the shelf today, I'd grab Moq first.&lt;/p&gt;
</description>
      <pubDate>Thu, 10 Mar 2011 01:40:15 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/lazy-load-off-screen-images-with-lazysizes</guid>
      <link>https://volaresoftware.com/nl/technical-posts/lazy-load-off-screen-images-with-lazysizes</link>
      <title>Lazy load off-screen images with lazysizes</title>
      <description>&lt;p&gt;Many users will never scroll all the way down to see the awesome images below the fold on your web site. If you load all your images when the page loads, you are wasting bandwidth and slowing down the page start-up experience.&lt;/p&gt;
&lt;p&gt;Instead, you can lazy-load images as they are about to come into view. The latest way to do this is using Intersectional Observer, but &lt;a href="https://caniuse.com/#feat=intersectionobserver"&gt;it isn't supported on Safari, iOS Safari, or IE11&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I opted to use &lt;a href="https://www.npmjs.com/package/lazysizes"&gt;lazysizes&lt;/a&gt; to deal with cross-browser differences, viewport size differences, scroll speeds, and the other headaches you could get rolling your own solution. To see it in action, &lt;a href="http://afarkas.github.io/lazysizes/"&gt;go to their test page&lt;/a&gt;, open your browser tools Network tab, filter for Images, and scroll down.  You'll see new images loaded as you get closer to them. It's slick.&lt;/p&gt;
&lt;p&gt;The easiest way to use lazysizes is to reference the script in your page:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script src=&amp;quot;lazysizes.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then change &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags from &lt;code&gt;src=&amp;quot;myImage.jpg&amp;quot;&lt;/code&gt; to &lt;code&gt;data-src=&amp;quot;myImage.jpg&amp;quot;&lt;/code&gt; and add &lt;code&gt;class=&amp;quot;lazyload&amp;quot;&lt;/code&gt; like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;img data-src=&amp;quot;myImage.jpg&amp;quot; class=&amp;quot;lazyload&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can get fancier with &lt;a href="https://github.com/aFarkas/lazysizes#responsive-image-support-picture-andor-srcset"&gt;responsive image sets&lt;/a&gt; and &lt;a href="https://github.com/aFarkas/lazysizes#responsive-image-support-picture-andor-srcset"&gt;lazy loading CSS background images&lt;/a&gt;, too.&lt;/p&gt;
</description>
      <pubDate>Mon, 23 Apr 2018 00:39:09 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/where-should-validation-go</guid>
      <link>https://volaresoftware.com/nl/technical-posts/where-should-validation-go</link>
      <title>Where should validation go?</title>
      <description>&lt;p&gt;&lt;code&gt;&amp;lt;groan&amp;gt;&lt;/code&gt;Not this argument again!&lt;code&gt;&amp;lt;/groan&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The short answer: I don't know.&lt;/p&gt;
&lt;p&gt;The long answer: Yeah, I &lt;strong&gt;really&lt;/strong&gt; don't know.&lt;/p&gt;
&lt;p&gt;There is still no widely accepted answer on this one.  Reasonable people disagree.  One camp pushes it up closer to the UI, the other down lower so it shelters the domain from invalid states.  Some like it sprinkled across layers; some like it centralized.&lt;/p&gt;
&lt;p&gt;I think Steve Sanderson is correct that &lt;a href="http://blog.codeville.net/2008/09/08/thoughts-on-validation-in-aspnet-mvc-applications/"&gt;validation falls on a continuum&lt;/a&gt; from easy UI validation, like required fields, to complex business rules that need to be checked closer to or in the domain entities.&lt;/p&gt;
&lt;p&gt;I also think Jimmy Bogard is correct that &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/02/15/validation-in-a-ddd-world.aspx"&gt;context matters when it comes to validation&lt;/a&gt;.  This object is valid for what?  Saving to the database?  Emailing to sales?  Displaying on the screen?  The validation rules depend on the the behavior you are validating.&lt;/p&gt;
&lt;p&gt;These days, I think of validation as either UI Validation (required fields, min/max length, etc.), Domain Validation (start date/time must be before end date/time, order must have at least one item, etc.), or Database Validation (is this value unique, is this ID value going to throw a foreign key violation).  This is based on &lt;strong&gt;when&lt;/strong&gt; you can validate in the call chain more than &lt;strong&gt;what&lt;/strong&gt; it's valid for.  I still like validation in context, but those business rules end up in my Domain Validation logic with method names like &lt;code&gt;CanSendEmailToCustomer()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.sharparchitecture.net/"&gt;Sharp Architecture&lt;/a&gt; uses &lt;a href="http://nhforge.org/wikis/validator/nhibernate-validator-1-0-0-documentation.aspx"&gt;NHibernate Validators&lt;/a&gt; as attributes on the domain entities.  The best thing about this is your validation is centralized.  It's sitting right there in your domain, and you know where to go if there is a rule change.&lt;/p&gt;
&lt;p&gt;The other good thing about this approach is your entity should always be valid when saved.  The built-in &lt;code&gt;Repository&amp;lt;TEntity&amp;gt;&lt;/code&gt; calls in Sharp Architecture enforce validation before inserts and updates, so you're covered there.  If you want to call &lt;code&gt;MyEntity.IsValid()&lt;/code&gt; in a method, you can do that as well.&lt;/p&gt;
&lt;p&gt;The bad thing is those validation attributes can start looking like UI concerns when they have user-centric error messages in them (&amp;quot;Hey, user, that's not a valid format for a phone number&amp;quot;).  And if there is a rule that doesn't lend itself to attributes (e.g., orders must have at least one order item), you are on your own.&lt;/p&gt;
&lt;p&gt;I started with validation attributes on my domain entities, and when my attribute messages got too UI-looking, I moved to using &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt; on DTOs in my application service layer for UI validation.  The DTOs are made to be client facing, so I'm not bothered by user-specific messages in them.&lt;/p&gt;
&lt;p&gt;Then when Domain or Database Validation problems come up, a &lt;code&gt;ValidationException&lt;/code&gt; is thrown up through the application service to the UI so the calling app can either display or handle it.  I haven't played with it yet, but I think this is what &lt;a href="http://xval.codeplex.com/"&gt;xVal&lt;/a&gt; is doing, too.&lt;/p&gt;
&lt;p&gt;The more I think about it, the more I see my web app as just another client calling into my application service layer which is encapsulating my domain.  So my web app is the &amp;quot;user&amp;quot; and the message needs to be just enough for &lt;strong&gt;that&lt;/strong&gt; user, not necessarily the end user.  Maybe a validation exception token is sent out from the application service layer to the UI, and the UI translates that to a string from a very UI-centric resource file?&lt;/p&gt;
&lt;p&gt;Bu I'm still not happy with this.  I feel like I have the right kind of validation in the right places, but I would still like a more centralized approach for easier refactoring of business rules.  I've used the &lt;a href="http://en.wikipedia.org/wiki/Specification_pattern"&gt;Specification Pattern&lt;/a&gt; before, and it does a great job of centralizing the rules.  But making yet another class for yet another required field and adding it to yet another Composite Specification?  Seems like your walking away from a lot of the productivity attributes can give you.&lt;/p&gt;
&lt;p&gt;Obviously, my thoughts on validation are still not fully formed.  I'm still arguing with myself.  My dream validation would be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;centralized for easy refactoring and rule changes&lt;/li&gt;
&lt;li&gt;automatically called for routine things so I don't forget (like saving the order to the database)&lt;/li&gt;
&lt;li&gt;allow ad hoc calls for non-routine things (like validating the order confirmation email can be sent to the customer)&lt;/li&gt;
&lt;li&gt;handle simple validation like attributes so I can be productive&lt;/li&gt;
&lt;li&gt;handle complex validation like specifications so I'm not limited&lt;/li&gt;
&lt;li&gt;UI-agnostic so the centralized validation goo isn't holding end-user strings, except when I'm too lazy to set up the resource file, in which case strings can be passed up from this layer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I told you I didn't know! :)&lt;/p&gt;
</description>
      <pubDate>Tue, 15 Sep 2009 00:41:26 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/specifying-args-with-rhino-mocks</guid>
      <link>https://volaresoftware.com/nl/technical-posts/specifying-args-with-rhino-mocks</link>
      <title>Specifying Args with Rhino Mocks</title>
      <description>&lt;h2 id="the-problem"&gt;The problem&lt;/h2&gt;
&lt;p&gt;I ran into a snag testing some code today with Rhino Mocks.  I was mocking calls to a repository and inspecting the repository method calls and arguments passed.&lt;/p&gt;
&lt;p&gt;Everything started off pretty normal with the repository dependency injected into the class under test:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Arrange
var repository = MockRepository.GenerateMock&amp;lt;ICustomerRepository&amp;gt;();
var passenger = new Passenger(repository);
&lt;p&gt;// Act
passenger.CallTheMethodUnderTest(arg1, arg2);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In my Assert section, I needed to check that the correct repository methods were called with the correct arguments.  The catch was, one of the arguments was a class created &lt;strong&gt;within&lt;/strong&gt; the method under test.  I thought I could create and assert the equivalent Customer in my test like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Assert
var expectedCustomer = new Customer
                           {
                               CustomerID = &amp;quot;1234&amp;quot;,
                               FirstName = &amp;quot;Joe&amp;quot;,
                               LastName = &amp;quot;Wilson&amp;quot;
                           };
repository.AssertWasCalled(x =&amp;gt; x.SomeRepositoryMethod(
    arg1, 
    arg2, 
    expectedCustomer));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The two Customer objects (in the test and in the method under test) had the same values, but of course, were not the same objects.  They were two different Customer objects that happened to have the same values.  So Rhino Mocks told me that my expected Assert wasn't met.&lt;/p&gt;
&lt;h2 id="the-answer"&gt;The answer&lt;/h2&gt;
&lt;p&gt;I knew Rhino Mocks could ignore arguments with&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;Args&amp;lt;T&amp;gt;.Is.Anything
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But I knew what the values should be.  In fact, for this test, the values being passed into the repository calls were just as important as the calls themselves.&lt;/p&gt;
&lt;p&gt;So I tried comparing the &lt;strong&gt;values&lt;/strong&gt; of the two Customer objects instead of the objects themselves:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;repository.AssertWasCalled(x =&amp;gt; x.SomeRepositoryMethod(
    arg1,
    arg2,
    Arg&amp;lt;Customer&amp;gt;.Matches(c =&amp;gt; 
        c.CustomerID.Equals(&amp;quot;1234&amp;quot;) &amp;amp;amp;&amp;amp;amp;
        c.FirstName.Equals(&amp;quot;Joe&amp;quot;) &amp;amp;amp;&amp;amp;amp;
        c.LastName.Equals(&amp;quot;Wilson&amp;quot;))));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So close!  But now Rhino Mocks told me if I used Arg for one parameter, I'd better use it for all of them.  No biggie. I made the change and this worked:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;repository.AssertWasCalled(x =&amp;gt; x.SomeRepositoryMethod(
    Arg&amp;lt;int&amp;gt;.Is.Equal(arg1),
    Arg&amp;lt;int&amp;gt;.Is.Equal(arg2),
    Arg&amp;lt;Customer&amp;gt;.Matches(c =&amp;gt; 
        c.CustomerID.Equals(&amp;quot;1234&amp;quot;) &amp;amp;amp;&amp;amp;amp;
        c.FirstName.Equals(&amp;quot;Joe&amp;quot;) &amp;amp;amp;&amp;amp;amp;
        c.LastName.Equals(&amp;quot;Wilson&amp;quot;))));
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="postmortem"&gt;Postmortem&lt;/h2&gt;
&lt;p&gt;The Arg statement let's you specify a type and tell Rhino Mocks you don't know or don't care about the value:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;Args&amp;lt;int&amp;gt;.Is.Anything
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also tell Rhino Mocks you know the type &lt;strong&gt;and&lt;/strong&gt; what the value should be:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;Args&amp;lt;int&amp;gt;.Is.Equal(7)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you have a non-primitive type or complex assert, you can also inspect values with the Matches statement:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;Arg&amp;lt;Customer&amp;gt;.Matches(c =&amp;gt; 
    c.CustomerID.Equals(&amp;quot;1234&amp;quot;) &amp;amp;amp;&amp;amp;amp;
    c.FirstName.Equals(&amp;quot;Joe&amp;quot;) &amp;amp;amp;&amp;amp;amp;
    c.LastName.Equals(&amp;quot;Wilson&amp;quot;))));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I realize the code in these tests is probably way too familiar with the code under test.  I prefer testing state over this kind of interaction testing where possible.  But this was a case where the code under test had a void return and didn't do much besides parse some values and call repository methods based on those values.&lt;/p&gt;
&lt;p&gt;In times like this, I'm glad I have interaction testing to fall back on so I can verify my code is behaving the way it should.&lt;/p&gt;
</description>
      <pubDate>Thu, 26 Nov 2009 01:41:11 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/review-of-sharp-architecture</guid>
      <link>https://volaresoftware.com/nl/technical-posts/review-of-sharp-architecture</link>
      <title>Review of Sharp Architecture</title>
      <description>&lt;p&gt;I've been using the open-source project &lt;a href="http://code.google.com/p/sharp-architecture/"&gt;Sharp Architecture&lt;/a&gt; for about 6 months now, and version 1.0 was recently released.  It's a really great way to get rolling quickly on a project using ASP.NET MVC, Domain Driven Design (DDD), NHibernate, and Castle Windsor.&lt;/p&gt;
&lt;p&gt;I won't go into the details about what Sharp Architecture does.  I'll just cover what I like in the first version and what I hope makes it into future releases.&lt;/p&gt;
&lt;h2 id="what-i-like"&gt;What I like&lt;/h2&gt;
&lt;h3 id="decoupled-design"&gt;Decoupled Design&lt;/h3&gt;
&lt;p&gt;The Sharp Architecture framework uses inversion of control right out of the box with &lt;a href="http://www.castleproject.org/"&gt;Castle Windsor&lt;/a&gt; and the &lt;a href="http://www.codeplex.com/CommonServiceLocator"&gt;Common Service Locator&lt;/a&gt; wrapping container calls.  The &lt;code&gt;MyProject.Core&lt;/code&gt; assembly holds your domain model and interfaces to your repositories.  Implementations of those repositories are in &lt;code&gt;MyProject.Data&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is also a &lt;code&gt;MyProject.ApplicationServices&lt;/code&gt; assembly for times when your controller logic starts to look heavier than it should or you prefer to push all your logic into an application layer so you can skim off the MVC UI for something else at some point (Silverlight?  WCF?).  I like this approach with very lightweight controllers and views for just this reason.&lt;/p&gt;
&lt;h3 id="nhibernate-training-wheels"&gt;NHibernate Training Wheels&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/blogs/billy_mccafferty/"&gt;Billy McCafferty&lt;/a&gt;, the principal author on the project, is &lt;a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx"&gt;one of the gurus on NHibernate best practices&lt;/a&gt;.  NHibernate is very powerful, but some tools, like &lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt;, which uses C# code to map your domain to your database instead of XML, are.well.kind of fluid.and still under construction.&lt;/p&gt;
&lt;p&gt;I'm still new to NHibernate and very new to Fluent NHibernate, so I get tripped up often.  It's nice to know that my solution is using best practices for tools where my footing is not as sure, like NHibernate session management.&lt;/p&gt;
&lt;h3 id="templates-conventions"&gt;Templates + Conventions&lt;/h3&gt;
&lt;p&gt;The Visual Studio solution and T4 templates inside Sharp Architecture are the things that makes it different from being just another reference implementation or architecture guidance.  You can get a new, empty Sharp Architecture solution going in about 30 seconds with the Visual Studio solution template.  The T4 templates help you add controllers and views built around conventions and the property names in your domain entity.&lt;/p&gt;
&lt;p&gt;I used to be a big fan of code generation.  It's nice to spit out a bunch of classes very quickly, but there really has to be a balance.  If it gens too much code, is it all stuff you really need?  If it only gens a little bit, did you need a code generator at all?&lt;/p&gt;
&lt;p&gt;Sharp Architecture does a good job of giving you a jump start on stuff you will probably want or at least a place-holder for stuff you will want.  It doesn't litter the solution with too much junk.&lt;/p&gt;
&lt;p&gt;For instance, it doesn't generate a repository for your domain entity because you can use use the &lt;code&gt;IRepository&amp;lt;MyDomainEntity&amp;gt;&lt;/code&gt; and Repository&lt;MyDomainEntity&gt; in the Sharp Architecture assemblies.  It doesn't generate NHibernate mappings for your domain entity because the mapping conventions cover most cases.  If you do need additional repository methods or have unconventional database mappings, it's easy to inherit from and override these.  Sharp Architecture uses generics, base classes, and conventions to keep from needing a lot of code generation.&lt;/p&gt;
&lt;h3 id="documentation-sample-code-wiki-and-forum-support"&gt;Documentation, Sample Code, Wiki, and Forum Support&lt;/h3&gt;
&lt;p&gt;This project is much better documented than most open-source projects.  In addition to the &amp;quot;getting started&amp;quot; and 'using the framework&amp;quot; documents, there is a sample Northwind project that comes with the download files.  Online, there is a &lt;a href="http://wiki.sharparchitecture.net/MainPage.ashx"&gt;wiki&lt;/a&gt; and a &lt;a href="http://groups.google.com/group/sharp-architecture"&gt;Google Group&lt;/a&gt; that is actively monitored if you need additional help.&lt;/p&gt;
&lt;p&gt;I know real programmers only use &lt;a href="http://en.wikipedia.org/wiki/.NET_Reflector"&gt;Reflector&lt;/a&gt; for documentation.  :&amp;gt;  But don't underestimate the value of documentation for widespread adoption.  You can have a great open source project that doesn't get very far if people don't know how to get up and running quickly and fully exploit the framework.  That won't be a problem for Sharp Architecture.&lt;/p&gt;
&lt;h3 id="helpers"&gt;Helpers&lt;/h3&gt;
&lt;p&gt;Sharp Architecture libraries are chock full of all kinds of convenience methods and helpers.  Want to write a database integration test using &lt;a href="http://sqlite.org/"&gt;SQLite&lt;/a&gt;?  Just have your test class inherit from &lt;code&gt;RepositoryTestsBase()&lt;/code&gt;.  Want to hit the live database?  Inherit from &lt;code&gt;DatabaseRepositoryTestsBase()&lt;/code&gt;.  Want to design by contract and check incoming parameters and return values easily?  Look into the Check.Require() and Check.Ensure().&lt;/p&gt;
&lt;p&gt;There are a ton of things like this that all of us have written before.  Most developers I know walk around with a couple assemblies to make coding their next project easier.  With Sharp Architecture, these are referenced in your solution right after File &amp;gt; New Project.&lt;/p&gt;
&lt;h3 id="folder-structure"&gt;Folder Structure&lt;/h3&gt;
&lt;p&gt;Everyone has their own preferred solution and folder structure.  The default project and folder organization in a new Sharp Architecture solution is pretty close to what I was already using and is simple for any developer to jump in and follow along.&lt;/p&gt;
&lt;p&gt;This may not seem like a big deal because a good structure looks obvious in hindsight, but it's nice to not have to dig around for things.  I've worked on solutions that have 20+ projects.  Sharp Architecture goes the other way and you end up with about four projects in a normal MVC app.&lt;/p&gt;
&lt;h2 id="what-i-would-like-to-see-in-future-releases"&gt;What I would like to see in future releases&lt;/h2&gt;
&lt;p&gt;I don't have any strong objections to the design choices in Sharp Architecture.  Most of the things here are more a matter of style/taste than anything.&lt;/p&gt;
&lt;h3 id="controllers-back-in-myproject.web-project"&gt;Controllers back in MyProject.Web project&lt;/h3&gt;
&lt;p&gt;You can read &lt;a href="http://devlicio.us/blogs/billy_mccafferty/archive/2009/01/09/an-argument-for-moving-asp-net-mvc-controllers-to-a-separate-assembly.aspx"&gt;Billy's view on putting the controllers in the web project&lt;/a&gt;. His main point is that controllers should be written and tested independent of the other assemblies so you don't succumb to temptation and do things like go straight to your repository from your controller instead of asking your IoC tool to give you the concrete repository instance.&lt;/p&gt;
&lt;p&gt;That's fair.  But my controllers don't do much besides call into my application services layer, render views, and redirect to other controller actions. I don't mind having a reference to the entire web project in my unit test project so I can test routes and the very little logic I have in my controllers.&lt;/p&gt;
&lt;p&gt;In his article, Billy describes the pain of having done it the way I prefer.  Maybe this is one of those lessons where you have to experience it yourself to internalize it.  Like my dad telling me the stove was hot when I was a kid. :&amp;gt;&lt;/p&gt;
&lt;h3 id="myproject.infrastructure-instead-of-myproject.data"&gt;MyProject.Infrastructure instead of MyProject.Data&lt;/h3&gt;
&lt;p&gt;Maybe I've looked at &lt;a href="http://code.google.com/p/codecampserver/"&gt;Code Camp Server&lt;/a&gt; or listened to Jeffery Palermo talk too much, but I lump data handling into a larger category of infrastructure concerns.  Sharp Architecture's solution template gives you &lt;code&gt;MyProject.Data&lt;/code&gt;, which holds the NHibernate mappings and conventions and the repository classes.&lt;/p&gt;
&lt;p&gt;But I have other utility/infrastructure things I need to put somewhere, like logging, emailing, etc.  I prefer having &lt;code&gt;MyProject.Infrastructure&lt;/code&gt; with Data as a folder underneath it so I can throw all my infrastructure implementation code into that assembly.  The interfaces for these guys still go in &lt;code&gt;MyProject.Core&lt;/code&gt;, just like the repository interfaces.&lt;/p&gt;
&lt;h3 id="more-emphasis-on-myproject.applicationservices"&gt;More emphasis on MyProject.ApplicationServices&lt;/h3&gt;
&lt;p&gt;I prefer to have as little logic as possible in my views and controllers.  I push as much as I can to an application layer so the UI can be replaced or added to with minimal impact.  In Sharp Architecture, you've got &lt;code&gt;MyProject.ApplicationServices&lt;/code&gt; for exactly that.  There is one Northwind example that uses this layer, but in the other samples, the controllers are doing the application flow work.&lt;/p&gt;
&lt;p&gt;I think it's better to have an application service passed into the controller's constructor so the controller doesn't need to know much except routing, views, redirects, the app service method to call, etc.  I don't mind having these UI logic concerns in the controller, but anything beyond that needs to be in an application layer.&lt;/p&gt;
&lt;p&gt;I've borrowed a metaphor from the SQL Server installer that talk about &amp;quot;surface area&amp;quot;.  I think of the &lt;code&gt;MyProject.ApplicationServices&lt;/code&gt; layer as a wrapper around &lt;strong&gt;all&lt;/strong&gt; the app logic.  The methods in this layer are the surface area of my application, and they encapsulates all the implementation code my domain is dealing with.  Calls into this layer can kick off multi-step processes, handle workflow, and usually have long, explicit method names.  But this is the &lt;strong&gt;only&lt;/strong&gt; part of my domain's surface area that is exposed externally.&lt;/p&gt;
&lt;p&gt;The MVC web project is one client calling into this application layer, but there may be others someday on even medium-sized projects.  If your app becomes more popular and you've followed this approach, you can add other clients that call into your application service layer like a WCF service, a system tray tool, etc.  These guys may have their own specialized methods or may use something the web application was using.  Either way, you are very intentional on the surface area you expose.&lt;/p&gt;
&lt;p&gt;I think Sharp Architecture gets this right.  I would just like to give it a little nudge to make it a point of emphasis.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I've used a lot of different frameworks, but Sharp Architecture comes closest to the way I want to work already.  The templates and documentation put it well beyond a reference implementation, and you can work with a simplified solution sitting on top of a lot of abstracted complexity to get you productive right away.&lt;/p&gt;
</description>
      <pubDate>Tue, 15 Sep 2009 00:41:29 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/true-is-truthy-but-truthy-isnt-the-same-as-true</guid>
      <link>https://volaresoftware.com/nl/technical-posts/true-is-truthy-but-truthy-isnt-the-same-as-true</link>
      <title>True is Truthy, but Truthy isn't the same as True</title>
      <description>&lt;p&gt;Most JavaScript developers are familiar with the concepts of &lt;code&gt;truthy&lt;/code&gt; and &lt;code&gt;falsy&lt;/code&gt;.  As a quick refresher, the &lt;code&gt;falsy&lt;/code&gt; values are:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;false
null
undefined
0 (the number zero)
&amp;quot;&amp;quot; (an empty string)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Everything else is &lt;code&gt;truthy&lt;/code&gt;.  This is one of those things you just have to memorize, but it's simpler if you think of the &lt;code&gt;falsy&lt;/code&gt; stuff as things that are false or have no value.  Just watch out for zero and empty string.&lt;/p&gt;
&lt;p&gt;I got burned by a bug today in a passing Jasmine test by not paying enough attention to the &lt;code&gt;truthy&lt;/code&gt; values.  The code I was testing was a little function to make sure &lt;code&gt;scaleMin&lt;/code&gt; was smaller than &lt;code&gt;scaleMax&lt;/code&gt;, but if they were both set to 0, that was OK.  If &lt;code&gt;scaleMin&lt;/code&gt; was greater than or equal to &lt;code&gt;scaleMax&lt;/code&gt;, we'd return an error message.&lt;/p&gt;
&lt;p&gt;Here are the function and tests I started with.  All the tests pass.  Done, right?!?!&lt;/p&gt;
&lt;iframe height="300" src="https://jsfiddle.net/joewilson0/9adyhc1f/embedded/js,result" frameborder="0" width="100%" allowfullscreen="allowfullscreen"&gt;&lt;/iframe&gt;
&lt;p&gt;Not so much.&lt;/p&gt;
&lt;p&gt;Jasmine's &lt;code&gt;toBeTruthy()&lt;/code&gt; checks for any &lt;code&gt;truthy&lt;/code&gt; value, and a string with something in it is &lt;code&gt;truthy&lt;/code&gt;.  So in the test where I'm checking that it's OK if &lt;code&gt;scaleMin&lt;/code&gt; and &lt;code&gt;scaleMax&lt;/code&gt; are both 0, I'm getting the error string, which is &lt;code&gt;truthy&lt;/code&gt;.  Since the error string and the value true are both &lt;code&gt;truthy&lt;/code&gt;, my check for &lt;code&gt;toBeTruthy()&lt;/code&gt; will always pass.  I'm getting false positives.&lt;/p&gt;
&lt;p&gt;This is why you are supposed to write a failing test, then a passing test to prove your code was the thing that made the test pass.  I skipped that here because this code was so simple.  What could go wrong?  Oops!&lt;/p&gt;
&lt;p&gt;Here's the fixed function and test code, which uses Jasmine's &lt;code&gt;toBe(true)&lt;/code&gt; instead of &lt;code&gt;toBeTruthy()&lt;/code&gt; to tease apart error strings and the value true:&lt;/p&gt;
&lt;iframe height="300" src="https://jsfiddle.net/joewilson0/q46z3wer/embedded/js,result" frameborder="0" width="100%" allowfullscreen="allowfullscreen"&gt;&lt;/iframe&gt;
</description>
      <pubDate>Fri, 24 Apr 2015 11:08:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/unit-testing-untestable-code</guid>
      <link>https://volaresoftware.com/nl/technical-posts/unit-testing-untestable-code</link>
      <title>Unit testing untestable code</title>
      <description>&lt;p&gt;Let's say you've got a static or sealed class, or a class with non-virtual members that your code needs to use.  You need to unit test your code, but you can't get an instance of this class and/or you can't mock it.&lt;/p&gt;
&lt;p&gt;There are two ways to go:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Buy a tool that let's you mock things like this, such as &lt;a href="http://site.typemock.com/"&gt;Typemock Isolator&lt;/a&gt; or the newly announced &lt;a href="http://www.telerik.com/products/mocking.aspx"&gt;Telerik JustMock&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Code around it.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="buy-it"&gt;Buy it&lt;/h2&gt;
&lt;p&gt;I've already &lt;a href="https://volaresoftware.com/en/technical-posts/comparison-of-typemock-Isolator-and-rhino-mocks"&gt;compared&lt;/a&gt; Typemock Isolator (&lt;a href="http://www.typemock.com/BuyCommercial.php"&gt;$799&lt;/a&gt;) to RhinoMocks (&lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;free&lt;/a&gt;).  Typemock Isolator works as advertised.  The biggest issue is the price.  It's hard enough to get management approval for introducing external tools.  But when buy-in literally means &lt;strong&gt;BUY&lt;/strong&gt; in, it's even harder.&lt;/p&gt;
&lt;h2 id="build-it"&gt;Build it&lt;/h2&gt;
&lt;p&gt;Don't despair if you're stuck with &amp;quot;code around it&amp;quot; and using free mocking tools!  If you can change the code that is static, sealed, private, non-virtual, etc. fix it that way.  That's the best thing.&lt;/p&gt;
&lt;p&gt;But if it's in a legacy assembly you have to use, and you can't just change the original code, use this simple technique.&lt;/p&gt;
&lt;p&gt;Here's the untestable class we need to use.  It's static, so we can't mock an instance of it with Rhino Mocks.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public static class StaticSendOrderClass
{
    public static void SendOrderToAccountsPayable(Order order)
    {
        // Pretend code here...
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's the new code you're working on that uses this static class to process an order:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class OrderProcessor
{
    public void ProcessTheOrder(Order order, bool useStaticClass)
    {
        if (useStaticClass == true)
        {
            StaticSendOrderClass.SendOrderToAccountsPayable(order);
        }
        else
        {
            // Notify accounts payable some other way
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, we need to create an interface with &lt;strong&gt;just&lt;/strong&gt; the functionality we need from the untestable class.  Name the class and method(s) whatever makes sense for your app.  You're not tied to the legacy code naming convention; this is your code now.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public interface INotifyAccountsPayable
{
    void SendOrder(Order order);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, create a new class to implement this interface and wrap the untestable code.  In the method calls in the new class, turn around and delegate the call to the untestable class.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class NotifyAccountsPayable : INotifyAccountsPayable
{
    public void SendOrder(Order order)
    {
        StaticSendOrderClass.SendOrderToAccountsPayable(order);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now inject the new interface into the constructor of your new class as an argument.  You'll also want to create a private field and set its value to the instance argument in the constructor.  Now you can swap out your old code that calls the untestable code, and instead use your new private field.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class OrderProcessor
{
    private readonly INotifyAccountsPayable _notifyAccountsPayable;
&lt;pre&gt;&lt;code&gt;public OrderProcessor(INotifyAccountsPayable notifyAccountsPayable)
{
    _notifyAccountsPayable = notifyAccountsPayable;
}

public void ProcessTheOrder(Order order, bool useStaticClass)
{
    if (useStaticClass == true)
    {
        _notifyAccountsPayable.SendOrder(order);
    }
    else
    {
        // Notify accounts payable some other way
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now you've got a unit testable &lt;code&gt;OrderProcessor&lt;/code&gt; class!  Mock the &lt;code&gt;INotifyAccountsPayable&lt;/code&gt; interface with Rhino Mocks and inject that mocked dependency into your class under test.  Then you can verify the call was made as expected.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[Test]
public void Should_call_untestable_code_when_useStaticClass_is_set_to_true()
{
    // Arrange
    var mockNotifyAccountsPayable = MockRepository.GenerateMock&amp;lt;INotifyAccountsPayable&amp;gt;();
    var orderProcessor = new OrderProcessor(mockNotifyAccountsPayable);
    var stubOrder = MockRepository.GenerateStub&amp;lt;Order&amp;gt;();
    var useStaticClass = true;
&lt;pre&gt;&lt;code&gt;// Act
orderProcessor.ProcessTheOrder(stubOrder, useStaticClass);

// Assert
mockNotifyAccountsPayable.AssertWasCalled(x =&amp;amp;gt; x.SendOrder(stubOrder));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Please note this is &lt;strong&gt;not&lt;/strong&gt; testing the internals of the untestable, static code.  But you don't need to worry about unit testing the internals of that code.  You don't own that code.  Testing that is really an integration test, not a unit test.  Using this approach, you isolate your new code from an external dependency and keep all your new code testable.&lt;/p&gt;
</description>
      <pubDate>Tue, 06 Apr 2010 05:44:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/upgrading-fontawesome-from-4-to-5</guid>
      <link>https://volaresoftware.com/nl/technical-posts/upgrading-fontawesome-from-4-to-5</link>
      <title>Upgrading FontAwesome from 4 to 5</title>
      <description>&lt;p&gt;&lt;a href="http://fontawesome.io/"&gt;FontAwesome 4&lt;/a&gt; has been around a long time, and it's…well, awesome! Remember their &lt;a href="https://www.kickstarter.com/projects/232193852/font-awesome-5"&gt;Kickstarter with those videos&lt;/a&gt;? Well &lt;a href="https://fontawesome.com/"&gt;FontAwesome 5&lt;/a&gt; is out now, and as promised, it has some big improvements. But to get the benefits, you'll have to work through some breaking changes. Here's what I learned from my upgrade.&lt;/p&gt;
&lt;p&gt;Let's start with a simple page with &lt;a href="https://codepen.io/joewilson0/pen/WdmQPJ"&gt;3 icons using Font Awesome 4&lt;/a&gt;.&lt;/p&gt;
&lt;iframe height="265" style="width: 100%;" scrolling="no" title="FontAwesome 4 simple icon sample" src="https://codepen.io/joewilson0/embed/WdmQPJ?height=265&amp;theme-id=dark&amp;default-tab=html,result" frameborder="no" allowtransparency="true" allowfullscreen="true"&gt;
  See the Pen &lt;a href='https://codepen.io/joewilson0/pen/WdmQPJ'&gt;FontAwesome 4 simple icon sample&lt;/a&gt; by Joe Wilson
  (&lt;a href='https://codepen.io/joewilson0'&gt;@joewilson0&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;The big improvement in FontAwesome 5 is that the icons are drawn with SVG now. Yay for sharp scaling up or down! Now you reference a JavaScript file with the SVG specs embedded in it instead of a CSS file. I'll change the pen to remove the CSS reference and add the JavaScript reference from the CDN:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script defer src=&amp;quot;https://use.fontawesome.com/releases/v5.0.3/js/all.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then &lt;a href="https://codepen.io/joewilson0/pen/KZEdYG/"&gt;check the results&lt;/a&gt;:&lt;/p&gt;
&lt;iframe height="265" style="width: 100%;" scrolling="no" title="FontAwesome 4 to 5 upgrade" src="https://codepen.io/joewilson0/embed/KZEdYG?height=265&amp;theme-id=dark&amp;default-tab=html,result" frameborder="no" allowtransparency="true" allowfullscreen="true"&gt;
  See the Pen &lt;a href='https://codepen.io/joewilson0/pen/KZEdYG'&gt;FontAwesome 4 to 5 upgrade&lt;/a&gt; by Joe Wilson
  (&lt;a href='https://codepen.io/joewilson0'&gt;@joewilson0&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;You can see the icons, but they changed a little. The calendar is very dark, and the arrow is a little more narrow. That's because the way you reference the icons has changed in version 5. Instead of &lt;code&gt;fa&lt;/code&gt; as a style preceding every icon style, you need to pick from &lt;code&gt;fas&lt;/code&gt; for solid, &lt;code&gt;far&lt;/code&gt; for regular, &lt;code&gt;fal&lt;/code&gt; for light, or &lt;code&gt;fab&lt;/code&gt; for brand. It looks like &lt;code&gt;fas&lt;/code&gt; is the fallback, so you get solid if you leave your old &lt;code&gt;fa&lt;/code&gt; references. For most icons, this change makes the icon heavier or lighter.&lt;/p&gt;
&lt;p&gt;If you are biting your nails thinking of all the places you have icons that will now need to change, you can upgrade to 5 and use a shim.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script defer src=&amp;quot;https://use.fontawesome.com/releases/v5.0.3/js/v4-shims.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://codepen.io/joewilson0/pen/WdmQqy/"&gt;That's better&lt;/a&gt;:&lt;/p&gt;
&lt;iframe height="265" style="width: 100%;" scrolling="no" title="FontAwesome 4 to 5 upgrade using shim" src="https://codepen.io/joewilson0/embed/WdmQqy?height=265&amp;theme-id=dark&amp;default-tab=html,result" frameborder="no" allowtransparency="true" allowfullscreen="true"&gt;
  See the Pen &lt;a href='https://codepen.io/joewilson0/pen/WdmQqy'&gt;FontAwesome 4 to 5 upgrade using shim&lt;/a&gt; by Joe Wilson
  (&lt;a href='https://codepen.io/joewilson0'&gt;@joewilson0&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;But if you've got the time and the inclination, skip the shim and change your icon classes to take advantage of the new, lighter styles. If I change all the icons in the same from &lt;code&gt;fa&lt;/code&gt; to &lt;code&gt;far&lt;/code&gt; &lt;a href="https://codepen.io/joewilson0/pen/qpvOeb/"&gt;we get this&lt;/a&gt;:&lt;/p&gt;
&lt;iframe height="265" style="width: 100%;" scrolling="no" title="FontAwesome 4 to 5 upgrade using far icons" src="https://codepen.io/joewilson0/embed/qpvOeb?height=265&amp;theme-id=dark&amp;default-tab=html,result" frameborder="no" allowtransparency="true" allowfullscreen="true"&gt;
  See the Pen &lt;a href='https://codepen.io/joewilson0/pen/qpvOeb'&gt;FontAwesome 4 to 5 upgrade using far icons&lt;/a&gt; by Joe Wilson
  (&lt;a href='https://codepen.io/joewilson0'&gt;@joewilson0&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;That's one of the other big changes. FontAwesome has lots more icons, but to get all of them, you'll need to &lt;a href="https://fontawesome.com/buy/standard"&gt;buy the PRO version&lt;/a&gt; starting at $60 for 5 seats. I think that's a good deal, but the old icons are still free if you only need those.&lt;/p&gt;
&lt;p&gt;Finally, &lt;a href="https://fontawesome.com/how-to-use/upgrading-from-4#icon-name-changes"&gt;some icons changed names&lt;/a&gt;, and you'll need to swap them out if you don't want to use the shim.&lt;/p&gt;
</description>
      <pubDate>Mon, 22 Jan 2018 06:33:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/cache-busting-with-requirejs-and-r-js-in-an-asp-net-mvc-app</guid>
      <link>https://volaresoftware.com/nl/technical-posts/cache-busting-with-requirejs-and-r-js-in-an-asp-net-mvc-app</link>
      <title>Cache busting with RequireJS and R.js in an ASP.NET MVC app</title>
      <description>&lt;p&gt;Browser caching is great, except when it's not.  What if you deploy a new version to production, but the fix you made to a JavaScript or CSS file isn't showing up?  How can we force the browser to download files at least once with each build?&lt;/p&gt;
&lt;p&gt;In previous posts, I showed &lt;a href="https://volaresoftware.com/en/technical-posts/adding-requirejs-to-an-aspnet-mvc-project"&gt;how to use RequireJS in an MVC app&lt;/a&gt;, and &lt;a href="https://volaresoftware.com/en/technical-posts/optimizing-javascript-and-css-files-using-requirejs-and-rjs-in-an-aspnet-mvc-app"&gt;how to optimize JavaScript and CSS using r.js&lt;/a&gt; in that project.  Now we'll tackle cache busting to fix this problem.&lt;/p&gt;
&lt;p&gt;The code for this project is available for &lt;a href="https://github.com/VolareSoftware/RequireJSWithMVC"&gt;view/download on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="concept"&gt;Concept&lt;/h3&gt;
&lt;p&gt;We're going to put a small query string on every optimized JavaScript and CSS file with a unique code tied to that deployment.  I'll use the build number of the main web assembly, since that's easy to get.  The pattern will be like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;/Scripts-Build/app/main-fileName.js?v=1234
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you don't like using the build number for whatever reason, you can use anything you like, as long as it it changes when you build or deploy the files, but doesn't change all the time.  So something like a build date makes sense, but not the current date/time, because that will always be different on each request.&lt;/p&gt;
&lt;p&gt;Finally, be aware this is not a perfect solution.  If someone is sitting behind a proxy server, they may not see the changes &lt;strong&gt;IF&lt;/strong&gt; the proxy server doesn't honor the query strings and refetch the files.  If that applies in your situation, you may need a path and some extra routing work to get past the proxy with something like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;/Scripts-Build/app/1234/main-fileName.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'll only be showing the build version style, and I've found that works in most situations.&lt;/p&gt;
&lt;h3 id="getting-the-build-version"&gt;Getting the build version&lt;/h3&gt;
&lt;p&gt;This is not the kind of code you write very often, but here's how I got the build number from the current assembly:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Globalization;
using System.Reflection;
using System.Web;
using System.Web.Caching;
using System.Web.Mvc;
&lt;p&gt;namespace RequireJSWithMVC.Extensions
{
public static class ApplicationVersionHelpers
{
private const string _assemblyRevisionNumberKey = &amp;quot;AssemblyRevisionNumber&amp;quot;;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    public static string AssemblyRevisionNumber(this HtmlHelper helper)
    {
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#if (DEBUG)
return string.Empty;
#else
if (HttpRuntime.Cache[_assemblyRevisionNumberKey] == null)
{
var assembly = Assembly.GetExecutingAssembly();
var assemblyRevisionNumber = assembly.GetName().Version.Revision.ToString(CultureInfo.InvariantCulture);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;            HttpRuntime.Cache.Insert(_assemblyRevisionNumberKey, assemblyRevisionNumber,
                new CacheDependency(assembly.Location));
        }

        return HttpRuntime.Cache[_assemblyRevisionNumberKey] as string;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#endif
}
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;We are just returning an empty string in Debug mode.  In Release mode, we are caching the build revision number so we don't have to re-lookup that value every time we request it.&lt;/p&gt;
&lt;p&gt;Now we need a way to access this version number from JavaScript.  Let's put this version number in a global variable inside &lt;code&gt;_Layout.cshtml&lt;/code&gt; in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section so it's available on every page.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script&amp;gt;var version = &amp;quot;@Html.AssemblyRevisionNumber()&amp;quot;;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We all know global variables are a sin, so paste it in and say your penance.&lt;/p&gt;
&lt;h3 id="using-the-build-version"&gt;Using the build version&lt;/h3&gt;
&lt;p&gt;In the &lt;a href="https://volaresoftware.com/en/technical-posts/optimizing-javascript-and-css-files-using-requirejs-and-rjs-in-an-aspnet-mvc-app"&gt;previous post&lt;/a&gt;, we had a &lt;code&gt;PathHelpers.cs&lt;/code&gt; file that toggled between the &lt;code&gt;/Scripts&lt;/code&gt; and the &lt;code&gt;/Scripts-Build&lt;/code&gt; and between the &lt;code&gt;/Styles&lt;/code&gt; and the &lt;code&gt;/Styles-Build&lt;/code&gt; folders.  We need to update that to use our version number based on Debug/Release build mode:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web;
using System.Web.Mvc;
&lt;p&gt;namespace RequireJSWithMVC.Extensions
{
public static class PathHelpers
{
public static string ScriptsPath(this HtmlHelper helper, string pathWithoutScripts)
{
var fullPath = &amp;quot;&amp;quot;;
#if (DEBUG)
var scriptsPath = &amp;quot;&lt;sub&gt;/Scripts/&amp;quot;;
fullPath = VirtualPathUtility.ToAbsolute(scriptsPath + pathWithoutScripts);
#else
var scriptsPath = &amp;quot;&lt;/sub&gt;/Scripts-Build/&amp;quot;;
fullPath = VirtualPathUtility.ToAbsolute(scriptsPath + pathWithoutScripts + &amp;quot;?v=&amp;quot; + helper.AssemblyRevisionNumber());
#endif
return fullPath;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    public static string StylesPath(this HtmlHelper helper, string pathWithoutStyles)
    {
        var fullPath = &amp;amp;quot;&amp;amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#if (DEBUG)
var stylesPath = &amp;quot;&lt;sub&gt;/Styles/&amp;quot;;
fullPath = VirtualPathUtility.ToAbsolute(stylesPath + pathWithoutStyles);
#else
var stylesPath = &amp;quot;&lt;/sub&gt;/Styles-Build/&amp;quot;;
fullPath = VirtualPathUtility.ToAbsolute(stylesPath + pathWithoutStyles + &amp;quot;?v=&amp;quot; + helper.AssemblyRevisionNumber());
#endif
return fullPath;
}
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This covers the &lt;code&gt;_Layout.cshtml&lt;/code&gt; scripts, but  we also need to update &lt;code&gt;RequireJsHelpers.cs&lt;/code&gt;, our helper that is used for page-level scripts and pulls in &lt;code&gt;main.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
&lt;p&gt;namespace RequireJSWithMVC.Extensions
{
public static class RequireJsHelpers
{
public static MvcHtmlString InitPageMainModule(this HtmlHelper helper, string pageModule)
{
var require = new StringBuilder();&lt;/p&gt;
&lt;p&gt;#if (DEBUG)
var scriptsPath = &amp;quot;&lt;sub&gt;/Scripts/&amp;quot;;
#else
var scriptsPath = &amp;quot;&lt;/sub&gt;/Scripts-Build/&amp;quot;;
#endif&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        var absolutePath = VirtualPathUtility.ToAbsolute(scriptsPath);

        require.AppendLine(&amp;amp;quot;&amp;amp;lt;script&amp;amp;gt;&amp;amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;#if (DEBUG)
require.AppendFormat(&amp;quot;    require([&amp;amp;quot;{0}main.js&amp;amp;quot;],&amp;quot; + Environment.NewLine, absolutePath);
#else
require.AppendFormat(&amp;quot;    require([&amp;amp;quot;{0}main.js?v={1}&amp;amp;quot;],&amp;quot; + Environment.NewLine, absolutePath, helper.AssemblyRevisionNumber());
#endif
require.AppendLine(&amp;quot;        function() {&amp;quot;);
require.AppendFormat(&amp;quot;            require([&amp;amp;quot;{0}&amp;amp;quot;, &amp;amp;quot;domReady!&amp;amp;quot;]);&amp;quot; + Environment.NewLine, pageModule);
require.AppendLine(&amp;quot;        }&amp;quot;);
require.AppendLine(&amp;quot;    );&amp;quot;);
require.AppendLine(&amp;quot;&amp;lt;/script&amp;gt;&amp;quot;);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        return new MvcHtmlString(require.ToString());
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Both of these now put &lt;code&gt;?v=1234&lt;/code&gt; in the JavaScript or CSS path.&lt;/p&gt;
&lt;p&gt;We still need to do some work so our &lt;code&gt;/app&lt;/code&gt; and &lt;code&gt;/lib&lt;/code&gt; scripts get the same treatment.  We'll do that in main.js by adding this line:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;urlArgs: version === &amp;quot;&amp;quot; ? &amp;quot;&amp;quot; : &amp;quot;v=&amp;quot; + version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember our awful global variable &amp;quot;version&amp;quot; in &lt;code&gt;_Layout.cshtml&lt;/code&gt;?  This is where it's being used.  In my &lt;code&gt;main.js&lt;/code&gt; file, I have this right under the &lt;code&gt;baseUrl&lt;/code&gt; setting:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;require.config({
    baseUrl: &amp;quot;/Scripts/app&amp;quot;,
    urlArgs: version === &amp;quot;&amp;quot; ? &amp;quot;&amp;quot; : &amp;quot;v=&amp;quot; + version
    paths: {
        jquery: &amp;quot;../lib/jquery-2.1.1&amp;quot;,
        jqueryValidate: &amp;quot;../lib/jquery.validate&amp;quot;,
        jqueryValidateUnobtrusive: &amp;quot;../lib/jquery.validate.unobtrusive&amp;quot;,
        bootstrap: &amp;quot;../lib/bootstrap&amp;quot;,
        moment: &amp;quot;../lib/moment&amp;quot;,
        domReady: &amp;quot;../lib/domReady&amp;quot;,
    },
    shim: {
        jqueryValidate: [&amp;quot;jquery&amp;quot;],
        jqueryValidateUnobtrusive: [&amp;quot;jquery&amp;quot;, &amp;quot;jqueryValidate&amp;quot;]
    }
});
&lt;p&gt;require([&amp;quot;kickoff&amp;quot;], function(kickoff) {
kickoff.init();
}
);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now you should be able to run the web app in Release mode and get this, with &lt;code&gt;?v=1234&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/cache_bust_with_querystring_js.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/cache_bust_with_querystring_js.png" /&gt;
&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/cache_bust_with_querystring_css.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/cache_bust_with_querystring_css.png" /&gt;&lt;/p&gt;
&lt;p&gt;Or run in Debug mode and get this, without the bundling, minification, and the extra query string stuff:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/cache_bust_without_querystring_js.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/cache_bust_without_querystring_js.png" /&gt;
&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/cache_bust_without_querystring_css.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/cache_bust_without_querystring_css.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you get this far and your build version in the query strings is 0, you need to update your &lt;code&gt;AssemblyInfo.cs&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[assembly: AssemblyVersion(&amp;quot;1.0.*&amp;quot;)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;*&lt;/code&gt; is the auto increment of the build revision number.&lt;/p&gt;
</description>
      <pubDate>Sat, 31 May 2014 00:39:24 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/optimizing-bundle-size-with-telerik-asp-net-core-controls-bootstrap-and-webpack</guid>
      <link>https://volaresoftware.com/nl/technical-posts/optimizing-bundle-size-with-telerik-asp-net-core-controls-bootstrap-and-webpack</link>
      <title>Optimizing bundle size with Telerik ASP.NET Core controls, Bootstrap, and Webpack</title>
      <description>&lt;p&gt;I am working on a mobile web application project using Telerik ASP.NET Core controls. These are the C# equivalent of the Kendo UI JavaScript controls. In fact, the Telerik ASP.NET Core controls are really Razor and tag helper wrappers that emit JavaScript to the browser to save you from the trouble of writing the JavaScript yourself.&lt;/p&gt;
&lt;p&gt;Because this is a mobile web app that will be used in the field, we want fast page download speeds. Having worked with Kendo UI before, I knew I could import only the components I needed, rather than pull in code for sliders and other components not used in this app.&lt;/p&gt;
&lt;p&gt;We are also using webpack and import only the JavaScript for the Telerik components used in each module.&lt;/p&gt;
&lt;h2 id="styles"&gt;Styles&lt;/h2&gt;
&lt;p&gt;In this project, we have a &lt;code&gt;variables.scss&lt;/code&gt; file where we keep the common Sass variables, a &lt;code&gt;site.scss&lt;/code&gt; files with the site-specific styles and overrides, and a &lt;code&gt;common.scss&lt;/code&gt; file that brings these two project Sass files together with the vendor files - in this case, Bootstrap and Kendo UI styles.&lt;/p&gt;
&lt;p&gt;Notice we are pulling in all Bootstrap styles, but we are not importing every Kendo UI styles or a combined file with all the Kendo UI styles for all the components. We are using only a handful of Kendo UI components in this app, so we don't want the extra weight of all those styles that will never be used in the app.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-scss"&gt;// All variables
@import &amp;quot;variables&amp;quot;;
&lt;p&gt;// Bootstrap
@import &amp;quot;node_modules/bootstrap/scss/bootstrap&amp;quot;;&lt;/p&gt;
&lt;p&gt;// Kendo UI
@import &amp;quot;node_modules/@progress/kendo-theme-bootstrap/scss/autocomplete&amp;quot;;
@import &amp;quot;node_modules/@progress/kendo-theme-bootstrap/scss/grid&amp;quot;;
@import &amp;quot;node_modules/@progress/kendo-theme-bootstrap/scss/combobox&amp;quot;;
@import &amp;quot;node_modules/@progress/kendo-theme-bootstrap/scss/datetime&amp;quot;;&lt;/p&gt;
&lt;p&gt;// Site
@import &amp;quot;site&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="scripts"&gt;Scripts&lt;/h2&gt;
&lt;p&gt;The webpack entry points for this web app are pages. It's a multi-page, not a single-page application. Here's what the &lt;code&gt;home.js&lt;/code&gt; page script looks like. It imports the components it needs, which in turn import whatever they need. For this app, the home page is static and shows a splash, and that's about it.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import &amp;quot;common.scss&amp;quot;;
import $ from &amp;quot;jquery&amp;quot;;
import &amp;quot;components/top-menu&amp;quot;;
import &amp;quot;components/header&amp;quot;;
import &amp;quot;components/footer&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's the script for &lt;code&gt;search.js&lt;/code&gt; a page that uses the Kendo UI autocomplete search and a gid to show search results. It also uses the Bootstrap alert module to show the user if there are no records found in the search.&lt;/p&gt;
&lt;p&gt;Finally, I had to import &lt;code&gt;@progress/kendo-ui/js/kendo.aspnetmvc&lt;/code&gt; in the page's JavaScript module. This is the secret sauce to get client-side behavior from server-side Telerik ASP.NET Core controls we used in Razor views (below).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import &amp;quot;common.scss&amp;quot;;
import $ from &amp;quot;jquery&amp;quot;;
import &amp;quot;components/top-menu&amp;quot;;
import &amp;quot;components/header&amp;quot;;
import &amp;quot;components/footer&amp;quot;;
import &amp;quot;bootstrap/js/dist/alert&amp;quot;;
import &amp;quot;@progress/kendo-ui/js/kendo.autocomplete&amp;quot;;
import &amp;quot;@progress/kendo-ui/js/kendo.grid&amp;quot;;
import &amp;quot;@progress/kendo-ui/js/kendo.aspnetmvc&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="razor"&gt;Razor&lt;/h2&gt;
&lt;p&gt;The Razor views were like normal ASP.NET Razor views or pages, but with client-side behavior coming from the page's &lt;code&gt;import &amp;quot;@progress/kendo-ui/js/kendo.aspnetmvc&amp;quot;;&lt;/code&gt;. This means you can sort or filter the results in a grid without a server call, but you don't have to write all the JavaScript client code to handle that.&lt;/p&gt;
&lt;p&gt;We tried the Telerik ASP.NET Core control tag-helpers, and I kind of prefer the syntax, but we quickly found there were not enough examples on the Telerik site or out in the wild to figure out the API. Guessing got pretty old pretty fast, so we went to the more traditional HTML helper syntac in the Razor code.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;&amp;lt;form id=&amp;quot;searchForm&amp;quot; asp-controller=&amp;quot;Search&amp;quot; asp-action=&amp;quot;Index&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;input-group&amp;quot;&amp;gt;
        @(
        Html.Kendo().AutoComplete()
            .Name(&amp;quot;searchText&amp;quot;)
            .DataTextField(&amp;quot;HitString&amp;quot;)
            .HtmlAttributes(new {@class=&amp;quot;form-control&amp;quot;})
            .DataSource(source =&amp;gt;
            {
                source.Read(read =&amp;gt;
                {
                    read.Action(&amp;quot;GetAutoCompleteAccounts&amp;quot;, &amp;quot;Search&amp;quot;).Data(&amp;quot;() =&amp;gt; { return { text: $('#searchText').val() }; }&amp;quot;);
                }).ServerFiltering(true);
            })
            .Placeholder(&amp;quot;Address, Owner Name, Legal Description, Account Number, or Parcel Number&amp;quot;)
            .Value(Model)
            .Filter(FilterType.Contains)
            .MinLength(2)
        )
        &amp;lt;div class=&amp;quot;input-group-append&amp;quot;&amp;gt;
            &amp;lt;button type=&amp;quot;submit&amp;quot; class=&amp;quot;btn btn-primary text-light&amp;quot;&amp;gt;
                &amp;lt;span class=&amp;quot;fas fa-search&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; Search
            &amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="optimizing"&gt;Optimizing&lt;/h2&gt;
&lt;p&gt;When webpack starts build the entry points, in this case, &lt;code&gt;home.js&lt;/code&gt; and &lt;code&gt;search.js&lt;/code&gt;, it grabs only the styles in &lt;code&gt;common.scss&lt;/code&gt; and only the modules in the pages and the components they use, so we get a smaller bundle than if we put style and script links in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of the &lt;code&gt;_Layout.cshtml&lt;/code&gt; page.&lt;/p&gt;
</description>
      <pubDate>Mon, 21 Dec 2020 07:45:51 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/getting-the-sql-and-parameters-out-of-dapper-for-display-in-glimpse</guid>
      <link>https://volaresoftware.com/nl/technical-posts/getting-the-sql-and-parameters-out-of-dapper-for-display-in-glimpse</link>
      <title>Getting the SQL and Parameters out of Dapper for display in Glimpse</title>
      <description>&lt;p&gt;&lt;a href="http://getglimpse.com/"&gt;Glimpse&lt;/a&gt; is a really nice tracing and diagnostic tool for what's happening on the server in an ASP.NET app.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/9/image_58.png" alt="https://cdn.volaresoftware.com/images/posts/2013/9/image_58.png" /&gt;&lt;/p&gt;
&lt;p&gt;It has a tab for showing the SQL and the query parameters being passed to SQL Server, but my tab looked like this when using &lt;a href="https://www.nuget.org/packages/Dapper"&gt;Dapper dot net&lt;/a&gt;, a light-weight ORM that takes your SQL result and maps it to a C# object:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/9/image_59.png" alt="https://cdn.volaresoftware.com/images/posts/2013/9/image_59.png" /&gt;&lt;/p&gt;
&lt;p&gt;I knew Glimpse worked with ADO.NET, I had installed that &lt;a href="http://www.nuget.org/packages/Glimpse.Ado/"&gt;plugin&lt;/a&gt;, and Dapper was using ADO.NET somewhere inside its framework, but my SQL tab was disabled.  I thought maybe I needed to install a Glimpse Dapper plugin, but there was none on &lt;a href="http://getglimpse.com/Packages"&gt;the official Glimpse plugins page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I found &lt;a href="http://www.codelyfe.com/Blog/Entry/View/3"&gt;this unofficial Glimpse Dapper plugin&lt;/a&gt;, but it still seemed like it was trying too hard.  This should be easier.&lt;/p&gt;
&lt;p&gt;I was getting my Dapper SQL connection through a factory like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public static class ConnectionFactory
{
    public static IDbConnection CreateConnection(string connectionString)
    {
        var cnn = new SqlConnection(connectionString);
        cnn.Open();
&lt;pre&gt;&lt;code&gt;    return cnn;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I finally found the &lt;a href="http://getglimpse.com/Help/ADO-Integration"&gt;Glimpse ADO integration help&lt;/a&gt;, and it said, &amp;quot;If you're not using an ADO connection that uses the &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.common.dbproviderfactories.aspx"&gt;DbProviderFactories&lt;/a&gt; class, Glimpse won't collect any data for the SQL tab (out of the box).&amp;quot;&lt;/p&gt;
&lt;p&gt;Oh.  Ok.  So I changed my code to this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public static class ConnectionFactory
{
    public static IDbConnection CreateConnection(string connectionString)
    {
        var factory = DbProviderFactories.GetFactory(&amp;quot;System.Data.SqlClient&amp;quot;);
        var cnn = factory.CreateConnection();
        cnn.ConnectionString = connectionString;
        cnn.Open();
&lt;pre&gt;&lt;code&gt;    return cnn;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;and now the SQL and parameters are showing on the Glimpse SQL tab:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/9/image_61.png" alt="https://cdn.volaresoftware.com/images/posts/2013/9/image_61.png" /&gt;&lt;/p&gt;
&lt;p&gt;Yay!&lt;/p&gt;
</description>
      <pubDate>Mon, 02 Sep 2013 22:49:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/evolution-of-a-view-in-aspnet-mvc</guid>
      <link>https://volaresoftware.com/nl/technical-posts/evolution-of-a-view-in-aspnet-mvc</link>
      <title>Evolution of a View in ASP.NET MVC</title>
      <description>&lt;p&gt;Many developers prefer working with ASP.NET MVC over Web Forms because they are more connected with the HTML, have better control over the rendered output, and can easily build their own HTML helpers to get consistent output.&lt;/p&gt;
&lt;p&gt;But making the views can be a hassle when your building a CRUD app or something that has a lot of very similar views.  Let's look at some ways around that you can use today and in the future.&lt;/p&gt;
&lt;h2 id="past"&gt;Past&lt;/h2&gt;
&lt;p&gt;When MVC first came out, most people were coding their inputs in views like this.  Just straight HTML with some helpers:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;&amp;lt;% using (Html.BeginForm()) { %&amp;gt;
  &amp;lt;fieldset&amp;gt;	
    &amp;lt;label for=&amp;quot;Name&amp;quot;&amp;gt;Name&amp;lt;/label&amp;gt; &amp;lt;%= Html.TextBox(&amp;quot;Name&amp;quot;) %&amp;gt;	
    &amp;lt;label for=&amp;quot;Email&amp;quot;&amp;gt;Email address&amp;lt;/label&amp;gt; &amp;lt;%= Html.TextBox(&amp;quot;Email&amp;quot;) %&amp;gt;	
    &amp;lt;label for=&amp;quot;Phone&amp;quot;&amp;gt;Phone&amp;lt;/label&amp;gt; &amp;lt;%= Html.TextBox(&amp;quot;Phone&amp;quot;) %&amp;gt;	
    &amp;lt;%= Html.SubmitButton() %&amp;gt;
  &amp;lt;/fieldset&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Simple, but a little too much reliance on strings.  This made the code error prone, so developers made their own HTML Helpers to crank out consistent views with fewer strings by using lambda expressions:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;&amp;lt;% using (Html.BeginForm()) { %&amp;gt;
  &amp;lt;fieldset&amp;gt;	
    &amp;lt;label for=&amp;quot;Name&amp;quot;&amp;gt;Name&amp;lt;/label&amp;gt; &amp;lt;%= Html.TextBoxFor(c =&amp;gt; c.Name) %&amp;gt;	
    &amp;lt;label for=&amp;quot;Email&amp;quot;&amp;gt;Email address&amp;lt;/label&amp;gt; &amp;lt;%= Html.TextBoxFor(c =&amp;gt; c.Email) %&amp;gt; 	
    &amp;lt;label for=&amp;quot;Phone&amp;quot;&amp;gt;Phone&amp;lt;/label&amp;gt; &amp;lt;%= Html.TextBoxFor(c =&amp;gt; c.Phone) %&amp;gt; 
    &amp;lt;%= Html.SubmitButton() %&amp;gt;
  &amp;lt;/fieldset&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's better.  We get IntelliSense for the model's fields and we get the leave some of the strings behind.&lt;/p&gt;
&lt;h2 id="present"&gt;Present&lt;/h2&gt;
&lt;p&gt;The next step was to get rid of some of those label statements and get those rolled into the output automatically.  They did this in &lt;a href="http://code.google.com/p/codecampserver/"&gt;Code Camp Server&lt;/a&gt; and you can see the step-by-step progression in &lt;a href="http://www.lostechies.com/blogs/hex/archive/2009/06/09/opinionated-input-builders-for-asp-net-mvc-using-partials-part-i.aspx"&gt;Eric Hexter's blog&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;&amp;lt;% using (Html.BeginForm()) { %&amp;gt;
  &amp;lt;fieldset&amp;gt;	
    &amp;lt;%= Html.Input(c =&amp;gt; c.Name) %&amp;gt;	
    &amp;lt;%= Html.Input(c =&amp;gt; c.Email) %&amp;gt; 	
    &amp;lt;%= Html.Input(c =&amp;gt; c.Phone) %&amp;gt; 	
    &amp;lt;%= Html.SubmitButton() %&amp;gt;
  &amp;lt;/fieldset&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nice!  Now we're on the road to consistent output in all forms in our MVC app and we won't spend as much time typing up view code.  Eric even shows us &lt;a href="http://www.lostechies.com/blogs/hex/archive/2009/06/17/opinionated-input-builders-part-8-the-auto-form.aspx"&gt;he can name that view in one note&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;&amp;lt;%= Html.InputForm() %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="future"&gt;Future&lt;/h2&gt;
&lt;p&gt;If you've been following the latest on ASP.NET MVC, you've seen the announcement for MVC 2 Preview 1 &lt;a href="http://weblogs.asp.net/scottgu/archive/2009/07/31/asp-net-mvc-v2-preview-1-released.aspx"&gt;here&lt;/a&gt;, &lt;a href="http://www.hanselman.com/blog/HanselminutesOn9ASPNETMVC2Preview1Released.aspx"&gt;here&lt;/a&gt;, and &lt;a href="http://haacked.com/archive/2009/07/30/asp.net-mvc-released.aspx"&gt;here&lt;/a&gt;.  Microsoft is going the same direction as these open-source extensions and making it easier to get a consistent view rendered:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;&amp;lt;% using (Html.BeginForm()) { %&amp;gt;
  &amp;lt;fieldset&amp;gt;	
    &amp;lt;%= Html.LabelFor(c =&amp;gt; c.Name) %&amp;gt;	
    &amp;lt;%= Html.EditorFor(c =&amp;gt; c.Name) %&amp;gt;	
    &amp;lt;%= Html.LabelFor(c =&amp;gt; c.Email) %&amp;gt;	
    &amp;lt;%= Html.EditorFor(c =&amp;gt; c.Email) %&amp;gt; 	
    &amp;lt;%= Html.LabelFor(c =&amp;gt; c.Phone) %&amp;gt;	
    &amp;lt;%= Html.EditorFor(c =&amp;gt; c.Phone) %&amp;gt; 	
    &amp;lt;%= Html.SubmitButton() %&amp;gt;
  &amp;lt;/fieldset&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MVC 2 also has an almost one-liner form that you define with templates, one of the new features:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;&amp;lt;% using (Html.BeginForm()) { %&amp;gt;
  &amp;lt;fieldset&amp;gt;	
    &amp;lt;%= Html.EditorFor(c =&amp;gt; c) %&amp;gt;
    &amp;lt;%= Html.SubmitButton() %&amp;gt;
  &amp;lt;/fieldset&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we've seen views getting simpler and smaller and even one-line forms.  Can it get any smaller than a one-line form?  What if there was no view?  Can you have a view with &lt;strong&gt;zero&lt;/strong&gt; lines of code?&lt;/p&gt;
&lt;p&gt;Kind of.  &lt;a href="http://haacked.com/archive/2009/08/04/default-templated-views.aspx"&gt;Phil Haack&lt;/a&gt; took the MVC 2 Preview 1 code out for a spin to try what he calls &amp;quot;default templated views&amp;quot;.  The idea is that your controller gets a model and displays a virtual view by using templates from your web project's &amp;quot;~\Views\Shared&amp;quot; folder.  You can make as many templates as you need for different purposes.&lt;/p&gt;
&lt;p&gt;This is ideal for CRUD apps or places in your app where the view is the same except for the model data it renders.  You don't need a physical file for each view other than the template itself.  The controller just renders a view that is one of the shared views/templates.&lt;/p&gt;
&lt;p&gt;I like this approach because you can crank out code more quickly for the easy stuff, but if you have a view that needs something more complex, you still have the normal HTML inputs and helpers to fall back on.  I hope Microsoft gets this idea fully flushed out and it ends up in the final MVC 2 release.  It would make developers more productive on repetitive views and would have wider acceptance if it was in the MVC base-class libraries.&lt;/p&gt;
</description>
      <pubDate>Tue, 08 Dec 2009 05:00:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/combining-batch-edit-and-detail-template-edit-on-a-kendo-ui-grid</guid>
      <link>https://volaresoftware.com/nl/technical-posts/combining-batch-edit-and-detail-template-edit-on-a-kendo-ui-grid</link>
      <title>Combining batch edit and detail template edit on a Kendo UI grid</title>
      <description>&lt;p&gt;A client recently asked for something I didn't know a Kendo UI grid could do. They wanted &lt;strong&gt;both&lt;/strong&gt; batch edit and a detail/expand edit of the &lt;strong&gt;same record&lt;/strong&gt; in the grid.&lt;/p&gt;
&lt;p&gt;They liked the Excel-like editing experience of working in batch mode, where you make a bunch of edits and send all the changes at once. But they also wanted several  UI features in the expanded/detail view that don't make sense in a grid row (e.g., charts, hyperlinks, buttons to calculate things, etc.). The idea was that users could use whatever fit their needs or preference, then save all grid changes as usual in a batch.&lt;/p&gt;
&lt;p&gt;I got it mostly working with this code, which is using this HTML and JavaScript: &lt;a href="https://jsfiddle.net/joewilson0/jwcLhtg2/"&gt;https://jsfiddle.net/joewilson0/jwcLhtg2/&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div id=&amp;quot;myGrid&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; 
&lt;p&gt;&amp;lt;script type=&amp;quot;text/x-kendo-template&amp;quot; id=&amp;quot;myDetailTemplate&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;
&amp;lt;label for=&amp;quot;testNumber&amp;quot;&amp;gt;Test Number&amp;lt;/label&amp;gt;
&amp;lt;input name=&amp;quot;testNumber&amp;quot; class=&amp;quot;form-control w-25&amp;quot; data-bind=&amp;quot;value: testNumber&amp;quot; /&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;
&amp;lt;label for=&amp;quot;testString&amp;quot;&amp;gt;Test String&amp;lt;/label&amp;gt;
&amp;lt;input name=&amp;quot;testString&amp;quot; class=&amp;quot;form-control w-25&amp;quot; data-bind=&amp;quot;value: testString&amp;quot; /&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;
&amp;lt;label for=&amp;quot;testDate&amp;quot; class=&amp;quot;d-block&amp;quot;&amp;gt;Test Date&amp;lt;/label&amp;gt;
&amp;lt;input name=&amp;quot;testDate&amp;quot; class=&amp;quot;form-control&amp;quot; data-bind=&amp;quot;value: testDate&amp;quot; data-role=&amp;quot;datepicker&amp;quot; /&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;$(document).ready(() =&amp;gt; {
  const testData = [
    { testNumber: 123, testString: &amp;quot;apple&amp;quot;, testDate: new Date(2020, 10, 14) },
    { testNumber: 456, testString: &amp;quot;pear&amp;quot;, testDate: new Date(2020, 10, 15) },
    { testNumber: 789, testString: &amp;quot;plum&amp;quot;, testDate: new Date(2020, 10, 16) },
  ];

  $(&amp;quot;#myGrid&amp;quot;).kendoGrid({
    dataSource: {
      data: testData,
      schema: {
        model: {
          fields: {
            testNumber: { type: &amp;quot;number&amp;quot; },
            testString: { type: &amp;quot;string&amp;quot; },
            testDate: { type: &amp;quot;date&amp;quot; }
          }
        }
      }
    },
    columns: [
      { field: &amp;quot;testNumber&amp;quot;, title: &amp;quot;Test Number&amp;quot; },
      { field: &amp;quot;testString&amp;quot;, title: &amp;quot;Test String&amp;quot; },
      { field: &amp;quot;testDate&amp;quot;, title: &amp;quot;Test Date&amp;quot;, format: &amp;quot;{0:d}&amp;quot; }
    ],
    editable: true,
    detailTemplate: kendo.template($(&amp;quot;#myDetailTemplate&amp;quot;).html()),
    detailInit: event =&amp;gt; kendo.bind(event.detailRow, event.data)
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This line is the key to having the grid row and the expanded view share the same view model:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;detailInit: event =&amp;gt; kendo.bind(event.detailRow, event.data)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when you change a value in the grid row, it updates immediately in the expanded row. Great! But when you do the reverse, and update the expanded row value, the grid row updates, but the expanded row immediately collapses. Arg!&lt;/p&gt;
&lt;p&gt;The fix to prevent closing the expanded row was to ignore the &lt;code&gt;itemchange&lt;/code&gt; action in the &lt;code&gt;dataBinding&lt;/code&gt; event:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;function dataBinding(event) {
    // Prevent closing the expanded detail row when the itemchange action in the databinding event is fired so it doesn't close the expanded view
    if (event.action === &amp;quot;itemchange&amp;quot;) {
        event.preventDefault();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this workaround fixes one thing and breaks another. Now the row doesn't collapse every time you change a value in the expanded view, but it also doesn't update the grid row values when you collapse because you just short-circuited that event.&lt;/p&gt;
&lt;p&gt;To fix this new problem, I added a &amp;quot;Done&amp;quot; button to the template that collapses the expanded row and wired up a function to repaint the values in the grid row on collapse.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;button class=&amp;quot;btn btn-secondary btn-collapse&amp;quot;&amp;gt;Done&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the user changes 3 things in the expanded view and keeps the expanded view open, the grid row still shows the original, unchanged values. Once the user clicks the &amp;quot;Done&amp;quot; button or collapses the expanded view with the icon on the left, the grid row is repainted with the values from the shared view model.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;function repaintRow(row) {
    const grid = $(row).closest(&amp;quot;.k-grid&amp;quot;).data(&amp;quot;kendoGrid&amp;quot;);
    const dataItem = grid.dataItem(row);
    const rowChildren = $(row).children(&amp;quot;td[role='gridcell']&amp;quot;);
&lt;pre&gt;&lt;code&gt;for (let i = 0; i &amp;amp;lt; grid.columns.length; i++) {
    const column = grid.columns[i];
    const template = column.template;
    const cell = rowChildren.eq(i);

    if (column.field !== undefined) {
        if (template !== undefined) {
            // Handle templated columns
            const kendoTemplate = kendo.template(template);
            cell.html(kendoTemplate(dataItem));
        } else {
            const fieldValue = dataItem[column.field];
            const format = column.format;
            const values = column.values;

            if (fieldValue &amp;amp;amp;&amp;amp;amp; values) {
                // Handle drop downs
                for (let j = 0; j &amp;amp;lt; values.length; j++) {
                    const value = values[j];
                    if (value.value === fieldValue.toString()) {
                        cell.html(value.text);
                        break;
                    }
                }
            } else if (format !== undefined) {
                // Handle formatted columns (like dates and currency)
                cell.html(kendo.format(format, fieldValue));
            } else {
                // Handle unformatted, untemplated, non-drop down values
                cell.html(fieldValue);
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now we have to wire up the Kendo UI grid and button events:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;$(&amp;quot;#myGrid&amp;quot;).kendoGrid({
     ...other grid settings...
    detailInit: detailInit,
    detailCollapse: detailCollapse,
    dataBinding: dataBinding,
    ...other grid settings...
});
&lt;p&gt;function detailInit(event) {
const grid = $(event.masterRow).closest(&amp;quot;.k-grid&amp;quot;).data(&amp;quot;kendoGrid&amp;quot;);
const masterRow = event.masterRow;
const detailRow = event.detailRow;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Bind the expanded view (detailRow) to the values in the master row
kendo.bind(detailRow, event.data);    

// Handle the detail row &amp;amp;quot;Done&amp;amp;quot; button click
detailRow.find(&amp;amp;quot;.btn-collapse&amp;amp;quot;).click(() =&amp;amp;gt; grid.collapseRow(masterRow));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here's the final working version that keeps the Kendo UI grid row and the expanded view in sync: &lt;a href="https://jsfiddle.net/joewilson0/e3p70jac/2/"&gt;https://jsfiddle.net/joewilson0/e3p70jac/2/&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Sat, 13 Feb 2021 07:11:25 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/do-we-still-need-coding-standards</guid>
      <link>https://volaresoftware.com/nl/technical-posts/do-we-still-need-coding-standards</link>
      <title>Do we still need coding standards?</title>
      <description>&lt;h2 id="the-dark-ages"&gt;The dark ages&lt;/h2&gt;
&lt;p&gt;I used to be &lt;strong&gt;really&lt;/strong&gt; big on coding standards in the late 1990's.  It was so easy to slip into spaghetti code in classic ASP and VB6, and at the time, the best antidote was rigid standards and uncompromising code reviews.&lt;/p&gt;
&lt;p&gt;I was a hard ass about our coding standards.  Then, as now, the rationale was that coding standards would make the code easier to read and maintain in the inevitable and long maintenance phase.&lt;/p&gt;
&lt;p&gt;The development process we used at the time was to stand around the white board and talk about the development tasks, then the developers would go off and separately code it up.  That was the other reason the coding standards mattered - we didn't want two code files to look totally different if written by different developers.&lt;/p&gt;
&lt;p&gt;My teams used the naming conventions Microsoft came up with for Access/VBA/VB, including Hungarian notation prefixes, but a lot of the standards were about code comments, error handling code, whitespace and indenting, etc.&lt;/p&gt;
&lt;h2 id="net-comes-on-the-scene"&gt;.NET comes on the scene&lt;/h2&gt;
&lt;p&gt;Fast forward maybe 5 or so years to the introduction of .NET and C#, and coding changed.  ASP.NET HTML didn't require &amp;lt;% %&amp;gt; tags anymore.  We could put the C# in code behind files and other project files.  We didn't need On Error anymore, we had Try-Catch.  XML comments seemed like a cool feature to show Intellisense drop downs for code &lt;strong&gt;you&lt;/strong&gt; wrote in addition to framework Intellisense.&lt;/p&gt;
&lt;p&gt;So we updated our coding standards to reflect the language and IDE changes, but they became more like guidelines instead of hard and fast rules.  By convention, we would avoid the spaghetti code just by keeping the right code in the right place.  Hungarian notation went away (slowly but surely).  The coding standards document was mostly reference code snippets and justifications for the conventions we used.  Code reviews became less common because it wasn't as big of an issue.&lt;/p&gt;
&lt;h2 id="today"&gt;Today&lt;/h2&gt;
&lt;p&gt;A lot has changed since .NET first came out, and I code differently now.  I'm trying to make my code a lot more terse these days.  I'm a big fan of having clean, succinct, expressive code.  The fewer non-essential things on the screen to wade through, the better.  It's more readable and easier to refactor.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I could put Try-Catch blocks everywhere, but isn't it simpler to &lt;a href="https://volaresoftware.com/en/technical-posts/handling-exceptions-in-aspnet-mvc"&gt;catch unhandled exceptions in one place&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I could add XML comments, but why?  It's either code in my same web project or a project that is owned by my solution.  I don't usually work on common library code where an assembly will be used across projects and Intellisense might be needed.&lt;/li&gt;
&lt;li&gt;I don't put the variable type on the left side of the equal sign anymore and use &amp;quot;var&amp;quot; instead.&lt;/li&gt;
&lt;li&gt;I've walked away from code regions and just order the items in the class file by convention.  &lt;a href="http://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt; likes to put new fields under the last field declaration in the class, so region wrapping all the fields in a class with &amp;quot;#region Fields&amp;quot; just wastes time when refactoring to pull it back up into the region.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not only has the way I code changed, but the tools have changed. ReSharper code cleanup templates and &lt;a href="http://stylecopforresharper.codeplex.com/"&gt;StyleCop&lt;/a&gt; warnings can be used to keep your team writing code in a style that you've all agreed on.  Just run the tool and have it clean up the code for you or flag code that doesn't meet the style guidelines.&lt;/p&gt;
&lt;p&gt;Having tests around the code lets me refactor and use auto-code-cleanup tools freely.  I understand the project a little more fully every day, so I can rename my class, method, and variable names to be more descriptive and accurate without worrying about breaking code.&lt;/p&gt;
&lt;p&gt;I'm also doing more pair programming these days, and this is a good way to enforce and socialize team coding styles.  It also means we don't have to refer to a coding standards document as often.  Since we're more story-focused, we're thinking more about the feature and less about coding style.  Taking ceremony code off the screen helps us keep that focus.&lt;/p&gt;
&lt;h2 id="if-i-had-to-do-it-over"&gt;If I had to do it over&lt;/h2&gt;
&lt;p&gt;If I was going to write a coding standards document today, it would be more like a style guide to reflect my current less-is-more thinking, and I'd probably give my peers a ReSharper template to auto-clean their code as they go instead of a document to refer to.  &lt;a href="http://stylecopforresharper.codeplex.com/wikipage?title=Overview"&gt;StyleCop for ReSharper&lt;/a&gt; looks promising as a gentle background reminder of team coding styles.&lt;/p&gt;
&lt;p&gt;What about your team?  Do you have a coding standards document people refer to?  Do you use tools to enforce standards/styles? Does your &lt;a href="https://www.g2i.co/blog/telling-a-story-with-your-code"&gt;code tell a story&lt;/a&gt; other developers can read?&lt;/p&gt;
</description>
      <pubDate>Thu, 08 Jul 2010 00:40:47 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/making-spiffy-buttons-with-css-and-mvc-razor-helpers</guid>
      <link>https://volaresoftware.com/nl/technical-posts/making-spiffy-buttons-with-css-and-mvc-razor-helpers</link>
      <title>Making spiffy buttons with CSS and MVC Razor helpers</title>
      <description>&lt;p&gt;For most web apps, gray buttons with black text is fine.  But if you take some time to jazz up your buttons a little, you are making your app a little nicer to use and giving your users small visual cues to let them know their options.&lt;/p&gt;
&lt;p&gt;Going from this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/9/image_13.png" alt="image_13.png" /&gt;&lt;/p&gt;
&lt;p&gt;to this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/9/image_16.png" alt="image_16.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/9/image_14.png" alt="image_14.png" /&gt;&lt;/p&gt;
&lt;p&gt;with hover colors of green and red, which, in the U.S. at least, usually mean &amp;quot;go&amp;quot; and &amp;quot;stop&amp;quot;, can be just enough of a nudge to help your users and make them just a little happier.  Here's how I built these.&lt;/p&gt;
&lt;h2 id="credit"&gt;Credit&lt;/h2&gt;
&lt;p&gt;The bulk of the concept and CSS work for this came from someone else, but I can't remember who anymore.  It's been over a year since I started using this technique.  It might be from an old version of &lt;a href="http://html5boilerplate.com/"&gt;HTML5 Boilerplate&lt;/a&gt;, &lt;a href="http://www.blueprintcss.org/"&gt;Blueprint CSS&lt;/a&gt;, &lt;a href="http://960.gs/"&gt;960 Grid System&lt;/a&gt;, or something Rob Conery did on &lt;a href="http://tekpub.com/"&gt;TekPub&lt;/a&gt;.  I wish I could give more specific attribution, but it was probably one of these.  My main contributions have been some CSS tweaks, the JavaScript, and the MVC Razor helpers.&lt;/p&gt;
&lt;h2 id="html-and-images"&gt;HTML and images&lt;/h2&gt;
&lt;p&gt;This is what we're going for as the emitted HTML.  We want these &amp;quot;buttons&amp;quot; to really be hyperlinks, not HTML buttons, so we don't have as much browser style sheet nonsense getting in the way.&lt;/p&gt;
&lt;p&gt;This does add some complexity for submitting, which has to be done with JavaScript now, but the same script (see below) can be used throughout the app.&lt;/p&gt;
&lt;p&gt;The positive CSS class gives the green hover effect, and the negative one gives the red effect.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;buttons&amp;quot;&amp;gt;
    &amp;lt;a href=&amp;quot;#&amp;quot; class=&amp;quot;button positive&amp;quot;&amp;gt;
        &amp;lt;img width=&amp;quot;16&amp;quot; height=&amp;quot;16&amp;quot; src=&amp;quot;/Content/Images/Icons/tick.png&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;
        Save
    &amp;lt;/a&amp;gt;
    &amp;lt;a href=&amp;quot;https://volaresoftware.com/en/posts/archive&amp;quot; class=&amp;quot;button negative&amp;quot;&amp;gt;
        &amp;lt;img width=&amp;quot;16&amp;quot; height=&amp;quot;16&amp;quot; src=&amp;quot;/Content/Images/Icons/cross.png&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;
        Cancel
    &amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The icons I used are from the &lt;a href="http://www.famfamfam.com/lab/icons/silk/"&gt;Silk Icons&lt;/a&gt; collection.  There are lots of great icon libraries out there, so use your favorite.  Anything 16x16 should work, but you can go bigger or smaller and adjust the CSS and &lt;code&gt;HtmlHelper&lt;/code&gt; tags.&lt;/p&gt;
&lt;h2 id="javascriptjquery"&gt;JavaScript/jQuery&lt;/h2&gt;
&lt;p&gt;An anchor tag with a href to &amp;quot;#&amp;quot; won't get your values submitted back to the server, so we'll use some JavaScript and a touch of jQuery for that.  You'll want to include this script on every page where you're using these buttons.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;$(function () {
    global.initButtons();
});
&lt;p&gt;var global = {
initButtons: function () {
$('a.button.positive').click(function (e) {
e.preventDefault();
var parentForm = $(this).closest('form');
if (!parentForm.valid()) {
global.flashMessage('Error validating these values', 'error');
}
else {
$(this).css(global.disableCss).unbind('click');
parentForm.submit();
}
});
},
disableCss: { opacity: 0.5, display: 'inline-block' }
};
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="css"&gt;CSS&lt;/h2&gt;
&lt;p&gt;The CSS for this is pretty simple.  The div.buttons puts the buttons on one line and give a little vertical space around them.  The .button and .button img styles do most of the work, with block styling, light and medium gray borders, a light gray background, some padding around the text and icon to fatten the button up a little, margins so there is space before the next adjacent button on the right, and a small shadow effect.&lt;/p&gt;
&lt;p&gt;The :hover effects are where the color is flipped to darker gray, green, or red, with corresponding border colors.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-css"&gt;/*--------------------------*/
/* Buttons
/*--------------------------*/
div.buttons
{
    display: inline-block;
    margin: 10px 0;
}
.button
{
    display: block;
    float: left;
    border-top: 1px solid #CCC;
    border-left: 1px solid #CCC;
    border-bottom: 1px solid #AAA;
    border-right: 1px solid #AAA;
    background-color: #E3E3E3;
    font-family: Verdana, Helvetica, sans-serif;
    font-size: 100%;
    line-height: 110%;
    text-decoration: none !important;
    color: #333 !important;
    margin: 0 15px 0 0;
    padding: 5px 10px 5px 7px;
    cursor: pointer;
    box-shadow: 1px 1px 2px #969696;
    -moz-box-shadow: 1px 1px 2px #969696; /* Firefox */
    -webkit-box-shadow: 1px 1px 2px #969696; /* Safari and Chrome */
}
.button img
{
    margin: 0 3px -3px 0 !important;
    padding: 0;
    border: none;
    width: 16px;
    height: 16px;
    float: none;
}
&lt;p&gt;/&lt;em&gt;--------------------------&lt;/em&gt;/
/* Button colors - Standard
/&lt;em&gt;--------------------------&lt;/em&gt;/
.button:hover
{
border: 1px solid #999;
background-color: #D6D6D6;
color: #333 !important;
}&lt;/p&gt;
&lt;p&gt;/&lt;em&gt;--------------------------&lt;/em&gt;/
/* Button colors - Positive
/&lt;em&gt;--------------------------&lt;/em&gt;/
.positive:hover
{
background-color: #E6EFC2;
border: 1px solid #C6D880;
color: #264409 !important;
}&lt;/p&gt;
&lt;p&gt;/&lt;em&gt;--------------------------&lt;/em&gt;/
/* Button colors - Negative
/&lt;em&gt;--------------------------&lt;/em&gt;/
.negative:hover
{
background-color: #FBE3E4;
border: 1px solid #FBC2C4;
color: #8A1F11 !important;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mvc-razor-htmlhelpers"&gt;MVC Razor HtmlHelpers&lt;/h2&gt;
&lt;p&gt;So now we know the HTML and CSS we want.  You could stop there and code your MVC views with that HTML.  But if you want your Razor views to be able to user simple helpers like this, keep reading.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-aspnet"&gt;&amp;lt;div class=&amp;quot;buttons&amp;quot;&amp;gt;
    @Html.LinkButtonForSave()
    @Html.LinkButtonForCancel()
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The helpers here have two public entry points, &lt;code&gt;LinkButtonForSave&lt;/code&gt; and &lt;code&gt;LinkButtonForCancel&lt;/code&gt;. The rest of the code is refactoring out some of the route parsing and tag building work.  It's probably overkill for just these two methods, but it makes sense when you keep adding helpers for other buttons, like add, edit, delete, confirm, print, etc.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web;
using System.Web.Mvc;
&lt;p&gt;namespace Extensions
{
public static class ButtonHelpers
{
public static MvcHtmlString LinkButtonForSave(this HtmlHelper helper)
{
var imageTag = ImageTag(&amp;quot;tick.png&amp;quot;);
var anchorHtml = FormSubmitAnchorTag(imageTag, &amp;quot;Save&amp;quot;);
return MvcHtmlString.Create(anchorHtml);
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    public static MvcHtmlString LinkButtonForCancel(this HtmlHelper helper)
    {
        var areaName = AreaName(helper);
        var controllerName = ControllerName(helper);
        var imageTag = ImageTag(&amp;amp;quot;cross.png&amp;amp;quot;);
        var anchorHtml = AnchorTagWithImageAndText(areaName, controllerName, &amp;amp;quot;Index&amp;amp;quot;, null, &amp;amp;quot;button negative&amp;amp;quot;, imageTag, &amp;amp;quot;Cancel&amp;amp;quot;);
        return MvcHtmlString.Create(anchorHtml);
    }

    private static TagBuilder ImageTag(string iconName)
    {
        var imageTag = new TagBuilder(&amp;amp;quot;img&amp;amp;quot;);
        imageTag.MergeAttribute(&amp;amp;quot;src&amp;amp;quot;, VirtualPathUtility.ToAbsolute(string.Format(&amp;amp;quot;~/Content/Images/Icons/{0}&amp;amp;quot;, iconName)));
        imageTag.MergeAttribute(&amp;amp;quot;width&amp;amp;quot;, &amp;amp;quot;16&amp;amp;quot;);
        imageTag.MergeAttribute(&amp;amp;quot;height&amp;amp;quot;, &amp;amp;quot;16&amp;amp;quot;);
        imageTag.MergeAttribute(&amp;amp;quot;alt&amp;amp;quot;, &amp;amp;quot;&amp;amp;quot;);
        return imageTag;
    }

    private static string AreaName(HtmlHelper helper)
    {
        var routeData = helper.ViewContext.RouteData;
        return routeData.DataTokens[&amp;amp;quot;area&amp;amp;quot;] == null ? string.Empty : routeData.DataTokens[&amp;amp;quot;area&amp;amp;quot;].ToString();
    }

    private static string ControllerName(HtmlHelper helper)
    {
        var routeData = helper.ViewContext.RouteData;
        return routeData.GetRequiredString(&amp;amp;quot;controller&amp;amp;quot;);
    }

    private static string FormSubmitAnchorTag(TagBuilder imageTag, string anchorText)
    {
        var anchorTag = new TagBuilder(&amp;amp;quot;a&amp;amp;quot;);
        anchorTag.MergeAttribute(&amp;amp;quot;href&amp;amp;quot;, &amp;amp;quot;#&amp;amp;quot;);
        anchorTag.AddCssClass(&amp;amp;quot;button positive&amp;amp;quot;);
        anchorTag.InnerHtml = imageTag.ToString(TagRenderMode.SelfClosing) + anchorText;
        return anchorTag.ToString();
    }

    private static string AnchorTagWithImageAndText(string areaName, string controllerName, string actionName, int? id, string cssClass, TagBuilder imageTag, string anchorText)
    {
        var anchorTag = new TagBuilder(&amp;amp;quot;a&amp;amp;quot;);
        if (areaName != string.Empty)
        {
            anchorTag.MergeAttribute(&amp;amp;quot;href&amp;amp;quot;, id == null
                                                 ? string.Format(&amp;amp;quot;/{0}/{1}/{2}&amp;amp;quot;, areaName, controllerName, actionName)
                                                 : string.Format(&amp;amp;quot;/{0}/{1}/{2}/{3}&amp;amp;quot;, areaName, controllerName, actionName, id));               
        }
        else
        {
            anchorTag.MergeAttribute(&amp;amp;quot;href&amp;amp;quot;, id == null
                                                 ? string.Format(&amp;amp;quot;/{0}/{1}&amp;amp;quot;, controllerName, actionName)
                                                 : string.Format(&amp;amp;quot;/{0}/{1}/{2}&amp;amp;quot;, controllerName, actionName, id));
        }
        anchorTag.AddCssClass(cssClass);
        anchorTag.InnerHtml = imageTag.ToString(TagRenderMode.SelfClosing) + anchorText;
        return anchorTag.ToString();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
</description>
      <pubDate>Sun, 16 Sep 2012 06:07:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/using-the-should-assembly-for-testing</guid>
      <link>https://volaresoftware.com/nl/technical-posts/using-the-should-assembly-for-testing</link>
      <title>Using the Should assembly for testing</title>
      <description>&lt;p&gt;&lt;a href="http://should.codeplex.com/"&gt;Should&lt;/a&gt; is a .NET assembly of extension methods for building easy to write and easy to read assert statements.  The advantage of using this assembly is the syntax is more clear and more like human language.  It's free, open source, and it doesn't matter if you're using NUnit or MSTest or any test runner (Test Driven .NET, ReSharper, etc.).  The project is in Beta 1.1, but I've used it on a couple of projects now with no problems.&lt;/p&gt;
&lt;p&gt;I've never really liked the MSTest way of doing an assert.  The whole expected and actual arguments always seemed flipped around to me.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Assert
Assert.AreEqual(&amp;quot;eggs&amp;quot;, breakfast.Foods.First());
Assert.AreEqual(&amp;quot;bacon&amp;quot;, breakfast.Foods.Last()); 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead, just reference the Should assembly and add the&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using Should;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;statement to the top of your test code and you can change it to:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Assert
breakfast.Foods.First().ShouldEqual(&amp;quot;eggs&amp;quot;);
breakfast.Foods.Last().ShouldEqual(&amp;quot;bacon&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think one of the tricks to writing good tests is to have code that is dead simple to read when you come back to it much later.  The Should assembly gives you that.&lt;/p&gt;
&lt;p&gt;Here are some other calls from the CodePlex home page for the project:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public void Should_String_assertions()
{
    var obj = new object();
    obj.ShouldBeInRange(1,2);
    obj.ShouldBeNull();
    obj.ShouldBeSameAs(new object());
    obj.ShouldBeType(typeof (object));
    obj.ShouldEqual(obj);
    obj.ShouldNotBeInRange(1,2);
    obj.ShouldNotBeNull();
    obj.ShouldNotBeSameAs(new object());
    obj.ShouldNotBeType(typeof(string));
    obj.ShouldNotEqual(&amp;quot;foo&amp;quot;);
&lt;pre&gt;&lt;code&gt;&amp;amp;quot;This String&amp;amp;quot;.ShouldContain(&amp;amp;quot;this&amp;amp;quot;);
&amp;amp;quot;This String&amp;amp;quot;.ShouldNotBeEmpty();
&amp;amp;quot;This String&amp;amp;quot;.ShouldNotContain(&amp;amp;quot;foobar&amp;amp;quot;);

false.ShouldBeFalse();
true.ShouldBeTrue();

var list = new List&amp;amp;lt;object&amp;amp;gt;();
list.ShouldBeEmpty();
list.ShouldNotContain(new object());

var item = new object();
list.Add(item);
list.ShouldNotBeEmpty();
list.ShouldContain(item);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You should check it out!&lt;/p&gt;
</description>
      <pubDate>Tue, 24 Aug 2010 00:40:45 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/tree-shaking-with-font-awesome-and-webpack</guid>
      <link>https://volaresoftware.com/nl/technical-posts/tree-shaking-with-font-awesome-and-webpack</link>
      <title>Tree shaking with Font Awesome and webpack</title>
      <description>&lt;p&gt;&lt;a href="https://fontawesome.com"&gt;Font Awesome 5&lt;/a&gt; has a new tree shaking feature that works with &lt;a href="https://webpack.js.org/guides/tree-shaking/"&gt;webpack's tree shaking&lt;/a&gt;.  This is really helpful so you don't have to download one giant JavaScript file with a bunch of SVG icon definitions in it like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script defer src=&amp;quot;https://use.fontawesome.com/releases/v5.0.6/js/all.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which gets you file sizes like below, where all.js is 657 KB (278 KB gzipped) and index.js is 88 bytes.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/web_console_font_awesome_all.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/web_console_font_awesome_all.png" /&gt;&lt;/p&gt;
&lt;p&gt;Instead, you can limit the file size to only the icons you use in your project through ES2015+ module imports and get file sizes like this, where all.js is gone and index.js is now 33.3 KB gzipped. We just saved 600+ KB (or about 250 KB gzipped)!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/web_console_font_awesome_index.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/web_console_font_awesome_index.png" /&gt;&lt;/p&gt;
&lt;p&gt;The Font Awesome team wrote &lt;a href="https://fontawesome.com/how-to-use/use-with-node-js#tree-shaking"&gt;some nice documentation on how to do this&lt;/a&gt;, but I didn't need to reference the shakable modules to get the smaller file size benefits. Here's how I got it working with Font Awesome 5 and webpack 3.&lt;/p&gt;
&lt;h3 id="what-worked"&gt;What worked&lt;/h3&gt;
&lt;p&gt;This is the HTML for the index.html test page.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt;
    &amp;lt;title&amp;gt;Tree shaking with FontAwesome and webpack&amp;lt;/title&amp;gt;
    &amp;lt;link href=&amp;quot;https://volaresoftware.com/blog/node_modules/bootstrap/dist/css/bootstrap.min.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; /&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div class=&amp;quot;text-center&amp;quot; style=&amp;quot;font-size: 24px; margin-top: 30px;&amp;quot;&amp;gt;
        &amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
            &amp;lt;div class=&amp;quot;col-xs-2&amp;quot;&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;I class=&amp;quot;far fa-calendar-alt&amp;quot;&amp;gt;&amp;lt;/I&amp;gt;
                &amp;lt;/div&amp;gt;
                Calendar
            &amp;lt;/div&amp;gt;
            &amp;lt;div class=&amp;quot;col-xs-2&amp;quot;&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;I class=&amp;quot;far fa-envelope&amp;quot;&amp;gt;&amp;lt;/I&amp;gt;
                &amp;lt;/div&amp;gt;
                Email
            &amp;lt;/div&amp;gt;
            &amp;lt;div class=&amp;quot;col-xs-2&amp;quot;&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;I class=&amp;quot;fas fa-arrow-up&amp;quot;&amp;gt;&amp;lt;/I&amp;gt;
                &amp;lt;/div&amp;gt;
                Arrow Up
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;script src=&amp;quot;/dist/lib.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;/dist/index.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this is index.js.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import fontawesome from &amp;quot;@fortawesome/fontawesome&amp;quot;;
import farCalendar from &amp;quot;@fortawesome/fontawesome-free-regular/faCalendarAlt&amp;quot;;
import farEnvelope from &amp;quot;@fortawesome/fontawesome-free-regular/faEnvelope&amp;quot;;
import fasArrowUp from &amp;quot;@fortawesome/fontawesome-free-solid/faArrowUp&amp;quot;;
&lt;p&gt;fontawesome.library.add(farCalendar, farEnvelope, fasArrowUp);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the markup, I'm pulling in lib.js, which webpack will figure out from the commons chunk (see below about what that is), and index.js, whose code is nothing but some icon imports.&lt;/p&gt;
&lt;p&gt;In Font Awesome 5, you can now import a single icon, multiple icons, a full set of icons (the solid, regular, light, or brand sets), or every icon they make (free or pro).  If you want the tree shaking and small file size benefit, you have to import the Font Awesome library and add your newly imported icons to the library before they can be used, like I've done above.&lt;/p&gt;
&lt;p&gt;Here is the webpack.config.js file.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const webpack = require(&amp;quot;webpack&amp;quot;);
const path = require(&amp;quot;path&amp;quot;);
const CleanWebpackPlugin = require(&amp;quot;clean-webpack-plugin&amp;quot;);
const UglifyJsPlugin = require(&amp;quot;uglifyjs-webpack-plugin&amp;quot;);
&lt;p dead_code:="" true=""&gt;module.exports = () =&amp;gt; {&lt;br /&gt;
return {
entry: {
index: &amp;quot;index.js&amp;quot;
},
output: {
filename: &amp;quot;[name].js&amp;quot;,
path: path.resolve(__dirname, &amp;quot;dist&amp;quot;),
publicPath: &amp;quot;/dist&amp;quot;
},
devtool: &amp;quot;source-map&amp;quot;,
plugins: [
new CleanWebpackPlugin([&amp;quot;dist&amp;quot;]),
new webpack.optimize.CommonsChunkPlugin({
name: &amp;quot;lib&amp;quot;
}),
new UglifyJsPlugin({
sourceMap: true,
uglifyOptions: })
],
resolve: {
extensions: [
&amp;quot;.js&amp;quot;
],
modules: [
path.resolve(__dirname, &amp;quot;scripts&amp;quot;),
&amp;quot;node_modules&amp;quot;
]
},
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: &amp;quot;babel-loader&amp;quot;,
options: {
presets: [&amp;quot;env&amp;quot;],
babelrc: false,
cacheDirectory: true,
plugins: [
&amp;quot;transform-runtime&amp;quot;]
}
}
}
]
}
};
};
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you're used to seeing webpack.config files, there isn't anything too novel going on. If you aren't, here's the gist: There is one application entry point, index.js. Files will be output to the /dist folder. Source maps are turned on. We clean the /dist folder before a build. We have a commons chunk called lib.js, which means webpack figures out code shared across modules that can be extracted into a common file. We are minifying with UglifyJS and setting its source map flags to true also. We have the UglifyJS dead code (tree shaking) flag set to true, but I get the same results with or without that setting turned on. The resolve section tells webpack where to look for files, and the module rule we have set is to use Babel to load *.js files unless the file comes from the node_modules folder (so use Babel's loader for our projects' scripts).&lt;/p&gt;
&lt;p&gt;I'm pretty happy with this, and for a project with a handful or even several handfuls of icons, it probably makes sense to import just the ones your project uses.  One option is to make a selectedIcons.js file, set up all your imports and Font Awesome library additions there, and import selectedIcons.js in your single entry or for pages with icons if you have a multiple entries project.&lt;/p&gt;
&lt;h3 id="what-didnt-work"&gt;What didn't work&lt;/h3&gt;
&lt;p&gt;The Font Awesome documentation describes some special modules you can set up through webpack.config aliases, and when you import from those files, you get tree shaking.&lt;/p&gt;
&lt;p&gt;I changed the webpack.config.js resolve section to this.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;resolve: {
    extensions: [
        &amp;quot;.js&amp;quot;
    ],
    modules: [
        path.resolve(__dirname, &amp;quot;scripts&amp;quot;),
       &amp;quot;node_modules&amp;quot;
    ],
    alias: {
        &amp;quot;@fortawesome/fontawesome-free-solid$&amp;quot;: &amp;quot;@fortawesome/fontawesome-free-solid/shakable.es.js&amp;quot;,
        &amp;quot;@fortawesome/fontawesome-free-regular$&amp;quot;: &amp;quot;@fortawesome/fontawesome-free-regular/shakable.es.js&amp;quot;
    }
},
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then I changed index.js to import with a different syntax.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import fontawesome from &amp;quot;@fortawesome/fontawesome&amp;quot;;
import { faCalendarAlt, faEnvelope } from &amp;quot;@fortawesome/fontawesome-free-regular&amp;quot;;
import faArrowUp from &amp;quot;@fortawesome/fontawesome-free-solid&amp;quot;;
&lt;p&gt;fontawesome.library.add(faCalendarAlt, faEnvelope, faArrowUp);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then I re-built the code.  The page still works, but the index.js file got waaaay bigger.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2019/12/web_console_font_awesome_final.png" alt="https://cdn.volaresoftware.com/images/posts/2019/12/web_console_font_awesome_final.png" /&gt;&lt;/p&gt;
&lt;p&gt;I don't know if I missed something in my webpack.config.js, or I've imported with the wrong syntax, or I've referenced the special shakable files incorrectly, but I couldn't get it working. If you see my mistake, please comment below and I'll update the post.&lt;/p&gt;
&lt;p&gt;Either way, it works to import and add individual icons, and you get smaller files. All the &lt;a href="https://github.com/VolareSoftware/TreeShakingWithFontAwesome"&gt;code for this post can be found on GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Mon, 29 Jan 2018 06:30:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/stop-making-hay</guid>
      <link>https://volaresoftware.com/nl/technical-posts/stop-making-hay</link>
      <title>Stop making hay</title>
      <description>&lt;h2 id="straw-men"&gt;Straw men&lt;/h2&gt;
&lt;p&gt;When &lt;a href="http://en.wikipedia.org/wiki/Test_driven_development"&gt;test-driven development (TDD)&lt;/a&gt; or other test-first methods are first introduced, many people object with different variations of the same argument &amp;quot;if you can't test everything, it's flawed&amp;quot;.  People seem to get mentally stuck when they can't automate all test cases.  Sometimes, the point gets really stretched, like, &amp;quot;What if the user enters a negative salary lower than &lt;code&gt;int.MinValue&lt;/code&gt;?  We don't have a test for &lt;strong&gt;that&lt;/strong&gt;, do we?&amp;quot; or &amp;quot;What if the database or web server goes down?  How do we do TDD for &lt;strong&gt;that&lt;/strong&gt;?&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/darrencauthon"&gt;Darren Cauthon&lt;/a&gt; made this observation on Twitter a few months ago:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2010/12/darrencauthonquote.png" alt="https://cdn.volaresoftware.com/images/posts/2010/12/darrencauthonquote.png" /&gt;&lt;/p&gt;
&lt;p&gt;All these arguments are &lt;a href="http://en.wikipedia.org/wiki/Straw_man"&gt;straw men&lt;/a&gt;, where an exaggeration or misrepresentation of the point is used to discount the entire thing.&lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting started&lt;/h2&gt;
&lt;p&gt;TDD won't make all your problems go away or  all your dreams come true.  It's something that takes a lot of practice to get better at it.  I consider myself pretty mediocre at it.  You will be slower at coding when you start out, but you will get faster, and I believe it is worth the investment in terms of the cleaner design it yields.  The tests are nice, too. :&amp;gt;&lt;/p&gt;
&lt;p&gt;The trick for me to getting started with TDD was to start small.  This has also been the only way I've been able to do TDD successfully - in very small steps.  Create one test for the happy path for the feature you are trying to implement. This usually has to be broken down into sub steps.  Write the least amount of code you can write to get the test to pass.  Once the test is passing, refactor the code to clean it up and add some polish.  Then run your test again to make sure it still passes.&lt;/p&gt;
&lt;h2 id="unhappy-paths"&gt;Unhappy paths&lt;/h2&gt;
&lt;p&gt;Occasionally test the unhappy paths, based on how likely they are and how important they are to the business.  If your product owner isn't worried about &lt;code&gt;int.MinValue&lt;/code&gt;, you shouldn't be.  Move on to the next feature you're building.&lt;/p&gt;
&lt;p&gt;You probably won't automate all your test cases, but that's OK.  Your code will be decoupled, easier to refactor, and easier to read.  Plus you will have automated tests for whatever percentage of tests cases you came up with.&lt;/p&gt;
&lt;p&gt;There are far too many benefits to dismiss test-first approaches based on what it &lt;strong&gt;can't&lt;/strong&gt; do well.  So let's stop with the straw man arguments against test-first and start reaping the benefits.&lt;/p&gt;
</description>
      <pubDate>Sat, 25 Dec 2010 01:40:33 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/why-bother-writing-unit-tests</guid>
      <link>https://volaresoftware.com/nl/technical-posts/why-bother-writing-unit-tests</link>
      <title>Why bother writing unit tests?</title>
      <description>&lt;p&gt;More developers are coming around to the idea of writing unit tests for their code.  But not everyone is sold.  Let's take a look at the arguments for just writing code and either manually testing or handing the app over to QA:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It takes too long to write unit tests.&lt;/li&gt;
&lt;li&gt;This is really simple code.  I could see maybe testing something complex, but this is just a CRUD app.&lt;/li&gt;
&lt;li&gt;Write my tests &lt;strong&gt;before&lt;/strong&gt; my code?  Are you kidding me?  I've always done it the other way and it's worked out just fine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's take these one by one and see if they are still valid.&lt;/p&gt;
&lt;h2 id="time-argument"&gt;Time Argument&lt;/h2&gt;
&lt;p&gt;It doesn't take long to run the test.  I think there is consensus there.  But writing units tests &lt;strong&gt;and&lt;/strong&gt; writing code is more lines of code than just writing the code.  More lines = more time, right?&lt;/p&gt;
&lt;p&gt;Sure, as long as manual testing is less than the automated testing &lt;strong&gt;over time&lt;/strong&gt;.  Not just the first time, but for the &lt;strong&gt;lifetime of that code&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If I'm using your old assembly from 2004 or web service from last month, I want some assurances it still works the way it was supposed to.  If you knew the secret way to manually test it, but have forgotten it, I don't fully trust your code.  I have to spend time going over that code and testing it out myself.&lt;/p&gt;
&lt;p&gt;Code with a lifespan longer than your memory and availability to manually regression test it benefits from having a suite of unit tests that can be run in milliseconds.&lt;/p&gt;
&lt;h2 id="simplicity-argument"&gt;Simplicity Argument&lt;/h2&gt;
&lt;p&gt;&amp;quot;If the code is really simple, there is no point in writing unit tests.&amp;quot;&lt;/p&gt;
&lt;p&gt;This is a good point.  Unit testing can help work through complex code, but what if the code is really easy?&lt;/p&gt;
&lt;p&gt;I agree that there isn't a need to bother testing setting and getting properties and methods that just call other methods.  And please don't spend time testing code that is part of the .NET framework or an assembly you bought.  That's a waste of time.&lt;/p&gt;
&lt;p&gt;But if you're using test-driven development, you start with the functionality, not the implementation.  So you write tests that cover the important/core stuff in your requirements.  You don't bother testing properties and call wrappers, which are just technical artifacts of the important stuff you are coding.  If it's the important stuff, shouldn't it be covered with unit tests?&lt;/p&gt;
&lt;h2 id="tdd-my-world-upside-down"&gt;TDD = My World Upside Down&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2009/7/mad_hatter_thumb.gif" alt="https://cdn.volaresoftware.com/images/posts/2009/7/mad_hatter_thumb.gif" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;quot;Writing test before writing code is crazy talk.&amp;quot; I also have had a great career without doing this, so what's the point?&lt;/p&gt;
&lt;p&gt;I agree it is crazy.  I also agree it's a 180 on the conventional wisdom.  And I completely agree that it's harder than just writing the code.&lt;/p&gt;
&lt;p&gt;But here's where I depart from the TDD crowd.  If you're new to unit testing, I just want you to write unit tests to cover the critical code for now.  It might lead you to TDD at some point, it might not.  But &lt;strong&gt;it's not an all or nothing thing&lt;/strong&gt;.  Let's just try to work in as many tests as we can and leave it there for now. How many tests do you need?  What code coverage levels are you shooting for?  That's up to you.  If you feel good showing the code to your peers and are happy to be held accountable for the quality of your code, you're probably done.&lt;/p&gt;
&lt;p&gt;I'll make the case for TDD another time.  Just baby steps for now.&lt;/p&gt;
</description>
      <pubDate>Thu, 08 Oct 2009 00:41:38 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/htmlencode-and-urlencode-arent-the-same-thing</guid>
      <link>https://volaresoftware.com/nl/technical-posts/htmlencode-and-urlencode-arent-the-same-thing</link>
      <title>HtmlEncode and UrlEncode aren't the same thing</title>
      <description>&lt;p&gt;The other day I was trying to pass an encoded version of &lt;code&gt;id=123&lt;/code&gt; to a customer's search API.  I tried&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var result = HttpUtility.HtmlEncode(&amp;quot;id=123&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but it returned &lt;code&gt;id=123&lt;/code&gt;.  I stared at the screen, scratched my head, and jumped on Google.&lt;/p&gt;
&lt;p&gt;A quick search reminded me that &lt;a href="http://msdn.microsoft.com/en-us/library/73z22y6h.aspx"&gt;HtmlEncode&lt;/a&gt; is for escaping HTML, but it leaves everything else alone.  So&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var result = HttpUtility.HtmlEncode(&amp;quot;&amp;lt;br/&amp;gt;&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;returns &lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt;.  All the less thans and greater thans get escaped, but the rest is pretty much the same.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/4fkewx0t.aspx"&gt;UrlEncode&lt;/a&gt; is for cases where you want to escape a URL, so&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var result = HttpUtility.UrlEncode(&amp;quot;id=123&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;returns &lt;code&gt;id%3d123&lt;/code&gt;, which is what I wanted in the first place.  By comparison, if you UrlEncode the &lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt; tag, like&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var result = HttpUtility.UrlEncode(&amp;quot;&amp;lt;br/&amp;gt;&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;you'll get back &lt;code&gt;%3cbr%2f%3e&lt;/code&gt;.  It's encoding the less than, the slash, and the greater than, but it's encoding them with URL-type escapes instead of HTML-style ones.&lt;/p&gt;
&lt;p&gt;I guess it's been a while since I paid attention to encoding.  Not all encoding methods are equal in the ASP.NET framework, so be careful which one you use.&lt;/p&gt;
</description>
      <pubDate>Sat, 29 Jan 2011 07:43:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/resizing-a-kendo-ui-drop-down-to-fit-its-data-without-wrapping</guid>
      <link>https://volaresoftware.com/nl/technical-posts/resizing-a-kendo-ui-drop-down-to-fit-its-data-without-wrapping</link>
      <title>Resizing a Kendo UI drop down to fit its data without wrapping</title>
      <description>&lt;p&gt;Telerik's Kendo UI Web makes a spiffy looking drop down with JavaScript and CSS.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/2/image_31.png" alt="image_31.png" /&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://demos.kendoui.com/web/dropdownlist/index.html"&gt;demos on the Telerik site&lt;/a&gt; show drop downs with default widths and not much text.&lt;/p&gt;
&lt;p&gt;That breaks down when the text in the drop down gets longer because it wraps.  I don't like this look.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/2/image_32.png" alt="image_32.png" /&gt;&lt;/p&gt;
&lt;p&gt;So I wrote a JavaScript function that resizes the drop down to fit the width of the data so you avoid the wrapping and get:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/2/image_33.png" alt="image_33.png" /&gt;&lt;/p&gt;
&lt;p&gt;Here's the JavaScript:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;var resizeDropDown = function (e) {
    var $dropDown = $(e.sender.element),
        dataWidth = $dropDown.data(&amp;quot;kendoDropDownList&amp;quot;).list.width(),
        listWidth = dataWidth + 20,
        containerWidth = listWidth + 6;
&lt;pre&gt;&lt;code&gt;// Set widths to the new values
$dropDown.data(&amp;amp;quot;kendoDropDownList&amp;amp;quot;).list.width(listWidth);
$dropDown.closest(&amp;amp;quot;.k-widget&amp;amp;quot;).width(containerWidth);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You have to call this on the drop down's dataBound event.  That way, if you're pulling remote data through something like Web API, you won't resize until you've gotten the data back and fired the dataBound event.&lt;/p&gt;
&lt;p&gt;Here's a JSFiddle to play around with it.  The fiddle shows two drop downs – one with the default sizing and wrapping, and the other with the resizeDropDown function called on the dataBound event.&lt;/p&gt;
&lt;iframe style="height: 300px; width: 100%" src="https://jsfiddle.net/joewilson0/GxSpN/embedded/" frameborder="0" allowfullscreen="allowfullscreen"&gt;&lt;/iframe&gt;
</description>
      <pubDate>Sat, 02 Feb 2013 13:19:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/trim-unused-css-selectors-with-purifycss-and-webpack</guid>
      <link>https://volaresoftware.com/nl/technical-posts/trim-unused-css-selectors-with-purifycss-and-webpack</link>
      <title>Trim unused CSS selectors with PurifyCSS and webpack</title>
      <description>&lt;p&gt;Most web sites use a CSS library like &lt;a href="https://getbootstrap.com/"&gt;Bootstrap&lt;/a&gt;. It's great for getting started quickly and works well as an all-purpose style sheet.&lt;/p&gt;
&lt;p&gt;But what about all the selectors in Bootstrap you aren't using in your app? What if you also add a Bootstrap theme and your own web app style overrides on top of that? All the used and unused styles go down to your users' browsers with every response.&lt;/p&gt;
&lt;p&gt;If you can trim that down to only the styles your web app actually &lt;em&gt;uses&lt;/em&gt;, you'll send down a much smaller style sheet, your site will run faster, and you'll save on bandwidth costs.&lt;/p&gt;
&lt;p&gt;Here's how I did just that with &lt;a href="https://github.com/webpack-contrib/purifycss-webpack"&gt;PurifyCSS&lt;/a&gt; and &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="install-webpack-and-purifycss"&gt;Install webpack and PurifyCSS&lt;/h3&gt;
&lt;p&gt;Once you've got Node and NPM up and running, install webpack 4.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;npm install webpack webpack-cli --save-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then install &lt;a href="https://github.com/purifycss/purifycss"&gt;PurifyCSS&lt;/a&gt; and the &lt;a href="https://github.com/webpack-contrib/mini-css-extract-plugin"&gt;MiniCssExtractPlugin&lt;/a&gt;, if you don't already have it set up.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;npm install purify-css purifycss-webpack glob-all mini-css-extract-plugin --save-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="set-up-purifycss-in-webpack.config.js"&gt;Set up PurifyCSS in webpack.config.js&lt;/h3&gt;
&lt;p&gt;In your &lt;code&gt;webpack.config.js&lt;/code&gt; file, add a reference to the MiniCssExtractPlugin, the PurifyCSS plugin, and a way to glob files.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const glob = require(&amp;quot;glob-all&amp;quot;);
const MiniCssExtractPlugin = require(&amp;quot;mini-css-extract-plugin&amp;quot;);
const PurifyCSSPlugin = require(&amp;quot;purifycss-webpack&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then set up your &lt;code&gt;paths&lt;/code&gt; in PurifyCSS. These are the locations of the files that will contain your styles. PurifyCSS will statically scan these files for styles and reference them in the style sheet. Styles found in the markup or scripts are left in the final style sheet. Styles not found are removed. The &lt;a href="https://github.com/purifycss/purifycss#how-it-works"&gt;algorithm for finding used styles&lt;/a&gt; is pretty sophisticated.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;plugins: [
    new MiniCssExtractPlugin({
        filename: &amp;quot;[name].css&amp;quot;
    }),
    new PurifyCSSPlugin({
        paths: glob.sync([
            path.join(__dirname, &amp;quot;Views/**/*.cshtml&amp;quot;),
            path.join(__dirname, &amp;quot;Scripts/**/*.html&amp;quot;),
            path.join(__dirname, &amp;quot;Scripts/**/*.js&amp;quot;)
        ])
    })
],
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, I'm referencing my ASP.NET MVC Razor pages in &lt;code&gt;Views/**/*.cshtml&lt;/code&gt;, my component templates in &lt;code&gt;Scripts/**/*.html&lt;/code&gt;, and my project &lt;code&gt;*.js&lt;/code&gt; files. Also note this plugin entry goes &lt;em&gt;after&lt;/em&gt; the &lt;code&gt;MiniCssExtractPlugin&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="add-any-whitelist-exceptions"&gt;Add any whitelist exceptions&lt;/h3&gt;
&lt;p&gt;Even with it's fancy algorithm, PurifyCSS can still miss styles it should leave alone. To prevent PurifyCSS from removing them from the final CSS, use the &lt;code&gt;whitelist&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;Here, I've got a project style sheet with two styles – one that should be removed because it is not referenced, and one that should be left in even though it isn't referenced.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-css"&gt;.some-unused-class {
    color: red;
}
&lt;p&gt;.some-dynamic-class {
color: red;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;To do this, I've added &lt;code&gt;&amp;quot;*some-dynamic-class*&amp;quot;&lt;/code&gt; to the &lt;code&gt;whitelist&lt;/code&gt; array so PurifyCSS won't remove it.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;plugins: [
    new MiniCssExtractPlugin({
        filename: &amp;quot;[name].css&amp;quot;
    }),
    new PurifyCSSPlugin({
        paths: glob.sync([
            path.join(__dirname, &amp;quot;Views/**/*.cshtml&amp;quot;),
            path.join(__dirname, &amp;quot;Scripts/**/*.html&amp;quot;),
            path.join(__dirname, &amp;quot;Scripts/**/*.js&amp;quot;)
        ]),
        purifyOptions: {
            whitelist: [&amp;quot;*some-dynamic-class*&amp;quot;]
        }
    })
],
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="results"&gt;Results&lt;/h3&gt;
&lt;p&gt;In the sample project, I'm using Bootstrap and a very small app style sheet. Here are the result before PurifyCSS.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/4/before_purifycss_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/4/before_purifycss_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;And here are the result after PurifyCSS.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/4/after_purifycss_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/4/after_purifycss_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;The sample site is a one-page site with a carousel component that references Bootstrap CSS, and as you would expect, the KB trimmed from removing unused CSS selectors is significant.&lt;/p&gt;
&lt;p&gt;Here is what happened with that class &lt;code&gt;.some-dynamic-class&lt;/code&gt; I put in the PurifyCSS &lt;code&gt;whitelist&lt;/code&gt;.  The &lt;code&gt;.some-unused-class&lt;/code&gt; selector is removed as we'd expect, and the &lt;code&gt;.some-dynamic-class&lt;/code&gt; is still in the final CSS file at the bottom.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/4/whitelist_style_left_in_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/4/whitelist_style_left_in_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;All this code is on &lt;a href="https://github.com/VolareSoftware/TrimUnusedCSS"&gt;GitHub&lt;/a&gt; if you want to see the &lt;code&gt;package.json&lt;/code&gt; or full &lt;code&gt;webpack.config.js&lt;/code&gt; or mess around with this yourself.&lt;/p&gt;
</description>
      <pubDate>Mon, 16 Apr 2018 21:49:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/tree-shaking-with-bootstrap-4-and-webpack</guid>
      <link>https://volaresoftware.com/nl/technical-posts/tree-shaking-with-bootstrap-4-and-webpack</link>
      <title>Tree shaking with Bootstrap 4 and webpack</title>
      <description>&lt;p&gt;The simplest way to use &lt;a href="https://getbootstrap.com/"&gt;Bootstrap 4&lt;/a&gt; is to add the whole thing from the CDNs.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1, shrink-to-fit=no&amp;quot;&amp;gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;Bootstrap Size Test&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
        &amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
            &amp;lt;div class=&amp;quot;col-sm&amp;quot;&amp;gt;
                page
            &amp;lt;/div&amp;gt;
            &amp;lt;div class=&amp;quot;col-sm&amp;quot;&amp;gt;
                content
            &amp;lt;/div&amp;gt;
            &amp;lt;div class=&amp;quot;col-sm&amp;quot;&amp;gt;
                goes
            &amp;lt;/div&amp;gt;
            &amp;lt;div class=&amp;quot;col-sm&amp;quot;&amp;gt;
                here
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;script src=&amp;quot;//code.jquery.com/jquery-3.2.1.slim.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;//cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem is, you might not need everything Bootstrap has to offer. Adding the JavaScript like this adds 134.5 KB (ignoring gzipping for comparison below) to your page.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/2/full_bootstrap_fom_cdns_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/2/full_bootstrap_fom_cdns_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you are using ES2015+ and the npm distribution, and you don't need the whole Bootstrap package, you can &lt;code&gt;import&lt;/code&gt; just the code you need. Here's how.&lt;/p&gt;
&lt;h2 id="set-up-bootstrap-babel-and-webpack"&gt;Set up Bootstrap, Babel, and webpack&lt;/h2&gt;
&lt;p&gt;First, install Bootstrap, along with jQuery and Popper, which Bootstrap relies on. Then install webpack, along with tools to use ES2015+ syntax and minify JavaScript for distribution.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;npm install bootstrap jquery popper.js
npm install --save-dev webpack babel-core babel-loader babel-preset-env clean-webpack-plugin exports-loader path uglifyjs-webpack-plugin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, update your &lt;code&gt;webpack.config.js&lt;/code&gt; to resolve the &lt;code&gt;/node_modules&lt;/code&gt; folder. You're setting this up so your &lt;code&gt;import&lt;/code&gt; statements know where to look when you reference Bootstrap modules.&lt;/p&gt;
&lt;p&gt;You'll also need to use &lt;code&gt;exports-loader&lt;/code&gt; with the webpack &lt;code&gt;ProvidePlugin&lt;/code&gt; to export the expected values from the Bootstrap modules and their dependencies. This helps with globals some of the Bootstrap modules depend on, like $ for jQuery.&lt;/p&gt;
&lt;p&gt;Finally, I've added an &lt;code&gt;alias&lt;/code&gt; for jQuery to point to &lt;code&gt;jquery.slim.min.js&lt;/code&gt; since that's enough jQuery functionality for Bootstrap to work. If you are already using the full jQuery in your project, skip this &lt;code&gt;alias&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const webpack = require(&amp;quot;webpack&amp;quot;);
const path = require(&amp;quot;path&amp;quot;);
const CleanWebpackPlugin = require(&amp;quot;clean-webpack-plugin&amp;quot;);
const UglifyJsPlugin = require(&amp;quot;uglifyjs-webpack-plugin&amp;quot;);
&lt;p dead_code:="" true=""&gt;module.exports = () =&amp;gt; {
return {
entry: {
index: &amp;quot;index.js&amp;quot;
},
output: {
filename: &amp;quot;[name].js&amp;quot;,
path: path.resolve(__dirname, &amp;quot;dist&amp;quot;),
publicPath: &amp;quot;/dist&amp;quot;
},
devtool: &amp;quot;source-map&amp;quot;,
plugins: [
new CleanWebpackPlugin([&amp;quot;dist&amp;quot;]),
new webpack.ProvidePlugin({
$: &amp;quot;jquery&amp;quot;,
Popper: [&amp;quot;popper.js&amp;quot;, &amp;quot;default&amp;quot;],
Alert: &amp;quot;exports-loader?Alert!bootstrap/js/dist/alert&amp;quot;,
Button: &amp;quot;exports-loader?Button!bootstrap/js/dist/button&amp;quot;,
Carousel: &amp;quot;exports-loader?Carousel!bootstrap/js/dist/carousel&amp;quot;,
Collapse: &amp;quot;exports-loader?Collapse!bootstrap/js/dist/collapse&amp;quot;,
Dropdown: &amp;quot;exports-loader?Dropdown!bootstrap/js/dist/dropdown&amp;quot;,
Modal: &amp;quot;exports-loader?Modal!bootstrap/js/dist/modal&amp;quot;,
Popover: &amp;quot;exports-loader?Popover!bootstrap/js/dist/popover&amp;quot;,
Scrollspy: &amp;quot;exports-loader?Scrollspy!bootstrap/js/dist/scrollspy&amp;quot;,
Tab: &amp;quot;exports-loader?Tab!bootstrap/js/dist/tab&amp;quot;,
Tooltip: &amp;quot;exports-loader?Tooltip!bootstrap/js/dist/tooltip&amp;quot;,
Util: &amp;quot;exports-loader?Util!bootstrap/js/dist/util&amp;quot;
}),
new webpack.optimize.CommonsChunkPlugin({
name: &amp;quot;common&amp;quot;
}),
new UglifyJsPlugin({
sourceMap: true,
uglifyOptions: })
],
resolve: {
extensions: [
&amp;quot;.js&amp;quot;
],
modules: [
path.resolve(__dirname, &amp;quot;scripts&amp;quot;),
&amp;quot;node_modules&amp;quot;
],
alias: {
jquery: &amp;quot;jquery/dist/jquery.slim.min.js&amp;quot;
}
},
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: &amp;quot;babel-loader&amp;quot;,
options: {
presets: [&amp;quot;env&amp;quot;]
}
}
}
]
}
};
};
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="import-just-the-needed-modules"&gt;Import just the needed modules&lt;/h2&gt;
&lt;p&gt;Now you can import the Bootstrap style sheet from &lt;code&gt;/node_modules&lt;/code&gt;, assuming you want the same styling on every page.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://volaresoftware.com/blog/node_modules/bootstrap/dist/css/bootstrap.min.css&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also &lt;code&gt;import&lt;/code&gt; Bootstrap styles from inside your webpack modules, but for most web apps, you'll want the same styling on all pages, and putting a link to the style sheet in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; is an easy way to do that.&lt;/p&gt;
&lt;p&gt;Now you can write code that &lt;code&gt;imports&lt;/code&gt; only the needed Bootstrap modules like this.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;import &amp;quot;bootstrap/js/dist/carousel&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's say have a page that uses the Bootstrap carousel. Here's the HTML, including a reference to a webpack-built &lt;code&gt;index.js&lt;/code&gt; from my &lt;code&gt;/dist&lt;/code&gt; folder that only includes the carousel reference above.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1, shrink-to-fit=no&amp;quot;&amp;gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://volaresoftware.com/blog/node_modules/bootstrap/dist/css/bootstrap.min.css&amp;quot; /&amp;gt;
    &amp;lt;title&amp;gt;Bootstrap Size Test&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
        &amp;lt;div id=&amp;quot;carouselExampleIndicators&amp;quot; class=&amp;quot;carousel slide&amp;quot; data-ride=&amp;quot;carousel&amp;quot;&amp;gt;
            &amp;lt;ol class=&amp;quot;carousel-indicators&amp;quot;&amp;gt;
                &amp;lt;li data-target=&amp;quot;#carouselExampleIndicators&amp;quot; data-slide-to=&amp;quot;0&amp;quot; class=&amp;quot;active&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;
                &amp;lt;li data-target=&amp;quot;#carouselExampleIndicators&amp;quot; data-slide-to=&amp;quot;1&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;
                &amp;lt;li data-target=&amp;quot;#carouselExampleIndicators&amp;quot; data-slide-to=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;
            &amp;lt;/ol&amp;gt;
            &amp;lt;div class=&amp;quot;carousel-inner&amp;quot;&amp;gt;
                &amp;lt;div class=&amp;quot;carousel-item active&amp;quot;&amp;gt;
                    &amp;lt;img class=&amp;quot;d-block w-100&amp;quot; data-src=&amp;quot;holder.js/800x400?auto=yes&amp;amp;amp;amp;bg=777&amp;amp;amp;amp;fg=555&amp;amp;amp;amp;text=First slide&amp;quot; alt=&amp;quot;First slide [800x400]&amp;quot; src=&amp;quot;data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_161c9dd15ef%20text%20%7B%20fill%3A%23555%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_161c9dd15ef%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23777%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22285.921875%22%20y%3D%22217.7%22%3EFirst%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E&amp;quot; data-holder-rendered=&amp;quot;true&amp;quot;&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;
                    &amp;lt;img class=&amp;quot;d-block w-100&amp;quot; data-src=&amp;quot;holder.js/800x400?auto=yes&amp;amp;amp;amp;bg=666&amp;amp;amp;amp;fg=444&amp;amp;amp;amp;text=Second slide&amp;quot; alt=&amp;quot;Second slide [800x400]&amp;quot; src=&amp;quot;data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_161c9dd15f3%20text%20%7B%20fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_161c9dd15f3%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23666%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22247.3203125%22%20y%3D%22217.7%22%3ESecond%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E&amp;quot; data-holder-rendered=&amp;quot;true&amp;quot;&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;
                    &amp;lt;img class=&amp;quot;d-block w-100&amp;quot; data-src=&amp;quot;holder.js/800x400?auto=yes&amp;amp;amp;amp;bg=555&amp;amp;amp;amp;fg=333&amp;amp;amp;amp;text=Third slide&amp;quot; alt=&amp;quot;Third slide [800x400]&amp;quot; src=&amp;quot;data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_161c9dd15f8%20text%20%7B%20fill%3A%23333%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_161c9dd15f8%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23555%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22277%22%20y%3D%22217.7%22%3EThird%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E&amp;quot; data-holder-rendered=&amp;quot;true&amp;quot;&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;a class=&amp;quot;carousel-control-prev&amp;quot; href=&amp;quot;#carouselExampleIndicators&amp;quot; role=&amp;quot;button&amp;quot; data-slide=&amp;quot;prev&amp;quot;&amp;gt;
                &amp;lt;span class=&amp;quot;carousel-control-prev-icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
                &amp;lt;span class=&amp;quot;sr-only&amp;quot;&amp;gt;Previous&amp;lt;/span&amp;gt;
            &amp;lt;/a&amp;gt;
            &amp;lt;a class=&amp;quot;carousel-control-next&amp;quot; href=&amp;quot;#carouselExampleIndicators&amp;quot; role=&amp;quot;button&amp;quot; data-slide=&amp;quot;next&amp;quot;&amp;gt;
                &amp;lt;span class=&amp;quot;carousel-control-next-icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
                &amp;lt;span class=&amp;quot;sr-only&amp;quot;&amp;gt;Next&amp;lt;/span&amp;gt;
            &amp;lt;/a&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;script src=&amp;quot;/dist/common.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;/dist/index.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The page now uses the same full Bootstrap CSS, which accounts for most of the Bootstrap weight at 141 KB. But the size of the JavaScript is just over 76 KB, saving us about 58 KB from the original approach.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2018/2/tree_shaken_bootstrap_thumb.png" alt="https://cdn.volaresoftware.com/images/posts/2018/2/tree_shaken_bootstrap_thumb.png" /&gt;&lt;/p&gt;
&lt;p&gt;It is much simpler to pull in the full Bootstrap library, but if you need to squeeze out a little more performance or shrink your page weight a little more, pulling in only the Bootstrap libraries you need can help.&lt;/p&gt;
&lt;p&gt;The sample code for this post is &lt;a href="https://github.com/VolareSoftware/TreeShakingWithBootstrap"&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Sat, 24 Feb 2018 19:48:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/setting-default-values-for-multiple-value-parameters-in-reporting-services</guid>
      <link>https://volaresoftware.com/nl/technical-posts/setting-default-values-for-multiple-value-parameters-in-reporting-services</link>
      <title>Setting Default Values for Multiple Value Parameters in Reporting Services</title>
      <description>&lt;p&gt;Today I was working on a Reporting Services report that needed to have all the values checked for a multi-value parameter when the report opened up.  It was a little tricky to figure out, but it turned out to be very simple in the end.&lt;/p&gt;
&lt;h2 id="multiple-value-parameters"&gt;Multiple Value Parameters&lt;/h2&gt;
&lt;p&gt;I've got some multiple value parameters on a report.  These are easy to create in SQL Server Reporting Services.  Just check the box for your parameter and the user gets a check box drop down letting them pick more than one value from the drop down.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2010/10/image_4.png" alt="image_4.png" /&gt;&lt;/p&gt;
&lt;h2 id="available-values"&gt;Available Values&lt;/h2&gt;
&lt;p&gt;You can set the available values for the drop down to a dataset in your report or a shared dataset in the Reporting Services project.  Next, pick the value and name fields (which can be the same column in the dataset if that's what works in your situation).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2010/10/image_5.png" alt="image_5.png" /&gt;&lt;/p&gt;
&lt;h2 id="default-values"&gt;Default Values&lt;/h2&gt;
&lt;p&gt;This is the part where we want to check each of those multiple values on report startup.  The hard part is, I don't know the values at design time, so I can't hard code them.  I want to simulate a &amp;quot;select all&amp;quot; of the check boxes.  My mind started wandering to VBA code I could put in the report as a startup function.&lt;/p&gt;
&lt;p&gt;But on a whim, I tried selecting all the values from the same query, and I was pleased to see it work!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2010/10/image_6.png" alt="image_6.png" /&gt;&lt;/p&gt;
&lt;p&gt;And I get the results I want on the report when it opens:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2010/10/image_7.png" alt="image_7.png" /&gt;&lt;/p&gt;
</description>
      <pubDate>Sat, 02 Oct 2010 00:40:40 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/fixing-screen-saver-wait-time-of-999-minutes-on-a-dell-laptop</guid>
      <link>https://volaresoftware.com/nl/technical-posts/fixing-screen-saver-wait-time-of-999-minutes-on-a-dell-laptop</link>
      <title>Fixing screen saver wait time of 999 minutes on a Dell laptop</title>
      <description>&lt;p&gt;I have a Dell Precision M4500 with Windows 7 and ran into a problem with the screen saver not coming on.  Rebooting didn't fix it and calling Dell technical support didn't help (&amp;quot;You could reformat, I guess.&amp;quot;).&lt;/p&gt;
&lt;p&gt;My screen saver dialog looked like this with 999 minutes in the wait time:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2011/3/snaghtml1e594b9_1.png" alt="snaghtml1e594b9_1.png" /&gt;&lt;/p&gt;
&lt;p&gt;If I clicked Preview, the screen would go blank like it was supposed to, so it wasn't a video card thing.  When I set the wait time to 10 minutes and clicked OK, then opened the dialog box again, my value of 10 minutes was saved, but the screen saver never turned on.&lt;/p&gt;
&lt;p&gt;Finally, I found this dialog in the Dell System and Manager under Display Settings:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2011/3/snaghtml1e9726b_1.png" alt="snaghtml1e9726b_1.png" /&gt;&lt;/p&gt;
&lt;p&gt;See the &amp;quot;Disable alarms and timers for Presentations&amp;quot; check box?  I had that checked, so I unchecked it and the screen saver started working normally again.  I wasn't in Presentation mode, but this Dell app didn't seem to know that.&lt;/p&gt;
&lt;p&gt;I hope this is helpful to someone stuck on the same issue.&lt;/p&gt;
</description>
      <pubDate>Thu, 10 Mar 2011 01:40:18 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/specflow-and-watin-worst-practices-what-not-to-do</guid>
      <link>https://volaresoftware.com/nl/technical-posts/specflow-and-watin-worst-practices-what-not-to-do</link>
      <title>SpecFlow and WatiN Worst Practices: What *NOT* to do</title>
      <description>&lt;p&gt;The best way to learn something is to jump right in.  Best practices don't really emerge until you've found out what works and what doesn't.  This is my list of things that didn't work on my four &lt;a href="http://specflow.org/"&gt;SpecFlow&lt;/a&gt; and &lt;a href="http://watin.org/"&gt;WatiN&lt;/a&gt; projects in the last two years.  Of course, I'll also talk about what did work.&lt;/p&gt;
&lt;h2 id="acknowledgements"&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;First off, almost everything I know about SpecFlow/Cucumber/Gherkin I learned from &lt;a href="https://twitter.com/thepaulrayner"&gt;Paul Rayner&lt;/a&gt; and pairing with with him on two projects.  I'm grateful for the experience and the knowledge gained.&lt;/p&gt;
&lt;p&gt;I've also tried to glean as much as I can from &lt;a href="https://twitter.com/marcusoftnet"&gt;Marcus Hammarberg&lt;/a&gt;, &lt;a href="https://twitter.com/darrencauthon"&gt;Darren Cauthon&lt;/a&gt;, &lt;a href="https://twitter.com/rslawrence"&gt;Richard Lawrence&lt;/a&gt;, and &lt;a href="https://twitter.com/brandonsatrom"&gt;Brandon Satrom&lt;/a&gt; in their twitter feeds and &lt;a href="http://msdn.microsoft.com/en-us/magazine/gg490346.aspx"&gt;articles&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="what-level-of-your-app-should-you-test"&gt;What level of your app should you test?&lt;/h2&gt;
&lt;p&gt;One big issue that comes up around SpecFlow is what level of your application should you be testing – internal or external.  The answer has a big impact on how you write your feature files, what side benefits you get from the feature files, and the speed of your tests.&lt;/p&gt;
&lt;h3 id="developer-facing"&gt;Developer-facing&lt;/h3&gt;
&lt;p&gt;You can use SpecFlow as a BDD-style tool and do unit or light integration testing with it.  I call these developer-facing feature files, because they are expressed in language internal to the application (&amp;quot;Then I post the form values to the AccountController&amp;quot;).  The nice thing about this is the readability of the test from the dev side and the speed of execution, since you are explicitly testing code internals.&lt;/p&gt;
&lt;h3 id="business-facing"&gt;Business-facing&lt;/h3&gt;
&lt;p&gt;But I think this misses an opportunity to have richer language in the feature files.  If the SpecFlow features are worded the way the product owner sees the app working, you are fostering a &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design"&gt;ubiquitous language&lt;/a&gt; between the business and the developers.  You have a clearer vision of your app's external behavior expressed through concrete examples.&lt;/p&gt;
&lt;p&gt;You end up with &amp;quot;Then I click the save button&amp;quot; or even better, &amp;quot;Then I save&amp;quot; instead of &amp;quot;Then I post the form values to the AccountController&amp;quot;.  The bad thing about this style of spec wording is you end up testing through UI test automation tools like WatiN.  This testing style is slow and can be buggy and fragile if you aren't careful (see below for tips).&lt;/p&gt;
&lt;p&gt;In my experience, one of the main problems in software development is getting the dev team to understand what the business wants built and why.  SpecFlow is a great tool for getting both sides together to define that behavior through examples.&lt;/p&gt;
&lt;p&gt;Furthermore, UI testing becomes much more important as web applications take on more and more JavaScript and other client-side code.  Since the external behavior of the app is how the business and users will evaluate the app, I think it makes sense to test at this level.&lt;/p&gt;
&lt;h2 id="how-not-to-set-up-your-test-project"&gt;How not to set up your test project&lt;/h2&gt;
&lt;p&gt;Acceptance tests that drive the browser are &lt;strong&gt;not&lt;/strong&gt; unit tests.  They are closer to integration tests, but they are even &lt;strong&gt;slower&lt;/strong&gt;, since your local web server and the browser have to spin up each time and fill out forms, click buttons, etc.&lt;/p&gt;
&lt;p&gt;Because of this, don't add SpecFlow to your current unit test project or even your current integration test project, if you separate those.  Let it live in its own project with a name like MyProject.AcceptanceTests.  For quick test running and CI, &lt;a href="https://volaresoftware.com/en/technical-posts/running-specflow-and-watin-tests-with-teamcity-and-appharbor"&gt;it's much easier to omit an entire assembly of tests&lt;/a&gt;, so keep these guys separate.&lt;/p&gt;
&lt;p&gt;I find that I often want to run the faster unit tests and run the acceptance tests only around the parts of the application we are working on.  I run the full suite maybe 2-5 times a week, especially before a hand-off to a stakeholder or a big demo.&lt;/p&gt;
&lt;h2 id="how-not-to-install-specflow-and-watin"&gt;How not to install SpecFlow and WatiN&lt;/h2&gt;
&lt;p&gt;Don't bother with DLL downloads or manually setting up file references.  Install the &lt;a href="http://nuget.org/packages/SpecFlow"&gt;SpecFlow NuGet package&lt;/a&gt; and the &lt;a href="http://visualstudiogallery.msdn.microsoft.com/9915524d-7fb0-43c3-bb3c-a8a14fbd40ee"&gt;Visual Studio Extension&lt;/a&gt;.  Let NuGet handle the assembly references and setting up the app.config for you.  The VS Extension adds some nice feature file editing and right-click features to run a single test.&lt;/p&gt;
&lt;p&gt;You'll need to decide on &lt;a href="http://en.wikipedia.org/wiki/MSTest"&gt;MSTest&lt;/a&gt; versus &lt;a href="http://www.nunit.org/"&gt;NUnit&lt;/a&gt;.  The first comes with .NET, the later is free open source and &lt;a href="http://nuget.org/packages/nunit"&gt;you can add it with NuGet&lt;/a&gt;.  If you're in a shop that heavily favors one over the other, use that.  All you're using these for in the SpecFlow world is the generated code and the attributes marking your test fixtures and methods.&lt;/p&gt;
&lt;p&gt;If you're using NUnit (the default), you'll need to be sure ApartmentState is set to &amp;quot;STA&amp;quot; in the app.config for your test project like this.  If you use the NuGet download, it should take care of that.&lt;/p&gt;
&lt;p&gt;Finally, you'll need WatiN, which can also be installed with a &lt;a href="http://nuget.org/packages/watin"&gt;NuGet package&lt;/a&gt;.  I've sometimes had to set some of the WatiN assemblies to Copy Local = true in the acceptance test project to get everything working.  Kind of a hassle, but once it's set up right, you're done forever with it.&lt;/p&gt;
&lt;h2 id="how-not-to-set-up-a-webbrowser-class-and-app.config"&gt;How not to set up a WebBrowser class and app.config&lt;/h2&gt;
&lt;p&gt;WatiN can run UI tests with Internet Explorer or FireFox (not Chrome, Safari, Opera, or anything else).  The FireFox API didn't have parity with the IE one last time I checked, so I've gotten used to using the WatiN IE class.&lt;/p&gt;
&lt;p&gt;However, don't reference this class directly, or all your code is IE dependent.  What if the next version of WatiN supports an iPad emulator you want to use?  Do you really trust your find-replace skills that much?&lt;/p&gt;
&lt;p&gt;Instead, wrap the references with a static class, and reference that in your step definitions.  Here's the one I'm using these days that gets an instance of IE in a static constructor:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;namespace Helpers
{
    public static class WebBrowser
    {
        private static IE _browser;
&lt;pre&gt;&lt;code&gt;    static WebBrowser()
    {
        _browser = new IE();
        _browser.ShowWindow(NativeMethods.WindowShowStyle.Maximize);
    }

    public static IE Current
    {
        get { return _browser; }
        set { _browser = value; }
    }

    public static string BaseUrl
    {
        get { return ConfigurationManager.AppSettings[&amp;amp;quot;BaseUrl&amp;amp;quot;]; }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This is maximizing the IE window after it opens and adding a reference to a BaseUrl property, which is set in the &lt;code&gt;app.config&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;appSettings&amp;gt;
    &amp;lt;clear/&amp;gt;
    &amp;lt;add key=&amp;quot;BaseUrl&amp;quot; value=&amp;quot;http://localhost:1234/&amp;quot;/&amp;gt;
    &amp;lt;!--&amp;lt;add key=&amp;quot;BaseUrl&amp;quot; value=&amp;quot;http://myapp.apphb.com&amp;quot;/&amp;gt;--&amp;gt;
&amp;lt;/appSettings&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I use the BaseUrl to switch out the location of the test target in the step definitions (not shown above).  So if I want to test locally, the BaseUrl is &amp;quot;http://localhost:1234/&amp;quot;.  If I want to hit the AppHarbor version, the BaseUrl &amp;quot;http://myapp.apphb.com/&amp;quot;.  Just change the app.config and run the tests.&lt;/p&gt;
&lt;h2 id="how-not-to-set-up-your-specflow-before-and-after-attributes"&gt;How not to set up your SpecFlow Before and After attributes&lt;/h2&gt;
&lt;p&gt;SpecFlow has attributes that can be put over your step definitions for your setup and teardown code.  Here are the hooks you have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BeforeTestRun / AfterTestRun&lt;/li&gt;
&lt;li&gt;BeforeFeature / AfterFeature&lt;/li&gt;
&lt;li&gt;BeforeScenario / AfterScenario&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I've struggled with where these go before, but the last couple projects I created a &lt;code&gt;BeforeAndAfter.cs&lt;/code&gt; class (clever, huh?), set the SpecFlow [Binding] attribute to the top of the class, then added all my before/after code.&lt;/p&gt;
&lt;p&gt;This is a great place to put database clean ups, security code if your app has a login, any custom SpecFlow tags you've created, etc.  Here's the code I used on my last project:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Configuration;
using TechTalk.SpecFlow;
using WatiN.Core;
&lt;p&gt;namespace Helpers
{
[Binding]
public class BeforeAndAfter
{
[BeforeTestRun]
public static void BeforeTestRun()
{
// Ignore all features and scenarios when running on AppHarbor
if (ConfigurationManager.AppSettings[&amp;quot;Environment&amp;quot;] == &amp;quot;Test&amp;quot;)
{
Assert.Ignore();
return;
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        // Always login first
        Security.ILoginAsAdministrator();
    }

    [AfterTestRun]
    public static void AfterTestRun()
    {
        // Logout to be ready for next session
        Security.ILogout();

        // Close the browser and dispose
        WebBrowser.Current.Close();
        WebBrowser.Current.Dispose();

        // Reset the data to be ready for the next session
        TestData.CleanUp();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I put all my helper methods like the &lt;code&gt;WebBrowser.cs&lt;/code&gt; and &lt;code&gt;BeforeAndAfter.cs&lt;/code&gt; in a &lt;code&gt;/Helpers&lt;/code&gt; folder in the acceptance test project.&lt;/p&gt;
&lt;h2 id="how-not-to-organize-your-feature-files"&gt;How not to organize your feature files&lt;/h2&gt;
&lt;p&gt;Feature files have one or more features in them.  You could put each separate feature in it's on .feature file, but that's overkill.&lt;/p&gt;
&lt;p&gt;I used to create a new feature file for each view in the app.  That probably makes sense in some cases, but this approach often misses the value of those pages.  For instance, if there are 2-3 pages for an e-commerce checkout process, it's probably not that helpful to have a feature file for &lt;code&gt;BillingAndShippingAddress.feature&lt;/code&gt;, &lt;code&gt;CreditCard.feature&lt;/code&gt;, and &lt;code&gt;Confirmation.feature&lt;/code&gt;.  It might be helpful to developers, but it's likely non-developers on the team see the checkout process more holistically, so why not start with a Checkout.feature file?  If this gets too big, split out pieces into their own logical .feature files later.&lt;/p&gt;
&lt;p&gt;I put all my feature files in a /Features folder in the acceptance test project.  It's mostly cosmetic, but it does help a little.&lt;/p&gt;
&lt;h2 id="how-not-to-organize-your-step-definition-files"&gt;How not to organize your step definition files&lt;/h2&gt;
&lt;p&gt;Step definitions are the implementation of the steps in the feature files. Since I was organizing feature files by web app page, I started out doing the same with step definitions. When you try this approach, you quickly see the problem, since step definitions can and should be reused across features.&lt;/p&gt;
&lt;p&gt;If there is a step definition &amp;quot;Then I go to /MyPage&amp;quot;, the step definition might be clicking a menu, a link in the page, or just opening a URL.  As you can imagine, this can be helpful in lots of different feature files, so it makes more sense to group these in a Navigation.cs file or something like that.  Maybe you have a separate Menu.cs with those step definitions, or maybe you lump them in with Navigation.&lt;/p&gt;
&lt;p&gt;How you group these is up to you.  SpecFlow sees all &lt;code&gt;*.cs&lt;/code&gt; files with a &lt;code&gt;[Binding]&lt;/code&gt; on them as places where your step definitions could live, and it uses regex matching to find the right method.  SpecFlow doesn't care if you put your methods in one class or 100 classes, but you will.  So put some thought into how you group these, because it's easier to see opportunities to refactor out similar code you find within the same .cs file versus across .cs files.&lt;/p&gt;
&lt;p&gt;This makes the file names much more generic, but I've had the most success with this style.  On recent projects, my step definition files have included Forms.cs, Menu.cs, Messages.cs, Navigation.cs, Search.cs, Security.cs, and SEO.cs.&lt;/p&gt;
&lt;p&gt;I put all my step definition code in a /Steps folder.  In the end, it looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/1/image_30.png" alt="image_30.png" /&gt;&lt;/p&gt;
&lt;h2 id="how-not-to-code-step-definitions"&gt;How not to code step definitions&lt;/h2&gt;
&lt;p&gt;Step definition code in each method should be brief – like a couple lines.  If you've got large blocks of code, you've probably got too much going on.&lt;/p&gt;
&lt;p&gt;Maybe you have a giant form with tons of fields and a SpecFlow table feeding you the values.  You can probably get away with something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public void IFillOutTheForm(Table table) 
{
    foreach (var row in table.Rows)
    {
        var field = row[&amp;quot;Field&amp;quot;];
        var value = row[&amp;quot;Value&amp;quot;];
        switch (field)
        {
            case &amp;quot;Something Different&amp;quot;:  // Put exceptions here for drop downs, date pickers, radio buttons, etc.
                WebBrowser.Current.SelectList(Find.ByName(&amp;quot;SomethingDifferentId&amp;quot;)).Select(value);
                break;
            default:
                WebBrowser.Current.TextField(Find.ByName(field)).Value = value;
                break;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, the &amp;quot;Something Different&amp;quot; case is where you would put non-textbox filling out code.  But if your forms are like most business apps, there are lots of text boxes, a handful of drop downs, and a smattering of radio, checkbox, date pickers, sliders, etc. that require some different WatiN code.&lt;/p&gt;
&lt;p&gt;Of course, if the exceptions outnumber the convention, make a separate method and see if you can factor out some common code to use somewhere else.  Remember, the key to being productive with SpecFlow is reusing the step definitions, so once you start seeing duplication, look for ways to refactor to a common convention in your feature files and step definitions.  It takes a while to get a critical mass of these built up, but once you do, you really start picking up speed.&lt;/p&gt;
</description>
      <pubDate>Sun, 06 Jan 2013 05:05:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/concatenating-and-decoding-strings-from-a-one-to-many-table-in-sql</guid>
      <link>https://volaresoftware.com/nl/technical-posts/concatenating-and-decoding-strings-from-a-one-to-many-table-in-sql</link>
      <title>Concatenating and decoding strings from a one-to-many table in SQL</title>
      <description>&lt;p&gt;Let's say you have two tables in SQL Server: Person and PersonNotes. PersonNotes is a one-to-many table of notes about that Person.  Here's the SQL for the tables:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;create table Person (PersonId int not null)
insert Person (PersonId) values (1)
&lt;p&gt;create table PersonNotes (PersonId int not null, Note varchar(max))
insert PersonNotes (PersonId, Note) values (1, 'note &amp;lt;1&amp;gt;')
insert PersonNotes (PersonId, Note) values (1, '&amp;amp;amp; note #2')
insert PersonNotes (PersonId, Note) values (1, '&amp;amp;amp; finally, note &amp;lt;3&amp;gt;')
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And let's say you need to grab all those PersonNotes rows and concatenate them into one string per Person row.  You have a couple options: 1) create a custom function, 2) write a cursor, or 3) use T-SQL's FOR XML trick.  I'll focus on the last one n this post.&lt;/p&gt;
&lt;p&gt;Using FOR XML is kind of lame, since it's really meant for something else, but it works pretty well to pull all the strings across rows into one value:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;select Person.PersonId, (select PersonNotes.Note + ' '
                        from PersonNotes
                        where PersonNotes.PersonId = Person.PersonId
                        for xml path('')) AS Notes
from Person  
where Person.PersonId = 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's the &lt;a href="http://sqlfiddle.com/#!6/8ec9d/14/0"&gt;SQL Fiddle&lt;/a&gt; for this table setup and query.  Running this will get you these results:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;note &amp;amp;amp;lt;1&amp;amp;amp;gt; &amp;amp;amp;amp; note #2 &amp;amp;amp;amp; finally, note &amp;amp;amp;lt;3&amp;amp;amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem is, putting it in XML means you get lots of &amp;quot;&amp;lt;&amp;quot;, &amp;quot;&amp;gt;&amp;quot;, and &amp;quot;&amp;amp;&amp;quot; where the strings have been encoded.  That's what you want for XML, but it's not usually what you want for a string.&lt;/p&gt;
&lt;p&gt;But if we use a little XPATH to pull the first node from that resulting XML, we do get the decoded values again:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;select Person.PersonId, (select PersonNotes.Note + ' '
                        from PersonNotes
                        where PersonNotes.PersonId = Person.PersonId
                        for xml path(''), root, type).value('/', 'varchar(max)') AS Notes
from Person  
where Person.PersonId = 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's the &lt;a href="http://sqlfiddle.com/#!6/8ec9d/12/0"&gt;SQL Fiddle&lt;/a&gt; for the tables setup and query with the extra XPATH casting back to varchar(max).  Running this will get you these results:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;note &amp;lt;1&amp;gt; &amp;amp;amp; note #2 &amp;amp;amp; finally, note &amp;lt;3&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we're happy!&lt;/p&gt;
</description>
      <pubDate>Tue, 13 Oct 2015 10:23:43 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/using-visual-studio-2012-test-explorer-with-nunit-and-specflow</guid>
      <link>https://volaresoftware.com/nl/technical-posts/using-visual-studio-2012-test-explorer-with-nunit-and-specflow</link>
      <title>Using Visual Studio 2012 Test Explorer with NUnit and SpecFlow</title>
      <description>&lt;p&gt;This one came up today and surprised me.  I usually use the &lt;a href="http://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt; test runner, but I wanted to try out the new, improved &lt;a href="http://blogs.msdn.com/b/visualstudioalm/archive/2012/03/08/what-s-new-in-visual-studio-11-beta-unit-testing.aspx"&gt;Visual Studio Test Explorer in VS2012&lt;/a&gt;.  I have &lt;a href="http://www.nunit.org"&gt;NUnit&lt;/a&gt;-based unit and integration tests and &lt;a href="http://www.specflow.org/specflownew/"&gt;SpecFlow&lt;/a&gt;/&lt;a href="http://watin.org/"&gt;WatiN&lt;/a&gt; UI automation tests that use NUnit behind the scenes.&lt;/p&gt;
&lt;h2 id="visual-studio-extensions-and-updates"&gt;Visual Studio Extensions and Updates&lt;/h2&gt;
&lt;p&gt;You'll need to install the &lt;a href="http://visualstudiogallery.msdn.microsoft.com/6ab922d0-21c0-4f06-ab5f-4ecd1fe7175d"&gt;NUnit Test Adapter&lt;/a&gt; so the Visual Studio Test Explorer knows what to do.  You don't need to go back and change attributes, references, etc. to use MSTest.  It can work with NUnit natively once you add this extension under Tools &amp;gt; Extensions and Updates.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2012/9/snaghtmldadd84c_2.png" alt="snaghtmldadd84c_2.png" /&gt;&lt;/p&gt;
&lt;h2 id="apartment-state"&gt;Apartment State&lt;/h2&gt;
&lt;p&gt;Using SpecFlow with NUnit means you have to set your app.config ApartmentState to STA.  &lt;a href="http://stackoverflow.com/questions/2463461/nunit-gui-runner-and-apartment-state"&gt;This is well documented&lt;/a&gt;, but it's one of those things you have to do to get everything working.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;NUnit&amp;gt;
  &amp;lt;TestRunner&amp;gt;
    &amp;lt;add key=&amp;quot;ApartmentState&amp;quot; value=&amp;quot;STA&amp;quot;/&amp;gt;
  &amp;lt;/TestRunner&amp;gt;
&amp;lt;/NUnit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Making this a&lt;code&gt;pp.config&lt;/code&gt; change is all the ReSharper test runner needs, but the Visual Studio Test Explorer needs a little more help.  You have to set the NUnit attribute&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[assembly: RequiresSTA]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;in your &lt;code&gt;AssemblyInfo.cs&lt;/code&gt; for your test project where your SpecFlow tests live.&lt;/p&gt;
&lt;h2 id="done"&gt;Done!&lt;/h2&gt;
&lt;p&gt;Now you should be able to run ALL your solution's tests with the Visual Studio Test Explorer, including the SpecFlow ones!&lt;/p&gt;
&lt;p&gt;Visual Studio Test Explorer still needs a lot of work around grouping tests, and &lt;a href="https://twitter.com/pprovost"&gt;Peter Provost&lt;/a&gt; says as much in his blog post, but it has come a long way.&lt;/p&gt;
</description>
      <pubDate>Wed, 19 Sep 2012 00:39:59 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/integrating-kendo-ui-drop-downs-with-knockout-js</guid>
      <link>https://volaresoftware.com/nl/technical-posts/integrating-kendo-ui-drop-downs-with-knockout-js</link>
      <title>Integrating Kendo UI drop downs with Knockout JS</title>
      <description>&lt;p&gt;&lt;a href="http://www.kendoui.com/web.aspx"&gt;Kendo UI&lt;/a&gt; drop downs look great.  Here is a Kendo UI drop down with default styling in closed and open view:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/2/image_34.png" alt="image_34.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.volaresoftware.com/images/posts/2013/2/image_35.png" alt="image_35.png" /&gt;&lt;/p&gt;
&lt;p&gt;It is built with this HTML:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;input id=&amp;quot;kendoDropDown&amp;quot; type=&amp;quot;text&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and this JavaScript:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;// Init the drop down
$(&amp;quot;#kendoDropDown&amp;quot;).kendoDropDownList({
    dataValueField: &amp;quot;id&amp;quot;,
    dataTextField: &amp;quot;name&amp;quot;,
    dataSource: [
        { id: &amp;quot;1&amp;quot;, name: &amp;quot;apple&amp;quot; }, 
        { id: &amp;quot;2&amp;quot;, name: &amp;quot;orange&amp;quot; }, 
        { id: &amp;quot;3&amp;quot;, name: &amp;quot;banana&amp;quot; }
    ]
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="the-snag"&gt;The snag&lt;/h2&gt;
&lt;p&gt;Unfortunately, this handsome drop down doesn't integrate smoothly with &lt;a href="http://knockoutjs.com/"&gt;Knockout JS&lt;/a&gt; when it comes to data binding.&lt;/p&gt;
&lt;p&gt;We should be able to update our HTML to use a Knockout binding:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;p&amp;gt;
    &amp;lt;label for=&amp;quot;kendoDropDown&amp;quot;&amp;gt;Kendo UI Drop Down&amp;lt;/label&amp;gt;
    &amp;lt;input id=&amp;quot;kendoDropDown&amp;quot; type=&amp;quot;text&amp;quot; data-bind=&amp;quot;value: fruitId&amp;quot;
    /&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then add a view model and apply the Knockout binding:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;// Define and init the Knockout view model
var ViewModel = function () {
        var self = this;
        self.fruitId = ko.observable();
    },
    vm = new ViewModel();   
&lt;p&gt;// Set the initial fruit value
vm.fruitId(&amp;quot;2&amp;quot;); // orange&lt;/p&gt;
&lt;p&gt;// Wire up KO binding
ko.applyBindings(vm);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;We should see a drop down loaded with the view model's initial value of &amp;quot;2&amp;quot; (orange), but the first value in the list (&amp;quot;1&amp;quot; apple) is selected instead.  What's going on?&lt;/p&gt;
&lt;h2 id="more-investigation"&gt;More investigation&lt;/h2&gt;
&lt;p&gt;I thought maybe I had a Knockout bug in my code, so I played around with a plain (non-Kendo) select list and a plain text box by adding the following HTML:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;p&amp;gt;
    &amp;lt;label for=&amp;quot;select&amp;quot;&amp;gt;Plain old select&amp;lt;/label&amp;gt;
    &amp;lt;select id=&amp;quot;select&amp;quot; data-bind=&amp;quot;value: fruitId&amp;quot;&amp;gt;
        &amp;lt;option value=&amp;quot;1&amp;quot;&amp;gt;apple&amp;lt;/option&amp;gt;
        &amp;lt;option value=&amp;quot;2&amp;quot;&amp;gt;orange&amp;lt;/option&amp;gt;
        &amp;lt;option value=&amp;quot;3&amp;quot;&amp;gt;banana&amp;lt;/option&amp;gt;
    &amp;lt;/select&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
    &amp;lt;label for=&amp;quot;textBox&amp;quot;&amp;gt;Plain old text box&amp;lt;/label&amp;gt;
    &amp;lt;input id=&amp;quot;textBox&amp;quot; type=&amp;quot;text&amp;quot; data-bind=&amp;quot;value: fruitId&amp;quot; /&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But these controls were set to the correct initial value (&amp;quot;2&amp;quot; orange).&lt;/p&gt;
&lt;p&gt;It gets weirder when you change the view model's value programmatically.  Here, I've added some HTML buttons to do that:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;p&amp;gt;
    &amp;lt;button id=&amp;quot;changeTo3&amp;quot; class=&amp;quot;k-button&amp;quot;&amp;gt;change fruitId to &amp;quot;3&amp;quot; (banana) programmatically&amp;lt;/button&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
    &amp;lt;button id=&amp;quot;changeTo2&amp;quot; class=&amp;quot;k-button&amp;quot;&amp;gt;change fruitId to &amp;quot;2&amp;quot; (orange) programmatically&amp;lt;/button&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and some JavaScript to change the view model's values:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;// Wire up the buttons
$(&amp;quot;#changeTo3&amp;quot;).click(function () {
    vm.fruitId(&amp;quot;3&amp;quot;); // banana
});
$(&amp;quot;#changeTo2&amp;quot;).click(function () {
    vm.fruitId(&amp;quot;2&amp;quot;); // orange
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clicking the buttons should change the view model's value, which should change the controls' values.  It works for the plain HTML controls, but not for the Kendo UI drop down.&lt;/p&gt;
&lt;p&gt;Here's the &lt;a href="https://jsfiddle.net/joewilson0/dCb5L/38/"&gt;JSFiddle&lt;/a&gt; to see all this in action.&lt;/p&gt;
&lt;iframe width="100%" height="300" src="https://jsfiddle.net/joewilson0/dCb5L/38/embedded" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
&lt;h2 id="the-work-around"&gt;The work around&lt;/h2&gt;
&lt;p&gt;A &lt;a href="http://www.kendoui.com/blogs/teamblog/posts/12-02-16/kendo_ui_mvvm_and_knockoutjs.aspx"&gt;Kendo UI team blog post&lt;/a&gt; describes a work around for this issue, but it didn't work for me.&lt;/p&gt;
&lt;p&gt;The trick here is that the Kendo UI drop down is really a hidden input and a bunch of spans.  Knockout changes the value of the hidden input when the view model changes, but you have to hook into that jQuery DOM change event and call the code to select a new value in the Kendo drop down.  Kind of lame, but it's supposed to work.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;$(&amp;quot;#kendoDropDown&amp;quot;).bind(&amp;quot;change&amp;quot;, function() {
    $(this).data(&amp;quot;kendoDropDownList&amp;quot;).select(this.selectedIndex);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can even unhide the hidden text box inside the Kendo UI drop down list and watch its value change as the view model changes, but the drop down just sits there.  Arg!&lt;/p&gt;
&lt;h2 id="the-real-work-around"&gt;The real work around&lt;/h2&gt;
&lt;p&gt;I was pulling my hair out by now, and &lt;a href="http://stackoverflow.com/questions/14639232/kendo-ui-drop-down-not-updated-when-knockout-view-model-updates"&gt;asked for help on Stack Overflow&lt;/a&gt;.  Unfortunately, the answer I got was use another library that does the integration in a different way, the &lt;a href="https://github.com/kendo-labs/knockout-kendo"&gt;Knockout-Kendo.js library&lt;/a&gt;.  That's probably a good answer, but I was hoping to avoid adding another library just to use Knockout and Kendo UI together.&lt;/p&gt;
&lt;p&gt;Instead, I found I could get everything working as expected with a &lt;a href="http://knockoutjs.com/documentation/observables.html"&gt;Knockout subscription&lt;/a&gt;.  It's like a view model data change listener.  My thinking was that I could use the same concept as the Kendo UI team blog post (listen for a change and then manually set the drop down).  Not ideal, but oh well.&lt;/p&gt;
&lt;p&gt;Here's what I changed in the view model:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;self.fruitId.subscribe(function (newValue) {
    $(&amp;quot;#kendoDropDown&amp;quot;).data(&amp;quot;kendoDropDownList&amp;quot;).value(newValue);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the final, working &lt;a href="https://jsfiddle.net/joewilson0/dCb5L/45"&gt;JSFiddle&lt;/a&gt;.&lt;/p&gt;
&lt;iframe width="100%" height="300" src="https://jsfiddle.net/joewilson0/dCb5L/45/embedded" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"&gt;&lt;/iframe&gt;
</description>
      <pubDate>Sun, 17 Feb 2013 22:07:00 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/increasing-testability</guid>
      <link>https://volaresoftware.com/nl/technical-posts/increasing-testability</link>
      <title>Increasing Testability</title>
      <description>&lt;h2 id="testa-what"&gt;Testa-what?&lt;/h2&gt;
&lt;p&gt;I don't know if &amp;quot;testability&amp;quot; is a word, but if Bud Light can make up &amp;quot;drinkability&amp;quot;, maybe it should be.  I'm talking about how pliant your code is to testing.  If you're doing &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;BDD&lt;/a&gt;, the code you write is testable by definition.&lt;/p&gt;
&lt;p&gt;But if you're going the other way, and coding first or testing &lt;a href="http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1267943524&amp;amp;sr=8-1"&gt;legacy code (any code not already under test)&lt;/a&gt;, you've probably run into code that was hard to test and felt like giving up.  Some of the most common hurdles for testability are not coding to abstractions and not decoupling dependencies.  Here's how to get around that.&lt;/p&gt;
&lt;h2 id="the-problem"&gt;The problem&lt;/h2&gt;
&lt;p&gt;Here's a garden variety Order class with a &lt;code&gt;ProcessOrder&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class Order
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Email { get; set; }
  public decimal Total { get; set; }
&lt;p&gt;public bool ProcessOrder()
{
var result = false;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Validate order
if (!string.IsNullOrEmpty(this.Email) &amp;amp;amp;amp;&amp;amp;amp;amp; this.Total &amp;amp;gt; 0)
{
  // Send order confirmation email
  var emailService = new EmailService();
  var emailSendResult = emailService.SendOrderConfirmationEmail(this);

  if (emailSendResult == true)
  {
    // Do more order processing...

    result = true;
  }
}

return result;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And here's the test:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[Test]
public void Should_return_true_when_using_good_order_values()
{
  // Arrange
  var order = new Order();
  order.FirstName = &amp;quot;Joe&amp;quot;;
  order.LastName = &amp;quot;Wilson&amp;quot;;
  order.Email = &amp;quot;real_email_address@volaresystems.com&amp;quot;;
  order.Total = 123.00m;
&lt;p&gt;// Act
// Watch out!  Don't run this or it will send real emails!
var result = order.ProcessOrder();&lt;/p&gt;
&lt;p&gt;// Assert
Assert.That(result, Is.True);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;We need to call the &lt;code&gt;SendOrderConfirmationEmail&lt;/code&gt; method in the &lt;code&gt;EmailService&lt;/code&gt; class.  But if our test calls &lt;code&gt;ProcessOrder&lt;/code&gt;, there is no way to avoid calling the live emailing method as it's coded now.&lt;/p&gt;
&lt;p&gt;How can we test the logic in the &lt;code&gt;ProcessOrder&lt;/code&gt; method &lt;strong&gt;without&lt;/strong&gt; sending out a real email?&lt;/p&gt;
&lt;h2 id="code-to-abstractions"&gt;Code to Abstractions&lt;/h2&gt;
&lt;p&gt;First, we need to code to an abstraction of &lt;code&gt;EmailService&lt;/code&gt;, not to the concrete class itself.  So let's create an interface around &lt;code&gt;EmailService&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public interface IEmailService
{
    bool SendOrderConfirmationEmail(Order order);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then change the &lt;code&gt;EmailService&lt;/code&gt; class to implement this new interface.  Visual Studio 2008 and &lt;a href="http://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt; make this easy.&lt;/p&gt;
&lt;p&gt;This will let us change our test later to use a &lt;strong&gt;fake&lt;/strong&gt; version of &lt;code&gt;IEmailService&lt;/code&gt; instead of the real one.&lt;/p&gt;
&lt;h2 id="decouple-and-invert-your-dependencies"&gt;Decouple and Invert your Dependencies&lt;/h2&gt;
&lt;p&gt;The next problem is we're creating an instance of the &lt;code&gt;EmailService&lt;/code&gt; class in the &lt;code&gt;ProcessOrder&lt;/code&gt; method.  Anytime you use &amp;quot;new&amp;quot; in your code, you're probably introducing a dependency and reducing testability.&lt;/p&gt;
&lt;p&gt;The fix is to let the &lt;strong&gt;caller&lt;/strong&gt; create the instance and tell the class or method being called which instance to use.  I am using a private field with constructor injection to set the field instance.  Note we're also now coding to the interface &lt;code&gt;IEmailService&lt;/code&gt; instead of the instance &lt;code&gt;EmailService&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here's the full Order method using the private field to call the &lt;code&gt;SendOrderConfirmationEmail&lt;/code&gt; method on &lt;code&gt;IEmailService&lt;/code&gt; inside the &lt;code&gt;ProcessOrder&lt;/code&gt; method.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class Order
{
  private readonly IEmailService _emailService;
&lt;p&gt;public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public decimal Total { get; set; }&lt;/p&gt;
&lt;p&gt;public Order(IEmailService emailService)&lt;/p&gt;
&lt;p&gt;public bool ProcessOrder()
{
var result = false;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Validate order
if (!string.IsNullOrEmpty(this.Email) &amp;amp;amp;amp;&amp;amp;amp;amp; this.Total &amp;amp;gt; 0)
{
  // Send order confirmation email
  //var emailService = new EmailService(); // Created outside this class now
  var emailSendResult = _emailService.SendOrderConfirmationEmail(this);

  if (emailSendResult == true)
  {
    // Do more order processing...

    result = true;
  }
}

return result;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Dependencies can be very hard to spot, but it's critical to tease them out of your code to increase testability.  They can even come from things as innocuous as &lt;a href="http://msdn.microsoft.com/en-us/library/system.datetime.aspx"&gt;DateTime&lt;/a&gt;.  If you're code relies on &lt;code&gt;DateTime.Now&lt;/code&gt;, how will you write unit tests for your logic without changing your system clock when you run the test?  It's simpler to have the caller pass in the &lt;code&gt;DateTime&lt;/code&gt; value and have the method do the calculations based on whatever value it is given.&lt;/p&gt;
&lt;h2 id="make-a-fake"&gt;Make a Fake&lt;/h2&gt;
&lt;p&gt;Now that we've got testable code, we can make a fake &lt;code&gt;EmailService&lt;/code&gt; and update our test.&lt;/p&gt;
&lt;p&gt;First, create the &lt;code&gt;FakeEmailService class&lt;/code&gt; implementing the &lt;code&gt;IEmailService&lt;/code&gt; we created earlier.  We need the &lt;code&gt;SendOrderConfirmationEmail&lt;/code&gt; method to return true to simulate an email being successfully sent.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public class FakeEmailService : IEmailService
{
  public bool SendOrderConfirmationEmail(Order order)
  {
    return true;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could also use a mocking framework like &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; or &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt; for this, but a homemade fake is easy, too.&lt;/p&gt;
&lt;p&gt;Now we're ready to update our test to use the fake and inject it into the &lt;code&gt;Order&lt;/code&gt; constructor:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;[Test]
public void Should_return_true_when_using_good_order_values()
{
    // Arrange
    var emailService = new FakeEmailService();
    order = new Order(emailService);
    order.FirstName = &amp;quot;Joe&amp;quot;;
    order.LastName = &amp;quot;Wilson&amp;quot;;
    order.Email = &amp;quot;real_email_address@volaresoftware.com&amp;quot;;
    order.Total = 123.00m;
&lt;pre&gt;&lt;code&gt;// Act
var result = order.ProcessOrder();

// Assert
Assert.That(result, Is.True);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="last-step"&gt;Last step&lt;/h2&gt;
&lt;p&gt;We've refactored the Order class so the caller sends the &lt;code&gt;IEmailService&lt;/code&gt; instance to it.  That makes sense for the test, but what about the real code?&lt;/p&gt;
&lt;p&gt;I typically use an &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;IOC container&lt;/a&gt; like &lt;a href="https://structuremap.github.io/"&gt;Structure Map&lt;/a&gt; or &lt;a href="http://www.castleproject.org/"&gt;Castle Windsor&lt;/a&gt; to hold and resolve an in-memory dictionary of interfaces and class instances.  You wire it up at application startup and when you call something that needs &lt;code&gt;IEmailService&lt;/code&gt;, it creates an instance of &lt;code&gt;EmailService&lt;/code&gt; for you.&lt;/p&gt;
&lt;p&gt;If you're working with legacy code and can't use and IOC container, you also can add a no arg constructor like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public Order() : this(new EmailService())
{
}
&lt;p&gt;public Order(IEmailService emailService)
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Your legacy code keeps calling the no arg constructor like it used to, and any new code and your test code use the constructor with &lt;code&gt;IEmailService&lt;/code&gt; dependency passed in.&lt;/p&gt;
&lt;h2 id="wrap-up"&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;If you code isn't testable, you won't test it.  If you're working with legacy code or writing tests after coding, you can use these techniques to pull out external dependencies so they can be faked for testing.&lt;/p&gt;
&lt;p&gt;You can have it all: testable code, unit tests around that code, and no broken legacy code. Mmmm.Testability. Drink it in!&lt;/p&gt;
</description>
      <pubDate>Sun, 07 Mar 2010 06:30:20 Z</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="true">https://volaresoftware.com/nl/technical-posts/reusing-kendo-ui-settings-to-make-your-app-s-ui-patterns-consistent</guid>
      <link>https://volaresoftware.com/nl/technical-posts/reusing-kendo-ui-settings-to-make-your-app-s-ui-patterns-consistent</link>
      <title>Reusing Kendo UI settings to make your app's UI patterns consistent</title>
      <description>&lt;p&gt;Kendo UI components have LOTS of settings and options. For most web apps, you'll pick a set of options and stick with common UI patterns throughout the app.&lt;/p&gt;
&lt;p&gt;Will your app's grids use paging or infinite scrolling of grid data? If paging, how many records should you show on each page? Which UI style should your app's date pickers use? What format should your app's numeric text boxes use by default - whole number or decimal?&lt;/p&gt;
&lt;p&gt;One technique for sharing common settings across all Kendo UI components within your app is to set up your defaults and wrap with the jQuery extend function.&lt;/p&gt;
&lt;p&gt;Here is a date picker:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import $ from &amp;quot;jquery&amp;quot;;
import &amp;quot;@progress/kendo-ui/js/kendo.datepicker&amp;quot;;
&lt;p&gt;export function extend(settings) {
const commonSettings = {
componentType: &amp;quot;modern&amp;quot;
};&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return $.extend(true, {}, commonSettings, settings);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is a drop down list where the server returns a &lt;code&gt;text&lt;/code&gt; and a &lt;code&gt;value&lt;/code&gt; field to populate the drop down:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import $ from &amp;quot;jquery&amp;quot;;
import &amp;quot;@progress/kendo-ui/js/kendo.dropdownlist&amp;quot;;
&lt;p&gt;export function extend(settings) {
const commonSettings = {
dataSource: {
sort: [{ field: &amp;quot;text&amp;quot; }] // Sort by the field called &amp;quot;text&amp;quot; every time
},
dataTextField: &amp;quot;text&amp;quot;, // Assume the text field is always called &amp;quot;text&amp;quot;
dataValueField: &amp;quot;value&amp;quot;,  // Assume the value field is always called &amp;quot;value&amp;quot;
optionLabel: &amp;quot;- Please Select -&amp;quot;,
autoBind: false, // Don't bind the drop down on initialization
valuePrimitive: true // Use primitives for values, like 123, not objects, like { value: 123, text: &amp;quot;Active&amp;quot; }
};&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return $.extend(true, {}, commonSettings, settings);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is a numeric text box for positive whole numbers:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import $ from &amp;quot;jquery&amp;quot;;
import &amp;quot;@progress/kendo-ui/js/kendo.numerictextbox&amp;quot;;
&lt;p&gt;export function extend(settings) {
const commonSettings = {
min: 0,
step: 1,
decimals: 0,
round: true,
format: &amp;quot;{0:0}&amp;quot;
};&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return $.extend(true, {}, commonSettings, settings);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Use these default app settings by importing the module, referencing the &lt;code&gt;extend&lt;/code&gt; method exported by that module, then using, adding to, or overriding the UI defaults needed for that date picker, drop down list, or numeric text box:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import * as datePicker from 'common/datePicker';
import * as dropDownList from 'common/dropDownList';
import * as numericTextBox from 'common/numericTextBox';
&lt;p&gt;$(&amp;quot;#myDatePicker&amp;quot;).kendoDatePicker(datePicker.extend()); // No change to default values
$(&amp;quot;#myDropDown&amp;quot;).kendoDropDownList(dropDownList.extend({
dataSource: &amp;quot;/api/myDropDown&amp;quot; // Add to, rather than change, default values
}));
$(&amp;quot;#myNumericTextBox&amp;quot;).kendoNumericTextBox(numericTextBox.extend({
min: -100 // Override default values
}));
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This is a good way to have a consistent UI without always copy-pasting key-value pairs across files.&lt;/p&gt;
&lt;p&gt;It also allows you to quickly change how your app looks and works across pages and components with a change to the common Kendo UI defaults.&lt;/p&gt;
</description>
      <pubDate>Sun, 14 Feb 2021 07:44:17 Z</pubDate>
    </item>
  </channel>
</rss>