Filed Under (C# code) by Christiaan van Bergen on April-22-2009
Ik wil via een webpagina een bestand (afbeelding) uploaden en deze tonen zodra ik hem binnen heb.
Ik maak een pagina met daarop een Asp:FileUpload control , Asp:Image control en een submit button. Doel is, kies een bestand, druk op submit (ik krijg een PostBack), en de afbeelding wordt getoond. Het probleem is echter, ik heb geen mogelijkheid om de FileContent direct te koppelen aan een Asp:Image.
Om de afbeelding te koppelen aan het Asp:Image control moet ik het control voorzien van een url naar de afbeelding. De eerste gedachte is dat ik de afbeelding op schijf moet hebben. Ja, dat werkt natuurlijk. Maar dat wil ik niet.
Een andere oplossing is, in de PostBack de byte[] van de FileUpload op te slaan in een Session object onder een bepaalde naam. De ImageUrl van de Asp:Image laten wijzen naar een nieuw te maken aspx pagina laten wijzen (ShowImage.aspx).
Deze ShowImage.aspx heeft de volgende code in zijn aspx.cs:
Dit heeft natuurlijk op deze wijze nogal wat security issues. Zo kan bijvoorbeeld een gogem figuur verschillende sessie waarden uitlezen. Deze zou je kunnen ondervangen door een wrapper object te maken met daarin de byte[] en specifiek in ShowImage.aspx uit te vragen of de sessie een object bevat van het wrapper Type.
Filed Under (C# code, CRM) by Christiaan van Bergen on April-16-2009
Om een dynamische (steeds wisselend) afbeelding op een report in Sql Server Reporting Services (SSRS) Report te plaatsen, zijn er verschillende mogelijkheden:
- een image ‘databound’ maken aan een veld in een dataset
- meerdere embedded images toevoegen en op basis van een stuk VBScript code bepalen welke getoond moet worden
- een url opgeven, zodat het report de image gaat ophalen
- een parameter opgeven met de waarde van de image
- (vast nog wel meer …..)
Over de laatste wil ik het hebben: ‘een parameter opgeven met de waarde van de image’
Maak in je report een ‘parameter’ aan: Ga naar de ‘properties’ van je Report en kies : ‘ReportParameters’. Klik op de elipsis. Voeg een parameter toe, zoals op de afbeelding hieronder (de naam mag uiteraard anders zijn)
Ga terug naar je Report en sleep een ‘image’ item op je report surface. Vul in de ‘properties’ van deze image de volgende gegevens in :
Bovenstaande zorgt ervoor dat de waarde die als parameter binnenkomt wordt vertaald naar een Byte[]. De ‘Source’ MOET op ‘Database’ staan. Een andere wijze lijkt niet te werken. Het gekozen MIMEType hoort eigenlijk te reageren op een stuk VBScript (dat nog niet is geschreven, maar dat komt nog wel) maar is voor nu hard op een PNG image gezet.
Belangrijk punt hier: de waarde die aan de parameter wordt meegegven is dus blijkbaar iets met ‘Base64′. Dit is een karakter-gebaseerde wijze van weergeven van bytes.
Stel je voor: voor dat de parameter wordt gevuld wordt er een plaatje gelezen en deze wordt van binair naar base64 geconverteerd. Dit gaat over de ‘lijn’. Het report zet dit weer om naar bytes en kan het weergeven.
Converteren van en naar Base64 gaat via: System.Convert.ToBase64String( <<byteArray>> ) en System.Convert.FromBase64String( <<base64String>> )
Filed Under (C# code) by Christiaan van Bergen on March-6-2008
Wanneer je in Visual Studio 2008 een Web Reference aanmaakt en je maakt gebruik van het .Net Framework 2.0 voor je project, dan krijg je exact dezelfde wizard als in Visual Studio 2005. Heb je echter een project gestart dat gebruik maakt van het .Net Framework 3.x, dan is de wizard anders (het heet zelfs Service Reference). Wat wanneer je een project maakt met het 3.x framework maar je wilt toch een web reference maken op de 2.0 manier?
Simpel, voeg een Service Reference toe. In de dialoog die zich opent klik je onderin op de knop "Advanced…".
In het scherm dat opent kies je voor "Add Web Reference…".
Het scherm dat nu verschijnt moet je herkennen als zijnde de wizard die je ook in de eerdere versies van Visual Studio had. Het toevoegen van een Web Reference.
De code die nu gegenereerd wordt is gebaseerd op .Net Framework 2.0. Maar wanneer je het project compileert, gaat het uiteraard wel tegen .Net Framework 3.x
Gisteravond vertelde ik bij de maandelijkse bijeenkomst van de dotNed gebruikersgroep over mijn ervaringen met Script# en haalde ik het inmiddels veel besproken Volta aan. Het was een prettige bijeenkomst waarbij zeker de mooie locatie een grote rol heeft gespeeld. InterAccess heeft als host wederom een erg goede indruk achtergelaten.
Ondertussen is inderdaad de aanzet gemaakt voor het schrijven van een codeproject.com artikel waarin Robertjan Tuit, Jasper Gilhuis en ik zullen beschrijven hoe je een projectstructuur zo opzet dat je op een eenvoudige wijze webcontrols kan schrijven met behulp van Script#. Matthijs Krempel (InterAccess) bracht ons op het idee om deze projectaanpak te plaatsen in een software factory en vervolgens te plaatsen op codeplex. Briljant plan! Eens zien hoe snel we hieraan toe komen.
Een ander project dat wij op Codeplex willen plaatsen, is de Script# compatibiliteitslibrary voor de Ajax Control Toolkit. Meer hierover zodra dit beschikbaar is en uiteraard alvast de uitnodiging om daaraan te zijner tijd mee te bouwen.
Zoals beloofd plaats ik mijn presentatie en gebruikte demos online en geef ik nog een opsomming van resources die van belang zijn.
Wanneer ik meer resources tegenkom, zelf maak of van jou te horen krijg, zal ik ze toevoegen aan de lijst welke je het eenvoudigst kan bekijken op mijn Links pagina.
Filed Under (C# code) by Christiaan van Bergen on January-22-2008
Zoals velen natuurlijk al weten kan je xml-data middels een stylesheet weergeven op een door jou gewenste manier. Je kan in de zgn. xslt gebruik maken van xpath queries en diverse transformaties. Maar op het moment dat je je niet zo’n held voelt op dit gebied dan moet het toch prettig zijn te weten dat je kan terugvallen op je vertrouwde C# (of andere .Net taal).
Voordat je je eigen code vanuit xslt kan aanroepen moet je uiteraard wel wat voorbereidend werk verrichten.
Laten we eens kijken naar onderstaande code. Deze method Transform krijgt een string die de xml data en een string die de stylesheet bevat. Deze twee worden samengevoegd en het uiteindelijke resultaat wordt als string teruggegeven.
public static string Transform(string xmlData, string xslStylesheet)
{
TextReader textreaderxml - new StringReader(xmlData);
XmlTextReader xmlreaderxml = new XmlTextReader(textreaderxml);
TextReader textreaderxsl = new StringReader(xslStylesheet);
XmlTextReader xmlreaderxsl = new XmlTextReader(textreaderxsl);
XPathDocument xpathdocument = new XPathDocument(xmlreaderxml);
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xmlreaderxsl);
StringBuilder sb = new StringBuilder();
TextWriter tw = new StringWriter(sb);
XsltArgumentList args = new XsltArgumentList();
args.AddExtensionObject(“http://voorbeeld.xslt.nl/calculatie”,
new XsltCalculatie());
xslt.Transform(xpathdocument, args, tw);
return sb.ToString();
}
De uiteindelijke transformatie van de xml volgens de stylesheet gebeurt in regel 18. Maar daar voor (regel 4) wordt een verwijzing gemaakt naar http://voorbeeld.xslt.nl/calculatie. Dit is een utility class geschreven in C# die de functie Round bevat. (Toegegeven, dit is natuurlijk niet spannend)
public Decimal Round(Decimal a, int b){ return Math.Round(a, b);}
Deze C# code wordt in regel 17(-18) in de Transform method toegevoegd aan de stylesheet als zijnde de plek waar gekeken moet worden voor elke verwijzing naar http://voorbeeld.xslt.nl/calculatie (ofwel Local)
De uiteindelijke output van de method Transform en het gewenste resultaat:
Filed Under (C# code) by Christiaan van Bergen on January-14-2008
Zo af en toe ruim ik mijn harde schijf eens op. Verplaats wat bestanden in mappen met een wat meer toepasselijke naam, wis wat rommel, defragmenteer hier en daar wat. Je kent het wel. Wat gebeurt er echter wel eens, ben je net lekker bezig, kan je sommige bestanden niet verwijderen omdat ze gelocked zijn door een bepaald proces of erger nog, de bestandsnaam is van dien aard dat je het bestand niet kan verwijderen. Deze laatste noem ik voor het gemak maar ’stupid files’.
Wat blijkt nu, in Windows verkenner kan je bestanden niet verwijderen omdat ze karakters bevatten die niet mogen of de naam is simpelweg te lang. De manier om deze bestanden alsnog te verwijderen is gebruik te maken van de oude 8.3 notatie (je kent het wel NHJ_87~1.TXT bijvoorbeeld). Om een 8.3 notatie te zien, kan je het commando dir /x gebruiken. Vervolgens gebruik je het command del <file> om het bestand te verwijderen.
Wel jammer dat er vaak zoveel bestanden staan dat het een tijdrovende taak wordt om dit bestand voor bestand uit te voeren. Tja, dan maar een klein proggie schrijven die dit voor je doet.
Een kleine console application met daarin alle bestanden op te sommen moet al voldoende zijn, ware het niet dat .Net niet het 8.3 filename formaat ondersteunt. Hiervoor moet je een dllImport uitvoeren op de kernel32.dll.
[DllImport("kernel32.dll")]
static extern int GetShortPathName(string longPath, StringBuilder buffer, int bufferSize);
...
StringBuilder buffer = new StringBuilder(256);
GetShortPathName(file, buffer, buffer.Capacity);
string shortfilename = buffer.ToString();
Om direct aan de slag te gaan met het deleten van die stupid files, kan je . De (eenvoudige) sourcecode van dit tooltje heb ik hier voor je beschikbaar.
Mocht je nou toch nog locked files tegenkomen, dan is misschien wat voor je. geeft je een extra optie in je rechtermuis-menu om een bestand te ‘unlocken’. Wel handig.
Filed Under (C# code) by Christiaan van Bergen on January-3-2008
In een post van vorig jaar december, meldde ik dat ik een artikel op codeproject.com had geplaatst over een DataSet te vullen via bijvoorbeeld een CSV bestand. Mijn aandacht werd hier weer op gevestigd door een vraag van Matt Krei. Hij vroeg me wat specifieke zaken hoe hij bepaalde opmaak middels reguliere expressies kon filteren.
Filed Under (Code algemeen, C# code) by Christiaan van Bergen on December-24-2007
Zojuist heb ik een klein artikel geplaatst op codeproject waarin ik een manier beschrijf hoe ik met reguliere expressies een csv-bestand omzet naar een Dataset. Hoewel er uiteraard vele manieren zijn om met csv-bestanden om te gaan, heeft deze code mij al enkele keren uit de brand geholpen.
Filed Under (C# code, Script#) by Christiaan van Bergen on July-16-2007
Zoals ik in een vorige post al opmerkte, gebeurt het wel eens dat een Script# compile ogenschijnlijk werkt. Uiteindelijk blijkt dat een groot deel van de compiler output niet is weggeschreven in het resulterende Javascript bestand. Om er voor te zorgen dat je toch een compiler melding krijgt heb ik hier een voorbeeld van een Custom MsBuild Task die je kan gebruiken.
Filed Under (C# code, Script#) by Christiaan van Bergen on July-4-2007
Nu ik al een tijdje Script# gebruik en het anderen ook in hun schoot gooi, kon het niet uitblijven dat er bugs boven komen drijven. Zo kreeg een collega van mij de compiler melding: “Numeric constant overflow“. Dit trad op plekken op waar code stond zoals het eenvoudige:
privatedouble a = 3.4;
Na wat speurwerk vond ik een soortgelijke bugmelding op de site van Nikhilk Kothari. En ook bij ons kwam deze melding voort uit het probleem van landinstellingen die verschillen per werkstation. Mijn collega had zijn landinstellingen op nederlands staan en ik op engels.
De Script# compiler ssc.exe (versie 0.3.0.0) blijkt nog niet goed om te gaan met afwijkende landinstellingen.
Nu kan je natuurlijk dit probleem snel oplossen door de instellingen op engels te zetten en vrolijk doorgaan met compilen. Nou ja, dit lijkt niet de oplossing die men wil horen. Een andere oplossing is een Custom MsBuild Task te maken en deze ervoor te laten zorgen dat de CurrentCulture van de huidige Thread op CultureInfo(”en-US”) wordt gezet. Deze custom task moet dan elke keer voor de compile worden uitgevoerd, et voila.
Plak de volgende regels onderin je script# project file:
De assembly envTask.dll bestaat uit de volgende code:
using System;
using System.Globalization;
using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace envTask
{
publicclass SetLocalEnglish : Task
{
publicoverridebool Execute()
{
Thread.CurrentThread.CurrentCulture =
new CultureInfo(“en-US”);
returntrue;
}
}
}
Toegeven, het is niet de meest elegante manier, maar toch wat mooier dan elke keer handmatig je regional settings aan te passen. Nu maar wachten op een versie van Script# waar dit in is opgelost.