TryUpdateModel and unknown model-types

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);

Unit testing with Linq to SQL

February 9th, 2010

For some time we have been using Microsofts Linq-to-Sql as our ORM for several of our projects. It has some nice features, but it is also very different from just about every other ORM out there, and in a lot of ways it is troublesome and difficult to work with. One of the things that have been irritating me about Linq-to-Sql is that it’s central object, the datacontext, does not implement an interface and therefore it is difficult to unittest code that depends on it. Today I stumpled upon a solution to that problem in this post: http://www.iridescence.no/post/Linq-to-Sql-Programming-Against-an-Interface-and-the-Repository-Pattern.aspx

Let’s start with an example of the problem. We use a repository pattern to encapsulate our Linq our Linq-queries into manageable and reusable componentes. Are repository can look kindof like this:

public class ClipRepository : IClipRepository
{
    IDataContext _dc;
    IDataContext dc
    {
        get
        {
            if (_dc == null)
            {
                _dc = new PiratDataContext();
            }
            return _dc;
        }
    }
    public IQueryable getClipsFromSite(int siteid)
    {
        return from sc in dc.SiteClips
        where sc.SiteID == siteid
        select sc.Clip;
    }
}

The repository implements a IClipRepository interface an all code that depends on the repository is written against the interface instead of the specific implementation. This is great because we can then switch from a database backend-implementation to, say, a cachebackend without changing any of the dependant code. We use a servicelocator to provice simple inversion-of-control and break dependencies, and as a bonus, we can write unittest of code that uses the repository be reconfiguring the servicelocator to return a MockedClipRepository instead of the real one.

However, as mentioned above, the DataContext itself does not implement an interface, so we cannot use the servicelocator to provide the datacontext, and therefore we cannot really unittest our repositories without great difficulty.

Wrapping the DataContext

C# is flexible – with generics we can create a proxy class around a DataContext, and we can make that class implement a suitable interface.

public interface IDataContext
{
    /// <summary>
    /// Gets the repository for the given type of entities
    /// </summary>
    /// <typeparam name="T">The type of the entity</typeparam>
    /// <returns>The repository of the given type</returns>
    IQueryable<t> GetTable<t>() where T : class, INotifyPropertyChanged;
 
    /// <summary>
    /// Adds a new entity to the repository
    /// </summary>
    /// <typeparam name="T">The type of the entity</typeparam>
    /// <param name="item">The entity to add</param>
    void Insert<t>(T item) where T : class, INotifyPropertyChanged;
 
    /// <summary>
    /// Deletes the specified entity from the repository
    /// </summary>
    /// <typeparam name="T">The type of the entity</typeparam>
    /// <param name="item">The entity to delete</param>
    void Delete<t>(T item) where T : class, INotifyPropertyChanged;
 
    /// <summary>
    /// Commits the changes to the repository
    /// </summary>
    void Save();
 
    /// <summary>
    /// Provides access to the modified objects tracked by the system
    /// </summary>
    ChangeSet GetChangeSet();
}

And the wrapper class implementation for LinqToSql datacontexts:

public class LinqToSqlDataContext<t_datacontexttype> : IDataContext where T_DataContextType : DataContext
{
    private DataContext _dc;
    private DataContext dc
    {
        get
        {
 
            if (_dc == null)
            {
                _dc = Activator.CreateInstance<t_datacontexttype>();
            }
            return _dc;
        }
    }
 
    public IQueryable<t> GetTable<t>() where T : class, INotifyPropertyChanged
    {
        return dc.GetTable(typeof(T)).Cast<t>();
    }
 
    public void Insert<t>(T item) where T : class, INotifyPropertyChanged
    {
        dc.GetTable(typeof(T)).InsertOnSubmit(item);
    }
 
    public void Delete<t>(T item) where T : class, INotifyPropertyChanged
    {
        dc.GetTable(typeof(T)).DeleteOnSubmit(item);
    }
 
    public void Save()
    {
        dc.SubmitChanges();
    }
 
    public ChangeSet GetChangeSet()
    {
        return dc.GetChangeSet();
    }
 
    #endregion
}

Using the wrapper

With this wrapper in place, we then change the implementation of the repository above so that instead of creating it’s datacontext directly it uses the wrapper:

// creating the context
// in the ServiceLocators config, IDataContext is setup to return LinqToSqlDataContext<piratdatacontext>
_dc = ServiceLocator.New<idatacontext>();
 
// using it
return from sc in dc.GetTable<siteclip>()
         where sc.SiteID == siteid
         select sc.Clip;

Unit testing

With the above setup we can now create a MemoryDataContext, that has the same interface as the LinqToSql context, but does not depend on a database:

public class MemoryDataContext : IDataContext
{
    private readonly List<object> _inMemoryDataStore = new List<object>();
    private readonly IList<object> _Inserts = new List<object>();
    private readonly IList<object> _Deletes = new List<object>();
    private readonly IList<object> _Updates = new List<object>();
 
    public MemoryDataContext()
    {
    }
 
    public MemoryDataContext(params INotifyPropertyChanged[] objects) : this()
    {
        foreach (var obj in objects)
        {
            _insert(obj);
        }
    }
 
    private void _insert(INotifyPropertyChanged item)
    {
        _inMemoryDataStore.Add(item);
        item.PropertyChanged += new PropertyChangedEventHandler((s,e) => _Updates.Add(s));
    }
 
    public IQueryable<t> GetTable<t>() where T : class, INotifyPropertyChanged
    {
        var list = from objects in _inMemoryDataStore
                    where typeof(T).IsAssignableFrom(objects.GetType())
                    select objects as T;
        return list.AsQueryable();
    }
 
    public void Insert<t>(T item) where T : class, INotifyPropertyChanged
    {
        _insert(item);
        _Inserts.Add(item);
    }
 
    public void Delete<t>(T item) where T : class, INotifyPropertyChanged
    {
        _inMemoryDataStore.Remove(item);
        _Deletes.Add(item);
    }
 
    public void Save()
    {
        if (Completed != null)
        {
            Completed(this, EventArgs.Empty);
        }
    }
 
    public ChangeSet GetChangeSet()
    {
        var constructor = typeof(ChangeSet).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).First();
        var changes = constructor.Invoke(new object[]
        {
            new ReadOnlyCollection<object>(_Inserts),
            new ReadOnlyCollection<object>(_Deletes),
            new ReadOnlyCollection<object>(_Updates),
        }) as ChangeSet;
 
        return changes;
    }
 
    public event EventHandler Completed;
}

And there – we can now write unittests of our repository methods like this:

        [TestInitialize]
        public void init()
        {
            var memContext = new MemoryDataContext();
            memContext.Insert(new Clip { ID = 1, Title = "hest" });
            memContext.Insert(new Clip { ID = 2, Title = "giraf" });
            memContext.Insert(new Clip { ID = 3, Title = "tobis" });
            memContext.Insert(new Clip { ID = 4, Title = "laks", AllowExternalEmbedding = true });
            memContext.Insert(new SiteClip { ClipID = 1, SiteID = 50 });
            memContext.Insert(new SiteClip { ClipID = 2, SiteID = 50 });
            memContext.Insert(new SiteClip { ClipID = 3, SiteID = 4 });
            memContext.Insert(new SiteClip { ClipID = 4, SiteID = 4 });
            memContext.Insert(new SiteClip { ClipID = 4, SiteID = 50 });
 
            ServiceLocator.Add(typeof(IDataContext), memContext);
        }
 
        [TestMethod]
        public void getClipsFromSiteTest()
        {
            ClipRepository target = new ClipRepository();
            Assert.AreEqual(3, target.getClipsFromSite(50).Count());
            Assert.AreEqual(2, target.getClipsFromSite(4).Count());
            Assert.AreEqual(0, target.getClipsFromSite(1).Count());
        }
    }

Hjælp med test af ny forside

January 26th, 2010

På Pirat TV bruger vi en del flash. Stort set al frontend er bygget i flash, hvilket vi i sin tid fik svenske Doberman til. Og de gjorde det rigtig godt. Desværre har det efterfølgende givet lidt bagslag, da vores egen flashmand har haft alt for travlt til at rette de småfejl vi har fundet undervejs.

Så for en uges tid siden kastede jeg mig ud i et eksperiment: At bygge Pirat TV’s forside udelukkende af god, gammeldags HTML, CSS og javascript — helt uden flash. Jeg er nu nået så langt at jeg har noget der er værd at se på. Det er ikke en færdig erstatning til forsiden. Mere et proof of concept, og jeg kunne derfor godt tænke mig at få noget feedback.

En ting der er vigtig for os, for at vi vil tage skridtet og skrælle noget flash af, er at det ikke må gå ud over brugeroplevelsen. For brugeren skal det ikke føles som en degradering at vi skifter den bagvedliggende teknologi for visningen af vores sider. Og siden er lidt tung. Både med mange billeder, men også med en god portion javascript.

Så derfor: Kig på den nuværende forside og den nye forside uden flash. Kør lidt rundt med musen på dem begge. Prøv at ændre størrelse på vinduet. Hvordan føles det? Hænger det for meget? I hvilke situationer? Prøv meget gerne i forskellige browsere. Jeg har selv testet i de fleste moderne browsere (i Windows), men har ikke haft mulighed for at prøve i en rigtig Internet Explorer 7/8. Skriv om dine observationer og hvad du synes i kommentarfeltet. Fortæl også gerne lige lidt om din computer: Hvor hurtig den er, hvor meget ram den har, hvilket styresystem du bruger, hvilke browsere du har testet i.

Det skal måske lige nævnes at de to forsider ikke er identiske helt ned på pixelniveau. Det behøver de ikke være. Endnu.

På forhånd tak.

nginx as a proxy for Visual Studio

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.

Lidt (uofficielle) tal fra MC’s Fight Night

October 18th, 2009

I går aftes streamede vi MC’s Fight Night live på Pirat TV. Det var en stor succes, og vores foreløbige, men uofficielle tal siger at der var nogen forbi mere end 13.000 gange før, under og lidt efter showet. Det er vi ret godt tilfredse med. Showet stod for 27% af vores sidevisninger i går, og derudover har nogle af vores Fight Night-arkivklip også trukket noget trafik.

Kommentarerne bar meget præg af folk i udlandet der ikke kunne se udsendelsen. Men det har i virkeligheden været meget få det var et reelt problem for. Det drejer sig om nogle få hundrede som har siddet udenlands og dermed ikke kunnet se showet på nettet.

En glædelig observation er til gengæld at hip hoppere tilsyneladende har god browsersmag: 45% af de besøgende brugte Firefox og kun 30% brugte Internet Explorer.

Det er næppe sidste gang vi har live-streamet fra den slags begivenheder. Det er fedt at være med til at tilgængeliggøre ungdomskultur der åbenbart er for smal til at kunne finde vej til de traditionelle kanaler.

Sig goddag til Pirat TV

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.

Custom Error Handler in IIS7

April 2nd, 2009

Introduction

During the development of SKUM3 some problems have not manifested themselves while developing for one simple reason: Visual Studio 2008 uses a version of IIS 6 as a development server, but our final setup will be an IIS 7 server. The differences between these two version are significant enough to cause headaches.

One such headache is the inability to debug code running on the remote server. This combined with differences in how errors are handled, both in the setup in the web.config file, and in the way a custom error handler is called, produced a very difficult to solve problem. Also a lack in documentation is partly to blame.

The problem

web.config differences.

IIS 7 version:

<httpErrors>
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" prefixLanguageFilePath=""
        path="/path/to/handlerwebservice"
        responseMode="ExecuteURL" />
</httpErrors>

 IIS 6 version:

<customErrors mode="On">
    <error statusCode="404" redirect="webservices/media/image"/>
</customErrors>

With the IIS 6 version all 404 errors are redirected to webservices/media/image?aspxerrorpath=original/path. In IIS 7 though this querystring parameter is missing so what to do?

The Solution

Well, microsoft is not very helpful and I tried asking my question to the Internet but as I didn’t receive any answers I just tried changing

context.Request.Path

to

context.Request.RawUrl

Resulting in this code to handle the differences:

string requestpath;

if(context.Request.QueryString.AllKeys.Contains("aspxerrorpath"))
{
    requestpath = context.Request.QueryString["aspxerrorpath"];
}
else
{
    requestpath = context.Request.RawUrl;
}

This seemed to have the desired effect. The difference between these two are that RawUrl contains the requested path unaltered by redirection or anything else and Path is the Url after any redirection. I had forgotten this minor detail even though I’ve used it in the breadcrumb method to split an original path up into individual pieces, after the request had been redirected by our UrlRewriter.

If you are getting weird errors about httpErrors being locked down use a cheat code

%windir%\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/httpErrors

Being trapped in IIS

March 26th, 2009

Mikkel has just spend a lot of time trying to get ASP.net MVC to work on a server. During this quest he bumped in to a lot of headache inducing problems the worst of which I will describe here and provide some sort of solution.

The error our dear setup threw at us was:

System.InvalidOperationException:
    The SessionStateTempDataProvider requires SessionState to be enabled.

The only results on google were suggesting to add a line in web.config to tell ISS and ASP.net that sessionState mode should be enabled. Trying this and still getting the same error we found this:

On the Session State tab in IIS, is it also set to enabled?

If you are reading this, you are probably having the some understanding of how the IIS7 management gui works and how it looks. It has no notion of Tabs, and no configuration icons relating to session at all.

Poking around at every concievable way to add SessionState we found that it was possible to add a module named:

System.Web.SessionState.SessionStateModule

Adding that module created the following in web.config:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
       <add name="SessionStateModule"
            type="System.Web.SessionState.SessionStateModule" />

Rembering to add this:

<system.web>
   <sessionState mode="InProc" />
</system.web>

made the server happy.

Hopefully someone in the same situation will find this helpful.

ps: If you are getting weird errors (0×80070021) about system.webServer handlers not being recognized you’ll need to enable them using the cheatcodes:

%windir%\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/handlers
%windir%\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/modules

Typeface.js

November 11th, 2008

Typeface.js er et rimeligt interessant stykke software. Interessant fordi det uden problemer tillader en at bruge fonte i websites selvom næsten ingen endnu har implementeret @font-face css-reglen.

Jeg skriver at det er uden problemer og det er en sandhed med modifikationer. Det er problemfrit når man bare bruger det som tekst rendering og ikke forventer at det kan redde verden. Det virker i de fleste grade A browsere. Lige netop det at det ikke virker i alle grade A browsere er det som denne artikel handler om.

I Opera virker det nemlig overhovedet ikke. Det påstås heller ikke fra forfatterens side, men det virkede lidt underligt at det ikke skulle virke, for Opera plejer at opføre sig ordentligt det meste af tiden.

Efter en hurtig omgang debugging i typeface kilden med Operas indbyggede debugger værktøj, fandt jeg ud af at Opera opfattede at de elementer som skulle have specielle fonte, skulle renderes med Arial. Det er jo ikke rigtigt til at forstå, eftersom Arial ikke var i stylesheet’et. Jeg kom frem til at Opera måtte smide specialfonten væk, fordi den ikke kunne finde den, og så bruge det den troede man havde brug for i stedet.

Efter en del søgen på det store Internet fandt jeg et indlæg i Operas developer forum om emnet. Det som Operas udvikler svarer er at de har taget en design beslutning og implementeret det på den måde de har. w3’s specifikation på området omkring computed styles (den værdi som der bliver hentet ud i dette tilfælde, og som indeholder beregnede værdier af de værdier som står i stylesheet’et) er yderst vag, og den beskriver kun at man skal lave pixel beregninger og sørge for at inherit værdier er ændret til de værdier som skal bruges. Mozilla skriver i deres developer central wiki at de faktisk har snydt lidt og bruger used styles som resultat af computed styl, men det ændrer ikke ved at de returnerer det rigtige resultat, nemlig en streng som indeholder en kommasepereret liste af de fonte som er i stylesheet’et. Forhåbentligt går der ikke mange dage før Opera har rettet op på denne fejl. Indlægget blev besvaret i går af en af deres udviklere og han skriver:

This was by design but will be “fixed” :smile:

Så man har to valg:

  • Vente og se hvornår de får implementeret den nye funktionalitet
  • Implementere en traversering af tilknyttede stylesheets for at finde de regler som berører netop de elementer man har brug for

I dette tilfælde vil det nok være lidt nyttesløst at vælge det sidste, eftersom der ikke er nok der bruger Opera til at det giver mening, derudover er Opera ikke en standardbrowser på nogen platform, så folk der bruger Opera kan se siden i mindst én anden browser.

Hvis man endelig skulle vælge vej nummer 2 og kigge stylesheet’ene igennem, så skulle man nok implementere et fuldt css bibliotek, som også vil kunne bruges til at udjævne forskelle mellem browsere i forhold til implementationer af nuværende standarder og også i forhold til at implementere kommende standarder, indtil browserne selv gør det. Javascript er jo netop nået et punkt hvor det er gjort så hurtigt at det ikke vil betyde store ventetider at have store scripts.

z-index og ie 6

November 11th, 2008

Dette er viden som skulle have været ubrugelig for længe siden, men folk er ignorante, og derfor skal vi stadig supportere forældede browsere.

Den browser som givers os flest problemer er jo selvfølgeligt Microsofts Internet Explorer version 6.

En af de utallige bugs vi har haft problemer med er at vi har nogle popup-elementer som sidder på vores brugerprofiler. Det virker som det skal i alle andre browsere, men ie6 synes ikke at det z-index popup-elementet har fået er godt nok og derfor vil den måske kunne skjule det bag andre elementer.

Måden den skjuler elementet på var dog ikke lige til at finde ud af, for det var kun nogen elementer der gemte popup’en. Efter lidt undersøgelse fandt jeg at de elementer der skjuler popup-elementet var relativt positioneret. og det element som popupen var i også var relativt positioneret. Det viser sig nemlig at ie6 ikke er tilfreds med at hvert element har deres helt eget z-index. I stedet siger den at den boks som elementet er inden i ligger i et lag for sig selv, som ingen andre elementer udefra kan komme imellem.

Dette betyder at man kan komme et hvilket som helst z-index på popup-elementet, det er stadig relativt i forhold til det element det er indeni. Og elementer der kommer umiddelbart efter vil, i kraft af at de kommer senere i dokumentet, overlappe ved “by-design” at have et højere z-index (på en måde). For atfå ie6 til at tegne det ordentligt, så bliver man nødt til at sætte z-index’et på popup-elementets relative parent til et andet højt z-index.

For mere dybdegående information: http://aplus.rs/lab/z-pos/