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:
Ononderhoudbaar, buggevoelig, en super hacky. Dat kan mooier!
Route Tables Om van een URL een action op een controller te maken hebben we 'route
tables'. Als je URL er uit ziet als X, doe Y. Een principe dat we
ook hier kunnen gebruiken. Alleen dan nog één niveau dieper:
Als URL is X, dan action is Y, dan GA tag is Z.
We moeten dus een koppeling maken tussen Y en Z. Tijd voor een eigen routetable!
Werking Om zo flexibel mogelijk te zijn, ziet een regel in de routetable er ongeveer
zo uit:
Nadeel is dat dit nog steeds niet strong-typed is, en we fouten dus pas
heel laat gaan merken (als we dat al doen). Een manier om strong-typed
C# at runtime om te zetten naar een ander stuk code (zoals bovenstaand)
zijn expression trees.
Nieuwe syntax Onze actie voor een detailpagina ziet er ongeveer zo uit:
We willen hier een Google Analytics tag voor maken, op basis van 'controller',
'action', 'aanbod' en 'pagina'. De nieuwe
syntax hiervoor is:
Ombouwen naar normale syntax Aan bovenstaand stuk code kunnen we niet vragen of een bepaalde set RouteData
overeenkomt, dus moeten we dit omkatten. Expression trees time dus!
Allereerst de 'MatchesRouteData' functie. Deze vervangt het
stuk 'routedata["controller"] == "Object"',
en zorgt ervoor dat deze niet casing ignored, en eventueel langs een ModelBinder
gaat als deze beschikbaar is:
Het uitgeschreven stuk code wordt met deze functie als volgt:
Compileren naar Expression Tree De volgende code zet de strong-typed syntax om naar een stuk code als
bovenstaand:
Alles samenvoegen De class, ready to use is te vinden op PasteBin. Om deze te gebruiken: in je Global.asax:
Om je Google Analytics label voor een willekeurige pagina te vinden, heb
je aan één regel genoeg:
Uiteraard bruikbaar voor nog veel meer In principe voor alles waar je een mapping nodig hebt van URL naar iets
anders globaals en onafhankelijks.
There are 7 comments on this article, read them on
Coding Glamour.