This is an archived copy of all my blog posts which is irregularly updated.
  • Schizofrene code met node.js

    Allereerst een kleine update, op 1 oktober ben ik overgestapt van de de gevestigde ordenaar de wondere wereld van een startup. Niet alleen cultureel een verschil, maar ook een shift van .NET naar javascript, van Solr naar Redis, van SVN naar Git en van een Xeon workstation naar een Macbook Air. En nog belangrijker, van tafeltennis naar tafelvoetbal. Voor de mensen die niet 74 feeds in Google Reader hebben zitten: Cloud9 is een IDE, vergelijkbaar met Eclipse of Visual Studio, maar volledig draaiend in de browser; het is 'c9.io' intikken en gaan. Debugging, stack exploration, versiebeheer, you name it.

    Cloud9 is helemaal gebouwd in javascript, de client is gebouwd op APF, een open source framework voor web applicaties dat intern is ontwikkeld (heeft wel wat weg van Webforms). De backend draait op node.js, een event-based framework voor het schrijven van server side applicaties in javascript. Doordat node vanaf design geschreven is met het idee dat alle code event-driven moet werken heb je bijna geen blocking calls, en kunnen je threads sneller vrijgegeven worden: ergo: je kan meer requests handlen in je web server (gesimplificeerde weergave :)).

    Direct spelen met alle code
    Het leuke van werken aan een IDE is dat je features die je zelf handig vind gewoon kan inbouwen, zoals het met een klik laten klonen van de GitHub repository waar alle code samples uit de blogpost zitten. Ergo, om alle code uit deze post in hun echte context te zien en meteen te runnen klik hieren druk hierna op 'Run'.

    Continue reading »

  • "Dus euh, jij voert dan die huizen in?"

    "Maar, dat funda dat is toch wel af?"; "En dat doe je dan in je eentje neem ik aan?"; "Maak jij dan de foto's ofzo?"; zomaar een paar citaten die in de afgelopen 2,5 jaar zijn langsgekomen tijdens feestjes. Daarom het enige echte dev-overzicht van funda, met hopelijk een verklaring hoe we 20 man fulltime bezig kunnen houden met het knutselen aan de site. Kan ik daarna mooi bit.ly/neeikvoergeenhuizenin hierheen laten linken en op een t-shirt printen.

    Dus, hoeveel man loopt daar nou rond?
    In totaal bestaan we uit een man/vrouw of 50, waarvan er ~ 20 zich bezig houden met techniek, verdeeld over de volgende disciplines:

    • - 1 Groot leider
    • - 1 Software architect
    • - 2 Project managers
    • - 2 Testers
    • - 4 User experience designers (waarvan 1 groot leider)
    • - 1 Release manager / interne technisch applicatiebeheerder
    • - 10 Software developers, waarvan 7 intern, en 3 op locatie
    En daarnaast nog 3 applicatiebeheerders die voornamelijk voor ons werken, maar in dienst van onze applicatiebeheer-partij zijn.

    Maar, die site verandert toch nooit?
    Wel dus! Maar naast werk aan de sites funda.nl en fundainbusiness.nl hebben we ook nog een mobiele site, een iPhone app, een API, etc. De meeste tijd gaat echter zitten in ons makelaarportaal, de funda desk, waar we tools hebben voor het beheer van alle panden, media en kantoorgegevens. Omdat er voor producten die we daar aanbieden betaald moet worden, hebben we tevens een grote set aan business rules + aanverwante programma's die dit allemaal in goede banen leiden.

    Continue reading »

  • OAuth provider in .NET

    Om maar eens met een auto-analogie te komen: wanneer je (iets te onbetrouwbare) neefje iets uit de kofferbak van je auto moet halen, kan het een onveilig gevoel geven om hem direct de sleutel van je nieuwe A4 te overhandigen. Hij kan immers met die sleutel de auto starten, wegrijden en je no-claim om zeep helpen. En doet hij het niet nu, dan kan hij de sleutel kopiëren en het morgen proberen. Zou het niet mooi zijn om een sleutel te geven die alleen werkt op de kofferbak?

    Zelfde geldt voor 3rd parties die bij jouw data willen. Wanneer een applicatie alleen een lijstje met de huizen die jij bewaard op funda wil tonen, waarom zou je dan je gebruikersnaam en wachtwoord moeten geven? Daar kan de applicatie immers álles mee. Daarom: OAuth.

    An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.
    "If you're storing protected data on your users' behalf, they shouldn't be spreading their passwords around the web to get access to it. Use OAuth to give your users access to their data while protecting their account credentials."

    OAuth is dus een open protocol waarmee je 3rd parties toegang kan geven tot data van je gebruikers, zonder dat de gebruiker zijn wachtwoord met de 3rd party hoeft te delen.

    Continue reading »

  • Google Analytics in MVC

    Wanneer je iets in je MVC applicatie wil implementeren dat op (bijna) elke pagina terug moet komen, zoals Google Analytics, is dat een probleem dat lastig te tackelen is. Tactieken die ik in de praktijk heb gezien:

    • 1. Een baseclass maken met daarop de property 'GoogleAnalyticsTag', en alle Masterpages van dit model laten overerven. In de masterpage vervolgens <%= Model.GoogleAnalyticsTag %> doen.
    • 2. In je action 'ViewData["GoogleAnalyticsTag"]' zetten, om geen afhankelijkheid op alle modellen te hebben.
    • 3. Een losse action maken, en in je masterpage '<%=Html.RenderAction("GoogleAnalytics", "SomeController")%>'.
    3 is op zich de 'way-to-go' wat mij betreft, maar in tegenstelling tot 1. en 2. waar je in je action (of model) de GA tag zet heb je hier geen action context meer. En dus zag de code er in een van onze applicaties uit als:

    var url = HttpContext.Current.Request.Url.PathAndQuery;
    var tag = "";
    if (url.StartsWith("/koop/")) tag += "koop/";
    if (url.StartsWith("/huur/")) tag += "huur/";
    if (new Regex(@"/(koop|huur)/[\w-]+/\w+-\d+-[\w-]+/").Match(url).Success) {
        if (url.Contains("omschrijving")) tag += "object-omschrijving";
        if (url.Contains("fotos")) tag += "object-fotos";
    }
    // etc. etc. etc.

    Ononderhoudbaar, buggevoelig, en super hacky. Dat kan mooier!

    Continue reading »

  • iOS like Javascript photo gallery breakdown

    Vandaag een breakdown van de swipe-events in de photo gallery die we op onze mobiele website gebruiken. Verwacht niet een line-to-line breakdown, maar alleen de wijzigingen die hebben moeten doen om van onze more-or-less statische versie een versie te maken die swipe events ondersteunt.

    Let's get it started
    Omdat we gebruik willen maken van de 'touchmove' events gebruiken we een zelfgeschreven jQuery plugin die de interface iets handiger maakt: jquery.(s)wipe.js. De syntax voor deze plugin is:

    $('#een-element').wipe({
        wipeStart: /* */,
        wipe: /* */,
        wipeEnd: /* */
    });

    We kunnen aan deze events functies koppelen waardoor we alle logica voor het swipen op één plaats hebben.

    Continue reading »

  • Mobiele website live

    Voor een ieder die benieuwd was naar de touch-photogallery in deze post: we zijn live!
    http://100procentjan.nl/tweakers/mobiellive.png

    Beschikbaar op m.funda.nl, als je op je desktop kijkt is het aan te raden Chrome of een andere Webkit browser te gebruiken.

    Continue reading »

  • MIX Rollup, deel 1

    http://100procentjan.nl/tweakers/mix1.jpg
    Vorige week gespendeerd in Las Vegas voor de jaarlijkse Microsoft conferentie over User Interaction & Development: MIX. Hier een quick rollup van deze week!

    Zondag
    Aankomst, en een dag voor de conferentie het schokkende bedrag van $20.75 uit de 5-card poker machine gehaald met 4 azen!
    http://100procentjan.nl/tweakers/mix2.png

    Continue reading »

  • Output Cache Substitution (Donut Caching) in ASP.NET MVC 2 en 3

    Dynamische pagina's, of het nou in PHP, CGI of .NET is, hebben het internet gemaakt tot wat het nu is; maar hebben één groot nadeel. Voor elk request dient de pagina opnieuw te worden gegenereerd. Oplossing: cachen. Nu hebben we hiervoor in ASP.NET MVC het 'OutputCache' attribuut, dat je op elke Action kan zetten:

    // cache voor 1 minuut
    [OutputCache(Duration = 60, VaryByParam = "id")]
    public ActionResult Detail(int id) {
        // haal model op
        return View();
    }


    Probleem
    Iedereen die deze pagina de komende minuut opvraagt krijgt dezelfde versie te zien. Geen probleem voor pagina's die more-or-less statisch zijn, maar funest wanneer je bijvoorbeeld login informatie toont! Voeg je bijvoorbeeld Output caching toe aan het standaard ASP.NET MVC 2 project (In VS 2010 -> New Project -> ASP.NET MVC 2 Web Application) dan krijg je de volgende situatie:
    http://www.100procentjan.nl/tweakers/cache1.png
    Overzichtspagina, je ziet de 'last update' datum ter referentie

    http://www.100procentjan.nl/tweakers/cache2.png
    Nu loggen we in

    http://www.100procentjan.nl/tweakers/cache3.png
    De pagina wordt uit cache geladen (zie 'last update') maar er staat nog steeds een 'Log on' knop ipv. 'Logged in as jan'.

    Continue reading »

  • Validatie zoals UX het wil, met ASP.NET MVC 2

    De standaard validatie in MVC 2 gaat er vanuit dat je werkt met 'Validation messages' achter je tekstvelden, en een 'Validation summary' bovenaan je scherm. Dit werkt snel en out-of-the box, inclusief javascript validatie via jQuery Validate, en ook server side wanneer er geen javascript beschikbaar is (pic via).
    http://100procentjan.nl/tweakers/validationsummary.jpg
    Maar... wat als je UX-afdeling dit spuuglelijk vindt? Vandaar dat we bovenstaande gaan transformeren naar:
    http://100procentjan.nl/tweakers/validationnew.png

    Continue reading »

  • Video! Preview van touch-based mobile photo gallery

    Continue reading »