21 september 2012

ASP.NET validatie in VS 2012 werkt niet meer?

Als je gewend bent om met de validatiecontrols te werken in ASP.NET, zou je wel eens voor verrassingen kunnen komen te staan. Beschouw de volgende snippet gecreëerd in een “New Empty Website” met VS 2012:

<form id="form1" runat="server">
<div>
    <asp:Label Text="Vul iets in: " runat="server" />
    <asp:TextBox ID="InputTextBox" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
        runat="server"
        ErrorMessage="U heeft niets ingevuld!"
        ControlToValidate="InputTextBox">
    </asp:RequiredFieldValidator>
    <br />
    <asp:Button ID="OKButton" runat="server" Text="Klik" />
</div>
</form>

Als je deze pagina opent in een browser en op de knop klikt, krijg je volgende foutmelding:

ServerError

Als je echter bestaande websites opent die gemaakt zijn met vroegere edities van Visual Studio, blijkt alles perfect te werken. Hoe komt dit nu?

Wel, zoals je weet gaan de validation controls zowel op de server als op de client (via gegenereerde JavaScript code) de validatie uitvoeren. Als je veel van deze controls op de pagina hebt staan, zal de JavaScript code groter en groter worden om uiteindelijk het laden van de pagina te vertragen. Dit is in feite gelijkaardig aan het ViewState probleem. Daarom is het raadzaam om bij nieuwe sites de validatie uit te besteden aan het JQuery framework. Echter dit is bij een bestaande website niet aanwezig en moet manueel toegevoegd worden.

We stellen drie oplossingen voor om dit probleem te verhelpen:

  1. Nieuwe websites draaien op een vorige versie van het .NET framework
  2. Nieuwe websites draaien op het meest recente .NET framework, maar via klassieke validatie
  3. Nieuwe websites draaien op het nieuwe validatieframework gebaseerd op JQuery

Nieuwe websites draaien op een vorige versie van het .NET framework

Dit is wellicht de eenvoudigste oplossing. Verander het web.config bestand van je website en vermeld 4.0 als versie nummer in plaats van 4.5:

<system.web>
  <compilation debug="true" targetFramework="4.0"/>
  <httpRuntime targetFramework="4.0"/>
</system.web>

Nieuwe websites draaien op het meest recente .NET framework, maar via klassieke validatie

Een nadeel van de vorige oplossing is dat je het meest recente .NET framework negeert. Je kan dus geen gebruik maken van de meeste recente performantieverbeteringen. Daarom is het wellicht beter om het frameworknummer te behouden, maar terug te vallen op de oude validatiemethode. Ook dit kan je instellen in het web.config bestand. Je voegt hiervoor een <appsettings> element toe met de volgende subelementen:

<?xml version="1.0"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5"/>
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
    <add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
  </appSettings>
</configuration>

Nieuwe websites draaien op het nieuwe validatieframework gebaseerd op JQuery

De beste oplossing, maar ook de meeste complexe, is het toevoegen van JQuery aan je website. Dit doen we in een paar stappen:

Stap 1: voeg via “Add New Item” een “Global Application Class” toe. Dit voegt een bestand genaamd Global.asax toe aan je project.

Stap 2: voeg volgende code toe, de methode headers zijn al voor jou aangemaakt:

void Application_Start(object sender, EventArgs e) 
{
    ScriptResourceDefinition jQuery = new ScriptResourceDefinition();
    jQuery.Path = "~/scripts/jquery-1.7.2.min.js";
    jQuery.DebugPath = "~/scripts/jquery-1.7.2.js";
    jQuery.CdnPath = "http://ajax.microsoft.com/ajax/jQuery/jquery-1.7.2.min.js";
    jQuery.CdnDebugPath = "http://ajax.microsoft.com/ajax/jQuery/jquery-1.7.2.js";
    ScriptManager.ScriptResourceMapping.AddDefinition("jquery", jQuery);
}

Deze code registreert het JQuery framework in je applicatie. JQuery wordt lokaal benaderd (in een scripts map) maar in een productieomgeving via de website van Microsoft zelf (via het CdnPath oftwel Content Delivery Network).

Stap 3: download de twee js-bestanden en voeg ze toe aan het project. Je project heeft dan volgende layout:

solution

Verwijder nu eventuele sporen van de vorige twee oplossingen, en run je programma. Je zal vaststellen dat validatie nu opnieuw werkt en dat het JQuery framework gebruikt wordt (rechtsklik: View Source).

Referenties:

19 februari 2012

Gallio draaien onder 64bit Windows

Gallio is een testautomatisatietool waarmee je MBUnit testen kan runnen. Spijtig blijkt de 64bit installatie niet te werken. Een unit test faalt immers met een BadImageFormatException, wat betekent dat er een x86 dll geladen wordt in een x64 proces.

Om dit op te lossen, volgende truc (gevonden op het Gallio forum):

  • Download de x86 installer, doe een typische installatie
  • Onder C:\Program Files (x86)\Gallio\bin hernoem:
    • Gallio.Host.exe naar Gallio.Host.x64.exe
    • Gallio.Host.x86.exe naar Gallio.Host.exe

Runnen vanaf Icarus lukt nu wel…

16 februari 2012

Mijn favoriete iPad apps

Dit zijn de apps die ik dagdagelijks of toch heel regelmatig gebruik in het kader van professionele activiteiten.

Dropbox

Deze app is onontbeerlijk om met andere apps zoals GoodReader vlot te kunnen werken. Door de iPad te koppelen met een Dropbox account, heb je een virtuele schijf “in de cloud” om je bestanden mee te synchroniseren.

GoodReader

De beste PDF lezer, tout court. Zeer handig: markeringen. Bovendien maakt de laatste update het mogelijk om ook zeer kleine notities in de marge te maken.

Notability

Na enkele maanden gewerkt te hebben met Note Taker HD (van Dan Bricklin, nota bene de uitvinder van VisiCalc, de voorloper van Excel!), ben ik overgeschakeld op Notability, vooral vanwege de gelikte UI en uitgebreide features. Vooral het kunnen mengen van getikte tekst en geschreven notities is erg handig.

Evernote

Notities synchroniseren, zowel op PC, Mac als iPad. Dit gebruik ik eerder voor snelle reminders of ToDo-lijstjes.

Instapaper

Deze app kan artikelen op het web vrijmaken van reclame en van een fraaie “krantenopmaak” voorzien. In combinatie met een Chrome plugin maak je de ultieme leestool: een leuk artikel dat je op je PC ontdekt, markeer je naar je leeslijst en ‘s avonds in de zetel lees je alles met de iPad op schoot.

Een gelijkaardige app die ik vroeger gebruikte: Read It Later

Reeder

Deze app is te vergelijken met Instapaper: het kan artikelen transformeren naar een fraai, leesbaar formaat. Echter de artikelen zelf zijn afkomstig van je Google Reader account.

Zite en Flipboard

Twee apps die het mogelijk maken om op basis van allerhande voorkeuren (Google Reader, Twitter, Facebook, enz.) een magazine “op maat” te maken.

Discover

Artikelen opzoeken op Wikipedia

ScreenChomp

Van de makers van Camtasia. Met deze tool kan je eenvoudige lesjes opnemen en voorzien van live getekende illustraties op de iPad.

DisplayLink

Je iPad uitbreiden als tweede scherm van je PC.

Foto en Video

2 januari 2012

Code omzetten van C# naar VB

Telerik heeft een online tool om C# naar VB om te zetten (en vice versa). Alhoewel dit zeker geen foutloze omzettingen oplevert (Handles clauses worden niet omgezet, sommige klassen zijn niet gekend e.d.), kan het zeker handig zijn om de hoeveelheid “overtikwerk” de reduceren.

Andere omzetters:

Let op: geen enkele van deze sites kan je programma in zijn geheel, foutloos vertalen. Je zal altijd zelf de code moeten nalezen en verbeteren!

9 november 2011

Over lijnen en nieuwe lijnen

In Visual Basic kan je op veel manieren een nieuwe lijn beginnen, bijvoorbeeld:

MessageBox.Show("Dag " + vbNewLine +
                "Meneer, " + Environment.NewLine +
                "Alles " + ControlChars.NewLine +
                "Naar wens?")

Vooral de klasse ControlChars is handig, want die bevat ook nog handige properties om tabs, formfeeds, … toe te voegen.

Wil je bovenstaand voorbeeld omzetten naar C#, dan blijven twee opties over:

MessageBox.Show("Dag \r\n" +
                "Meneer " + Environment.NewLine +
                "Alles \n" +
                "Naar wens?");

Ofwel werk je met Environment.NewLine, dan voeg je het nieuwelijn-teken toe dat voor het platform (in mijn geval Windows 7) gangbaar is. Ofwel werk je met de codes die vanuit de C-taal gegroeid zijn: \r\n is voor windowsplatformen het nieuwelijnteken voor tekstbestanden, \n is dat voor unixvarianten. Dit laatste werkt echter wel voor het voorbeeld hierboven.

En wat als je toch wil volharden en gebruik wil maken van ControlChars? Wel, dan moet je in eerste instantie de namespace Microsoft.VisualBasic toevoegen aan je C#-project. Dit kan door te rechtsklikken in je project op References en vervolgens via Add Reference het bestand Microsoft.VisualBasic.dll toe te voegen. Vervolgens importeer je deze namespace bovenaan in je bestand:

using Microsoft.VisualBasic;

En nu kan je deze klasse gebruiken in je C#-programma. Belangrijk nadeel: je moet een hele assembly (dll) toevoegen en laden in het geheugen omwille van slechts één klasse. Daarom kan je eventueel de raad uit dit artikel volgen en je eigen ControlChars maken, eventueel in een aparte namespace (bv. KrisHermans.Utils):

namespace KrisHermans.Utils
{
    public class ControlChars
    {
        public const string CrLf = "\r\n";
        public const string NewLine = Environment.NewLine;
        public const char Cr = (char)13;
        public const char Lf = (char)10;
        public const char Back = (char)8;
        public const char FormFeed = (char)12;
        public const char Tab = (char)9;
        public const char VerticalTab = (char)11;
        public const char NullChar = (char)0;
        public const char Quote = (char)34;
    }
}

8 november 2011

Tijdsduur meten van bewerkingen

Stel dat je in een programma de duur van een operatie wil meten, bijvoorbeeld:

  • hoelang het duurt om een bestand in te lezen;
  • hoelang een databasebewerking duurt;
  • hoelang het tekenen van een complexe figuur duurt;

Een voor de hand liggende aanpak zou zijn om gebruik te maken van twee instanties van DateTime en hiervan het verschil (een TimeSpan object) af te drukken, zoals:

DateTime start = DateTime.Now;
FooMethodToMeasure();
DateTime stop = DateTime.Now;
Console.WriteLine("Duur {0} msec", (stop - start).TotalMilliseconds);

Deze manier van werkwijze zou echter niet nauwkeurig zijn (bron 1, bron 2), en daarom gebruik je beter de StopWatch klasse, die rechtstreeks via het besturingssysteem een timer voorziet. Let op: je moet wel de System.Diagnostics namespace importeren.

Stopwatch watch = new Stopwatch();
watch.Start();
FooMethodToMeasure();
Console.WriteLine("Duur {0} msec", watch.ElapsedMilliseconds);
watch.Stop();

31 oktober 2011

Predikaten met C#

Predikaten (Engels: Predicate) verkorten vaak het programmeerwerk omdat ze het zelf schrijven van herhalingsstructuren overbodig maken. Ze komen handig van pas bij het zoeken. In plaats van zelf lussen te schrijven, gebruik je een ingebouwde zoekmethode zoals Array.Find of Array.FindAll en kan je via predikaten zelf je zoekcriteria “inpluggen”.

Vanuit de logica weet je wellicht dat een predikaat is een bewering is die waar of onwaar is. In C# is een predikaat een speciale methode (een delegate) die true of false oplevert. Het volgende voorbeeld is een predikaat die onderzoekt of een woord een palindroom is: achterstevoren gelezen blijft het woord hetzelfde.

public bool IsPalindroom(string woord)
{
    // omzetten naar karakterarray
    char[] karakters = woord.ToCharArray();
    // omdraaien
    Array.Reverse(karakters);
    // opnieuw naar string omzetten
    string omgekeerd = new string(karakters);
    // vergelijken
    return omgekeerd == woord;
}

Stel nu dat je een lijst van woorden hebt die je wil onderzoeken of het palindromen zijn:

private List<string> woordenLijst = new List<string>();

...

woordenLijst.Add("zeven");
woordenLijst.Add("lepel");
woordenLijst.Add("koekoek");
woordenLijst.Add("racecar");
woordenLijst.Add("racewagen");
woordenLijst.Add("topkookpot");

In plaats van zelf een for-lus te schrijven en één voor één de methode toe te passen, gebruik je de Array.FindAll-methode en voorzie je via het predikaat een zoekcriterium:

List<string> palindromen = woordenLijst.FindAll(IsPalindroom);

MessageBox.Show("gevonden palindromen: " +
                String.Join(", ", palindromen.ToArray()));

De lus is er nu nog wel, Array.FindAll doorloopt alle woorden en evalueert ze via het predikaat, en stopt de resultaten in een nieuwe lijst. De hoeveelheid programmeerwerk is echter afgenomen en je redeneert meer op een declaratieve manier: je denkt meer naar over “wat heb ik nodig (IsPalindroom)?” in plaats van “hoe moet ik dat programmeren (lussen)?”.