Posts Tagged ‘ASP.NET’

TryUpdateModel and unknown model-types

Thursday, May 20th, 2010

TryUpdateModel does not work on types not known at compile time. For example when creating an object through the Activator.CreateInstance()

To remedy this use this snippet of code:

public static class ControllerHelpers
{
  public static bool TryUpdateGenericModel(this Controller controller, object model)
  {
    var param = new Type[] { model.GetType() };
    var controllerType = controller.GetType();
    var controllerMethods = controllerType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
    var TUMmethod = controllerMethods.First(x => x.Name.StartsWith("TryUpdateModel") && x.GetParameters().Count() == 1);
    var TUMgeneric = TUMmethod.MakeGenericMethod(param);
    var result = TUMgeneric.Invoke(controller, new object[] { model });
    return (bool)result;
  }
}

And in your controller when trying to update your model, use it like this:

var emptyModelObject = Activator.CreateInstance(modelType); // whichever way you get it doesn't really matter.
var result = this.TryUpdateGenericModel(modelObject);

nginx as a proxy for Visual Studio

Tuesday, January 26th, 2010

I guess most people doing ASP.NET web development in Visual Studio (VS) have been frustrated by the fact that the development server in VS only wants to serve it’s content to the local machine. It is inaccessible from other computers on the network and impossible to reach from a Virtual Machine running alternative configurations of OS/browser. This is a pain in the ass when trying to debug something not working in another version of Internet Explorer than you have on your local machine.

We’ve been trying different approaches to circumvent this, using SSH tunnels and other similar technologies, without any luck. But this morning I came up with a solution: A local HTTP proxy in front of the development server. This way, anybody can access the proxy, and still all requests to the development server are local. I chose nginx (pronounced engine x) as the proxy. It’s free, open source and it only takes a couple minutes to get up and running.

Download

Currently, the most recent version of nginx for Windows is 0.8.32, and it is available for download here. It’s a simple zip file that just needs to be extracted. No installation is needed — the server runs directly from the uncompressed files.

Configuration

In the folder conf, there’s file called nginx.conf. This is the configuration file for nginx.

Around line 36 it says:

listen 80;
server_name localhost;

80 is the port number nginx is listening to. I have personally chosen to change this to 8080, as I already have a local Apache server running on port 80. But you can pick any port number you like, as long as it’s not in use.

Around line 43 it says:

location / {
root html;
index index.html index.htm;
}

Change this to:

location / {
#root html;
#index index.html index.htm;
proxy_pass http://localhost:xxxx;
}

Where xxxx is the port on which VS is running it’s development server. This changes from project to project, and even changes from time to time in a project. So this will need to be changed once in while.

Start and reload

nginx is started by double clicking the file nginx.exe, or by opening a command prompt, cd to the nginx folder and run the command start nginx.exe. If everything is fine (i.e. if you didn’t make any mistakes in the configuration), you will hereafter have 2 new processes (a master and a worker) running, both called nginx.exe.

If you need to reconfigure nginx (e.g. change to a new port VS has chosen to run it’s server at), afterwards you can reload nginx by running the command nginx -s reload from the nginx folder in command prompt.

Read more about start, reload and stop in the official documentation.

Access

The VS development server is now available — through nginx — at http://HOSTNAME:8080, where HOSTNAME is the network name (or IP address) of your computer, and 8080 is the port you chose to let nginx listen to in the configuration.

Happy external debugging.

Sig goddag til Pirat TV

Tuesday, September 1st, 2009

Efter 4-5 måneders udvikling lancerer vi i dag stolt Pirat TV. I virkeligheden lancerede vi allerede for et par måneder siden, men det var lidt i smug. I dag er den store dag med officiel lancering og alt hvad dertil hører.

Kort fortalt er Pirat TV Ungdomsredaktionens bud på en netbaseret platform for moderne og fremtidigt ungdoms-tv. Vi har droppet at sende på DR1 (vi fik alligevel kun skodsendetider) og koncentrerer os nu om at lave internetvenlige, klipformaterede ting, i troen på at unge fortsat vil rykke mere og mere over på net fra tv.

Bag den overvejende flash-baserede frontend gemmer sig en ASP.NET MVC-applikation som er forberedt til også at servere andre ting end blot Pirat TV. Så vi er klar til WORLD DOMINATION!

Det er vores første  MVC-applikation. MVC er ikke the framework to rule them all – personligt savner jeg mange ting der er til stede i andre web frameworks – men vi kan vist roligt sige: NØJ, hvor er det en befrielse fremfor at arbejde med det retarderede Web Forms fra ASP.NET.

På alle klipsider har vi – ligesom man kender fra fx. YouTube – en embed-kode liggende som man kan tage og putte ind på sit eget site. Vi er et par steder (1, 2) blevet hånet for vores “fortolkning” af embed. Og det er delvist fair. For resultatet af embed-koden er blot at der kommer et Pirat TV-logo, en thumbnail fra klippet og klippets titel med et link tilbage til klippet på Pirat TV.

Men kritikken er også lidt unfair. For vi har ikke gjort som vi har gjort fordi vi er inkompetente. Vi kunne sagtens lave rigtig embedding. Men desværre har vi på nuværende tidspunkt ikke rettighederne til at embedde vores indhold eksternt (selvom vi her på redaktionen rigtigt gerne ville). DR tør – modsat YouTube og andre – ikke køre efter princippet “hellere tilgivelse end tilladelse”. Så der er lige nogle jurasoldater der skal udkæmpe en vigtig krig før vi kan få lov.

Til gengæld er vores embedkode forberedt til at embedde rigtig video den dag vi får lov. Så hermed en opfordring til alle om at bruge embedkoden allerede fra i dag af. Så dukker der flot video op på jeres sites den dag rettighederne er på plads.

ViewState optimering

Monday, June 16th, 2008

Da jeg for mange år siden var en lille dreng der gik ude på DTU og lærte hvordan man blev ingeniør, var en af de ting jeg synes var rigtigt sjovt at hukommelsesoptimere. Præcis hvorfor ved jeg ikke, men det tiltalte mig på en eller anden måde rigtigt meget at få vredet lige otte bytes mere ud af et eller andet minimalt embedded system, eller at få en datastruktur til at fylde lige to bytes mindre pr. entry.

Det er mig en gåde hvorfor jeg dengang syntes at det var skægt, og efterhånden som jeg blev ældre lagde min fascination af den her helt særlige form for totur sig, og blev afløst af en langt mere naturlig foragt for den slags programmering. Ikke at jeg synes man skal svine unødigt med hukommelse, men inden for moderne udvikling så kan det simpelthen ikke være rigtigt at programmøren selv skal side og manuelt tilrette hver eneste datastruktur, og selv sidde og finde hver eneste lille ekstra byte ud af hukommelsen – og det ER selv følgelig heller ikke rigtigt. Med garbage collection, smartere compilere og nærmest uendelig performance og hukommelse så er det ikke noget programmører i dag nogensinde prøver at beskæftige sig med.

Derfor har det også overrasket mig pænt meget, når jeg tænker tilbage på hvad jeg har lavet den sidste uge. Jeg har siddet og kigget på lange, lange stackdumps, aflæst hvor meget hukkomelse hver enkelt object bruger, flyttet rundt på kode, tænkt datastrukturer om og klappet i mine små hænder hver gang jeg har sparet 15-20 bytes. Præcis som da jeg var en lille dreng på DTU – forskellen er bare at i dag hader jeg det som pesten.

Det jeg laver er at gå alle vores ASP.NET controls igennem og få styr på hvor meget de plads de bruger når de er serialiseret ud i ASP.NETs ViewState. 200 controls, hvoraf hveranden gemmer bare 100 bytes i viewstate giver 10kb i ViewState, og det bliver overført frem og tilbage mellem server og klient hvert eneste gang siden forsager et postback – og med moderne ting som AJAX og asynkrone postbacks, så kan det ske masser af gange i minuttet. I Skum 3 har vi nogen widgets (Skum fiduser) og hver gang de bliver flyttet melder de tilbage til serveren, at de bor et andet sted igennem et postback: Med et ViewState på 10kb skal man kun flytte en widget 50 gange, før man har overført en megabyte data. Ingen billeder, ingen ting, bare retursvar til serveren om hvor den her widget bor nu.

Med andre ord, hvis man ikke passer ekstremt meget på hvad man har i ViewState laver man meget, meget nemt den største og tungeste website nogensinde – uden at man får noget ekstra funktionalitet ud af det.

Så nu går jeg altså alle vore controls igennem en for en og sikrer mig at de ikke sviner i ViewState, ligesom programmørene i 1978 gik deres C eller Fortran kode igennem funktion for funtion, og datastruktur for datastruktur for at sikre sig de ikke svinede med hukommelsen. Jeg har lært mig følgende regler som alle folk burde følge når de udvikler ASP.NET controls:

  1. Det eneste der skal bo i ViewState er information som er direkte forsaget af en brugers handlinger, og ikke er gemt i databasen endnu.
  2. Alt, hvis værdi på nogensomhelst måde kan sættes før eller under en controls init-event skal sættes der. Efter Init event’et tracker ViewState og så bliver alting serialiseret ud til klienten.
  3. I UserControls skal alle værdier der overhovedet kan sættes i .ascx filen (som properties på et tag) sættes der. Den slags properties bliver sat før ViewState begynder og tracke, og derfor sviner de ikke i ViewState.
  4. Hvis man endelig ikke kan undgå at noget skal være i ViewState, så vær ekstremt omhyggelig med hvad du kommer derind. Alt andet end strings, bytes, bools og andre simple typer bliver serialiseret med en byteserializer der er ekstremt ueffektiv. Controls i ViewState er især super forbudt – brug ID’er i stedet. Overload hellere SaveViewstate og LoadViewstate en gang for meget end en gang for lidt.

ViewState kan være svært at forstå, og det er svært at læse sig frem til hvad det er og hvad det gør, hvis man kun bruger Microsofts dokumentation. Den her artikel er absolut den bedste jeg har set om ViewState og det bør være “required reading” for alle der har med ASP.NET at gøre:

Infinities Loop: Truly Understanding Viewstate

Et lille skridt for menneskeheden, men et stort skridt for mig

Monday, April 7th, 2008

Jeg har netop fået strikket min første ASP.NET Control sammen næsten uden hjælp. Den kan ikke alt hvad den skal kunne endnu, og den ser heller ikke helt ud som den skal. Men begge dele skal nok komme.

Den er ikke så satans avanceret: Det er bare en lille menu til – fx. – brugersider. Så som sådan er det ikke det vilde. Næh, det vilde ligger i at jeg endeligt, grundlæggende har forstået (og haft tid til at forstå) hvordan hele det her ASP.NET-cirkus fungerer.

Jeg er stadigt ikke vildt begejstret for det. Men det er heldigvis heller ikke det jeg får mine penge for at være.

Nå, men se den fine menu i aktion her:

Menu

Brug en font der ikke er installeret på serveren

Thursday, December 13th, 2007

Typisk når man laver et komponent der laver knapper, billeder, overskrifter m.m. gør man det ofte server-side for at kunne bruge en font der ikke er til stede på klineten.

Dette har dog ofte kun været muligt hvis man er i stand til at installere fonten på serveren – hvilket man langt fra altid kan.

Med .NET Framework kan dette dog løses med klassen PrivateFontCollection (som er i System.Drawing.Text namespacet).

PrivateFontCollection fontCollection = new PrivateFontCollection();
fontCollection.AddFontFile(Server.MapPath(“~/Fonts/TheSerif7.ttf”);
FontFamily fontFamily = fontCollection.Families[0];
Font font = new Font(fontFamily, 9F);

Dette kræver at man afvikler koden fra et sted man har adgang til et HttpContext object (f.eks. en HttpHandler eller et Page-objekt).

Hvis man ikke har det, eller ikke ønsker at have sine fonte liggende i sin webroot, kan man bruge en mere avanceret teknik – nemlig at embedde den direkte i sit Class Library’s Assembly (dll-fil). Dette gøres ved at tilføje font-filen til projektet og vælge and dens build action skal være “Embed Resource”.

Man kan få fat i fonten fra sin assembly med denne kode (man skal lave en Managed Pointer – fancy pansy):

fontCollection = new PrivateFontCollection();
using (Stream stream = this.GetType().Assembly.GetManifestResourceStream(“DR.Skum.Resources.Fonts.TheSerif7.ttf”))
{
      Byte[] buffer = new Byte[stream.Length];
      stream.Read(buffer, 0, (Int32)stream.Length);
      IntPtr PtrData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(byte)) * buffer.Length);
      Marshal.Copy(buffer, 0, PtrData, buffer.Length);
      fontCollection.AddMemoryFont(PtrData, buffer.Length);
}
fontFamily = fontCollection.Families[0];
font = new Font(fontFamily, 9F);

Fordelen ved metode 2 er at man får nemmere deployment – eftersom TTF filen sidder sammen med DLL filen

PNG This!

Tuesday, December 11th, 2007

Nu har jeg endelig efter at have skubbet problemet i næsten 3 år, igennem 2 jobs, løst problemet med at jeg ikke har kunne streame en PNG ud på en HTTP Stream (GDI+ har givet en intern framework fejl).

Løsningen skal åbenbart findes i hvordan PNG formattet virker – hele PNGen skal være genereret før den kan skrives til en stream.

Til at sikre dette kan man skrive PNG’en til en MemoryStream, og derefter skrive den MemoryStream til Response.OutputStream.

AsyncButtonResult async = result as AsyncButtonResult;
using (MemoryStream ms = new MemoryStream())
{
     async.img.Save(ms, ImageFormat.Png);
     ms.WriteTo(async.context.Response.OutputStream);
}

Kode eksemplet ovenover er fra en IHttpAsyncHandler  der genererer knapper der skal bruges på SKUMs nye community.