Kinect in the Abstract: Working with the Sealed SkeletonData and JointsCollection classes
My latest side project involving the Kinect started to get a bit hairy. The logic for what we were trying to do was at least an order of magnitude greater than the Target Tracking system my colleagues and I built last year. It functioned, but it was getting exponentially more difficult to add features to it, let alone debug it.
So, suffering from a lull in my regular project work over the holiday break, I decided to start building some unit tests for it. If nothing else, having a solid test suite would allow me to regression-test the application whenever I monkeyed with the code, and THAT would enable some good-sized refactorings that were long overdue. My first task, then, was to figure out how to mock out the data coming off the Kinect. My first task quickly hit a wall.
The application uses the SkeletonData object available in the SkeletonFrameReady event. My original event handler looked something like this:
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { List<SkeletonData> ActiveSkeletonsRaw; SkeletonFrame allSkeletons = e.SkeletonFrame; ActiveSkeletonsRaw = (from s in allSkeletons.Skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).ToList(); this._MyManager.UpdatePositions(ActiveSkeletonsRaw); }
The UpdatePositions() method would handle moving the objects around based on the new positions of the skeletons/joints, and that was the primary method I wanted to test. I figured if I could create my own SkeletonData object, and pass that into UpdatePositions, I could test any scenario I wanted. Unfortunately, the SkeletonData class is sealed, and there aren’t any public constructors on it. So, I went the route of writing my own version of SkeletonData – one that I could create objects from, and would effectively function the same as SkeletonData:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Research.Kinect.Nui; public class SkeletonDataAbstraction : ISkeletonData { public JointsCollectionAbstraction Joints { get; private set; } public Vector Position { get; set; } public SkeletonQuality Quality { get; set; } public int TrackingID { get; set; } public SkeletonTrackingState TrackingState { get; set; } public int UserIndex { get; set; } public SkeletonDataAbstraction() { this.InitializeJoints(); } public SkeletonDataAbstraction(Microsoft.Research.Kinect.Nui.SkeletonData RawData) : this() { foreach (Joint CurrentJoint in RawData.Joints) { this.UpdateJoint(CurrentJoint); } this.Position = RawData.Position; this.Quality = RawData.Quality; this.TrackingID = RawData.TrackingID; this.TrackingState = RawData.TrackingState; this.UserIndex = RawData.UserIndex; } private void InitializeJoints() { this.Joints = new JointsCollectionAbstraction(); foreach (JointID CurrentJointID in Enum.GetValues(typeof(JointID))) { this.Joints.Add(new Joint() { ID = CurrentJointID, Position = new Vector() { X = 0.0f, Y = 0.0f, Z = 0.0f, W = 0.0f }, TrackingState = JointTrackingState.NotTracked }); } } public void UpdateJoint(Joint NewJoint) { this.Joints[NewJoint.ID] = new Joint() { ID = NewJoint.ID, Position = new Vector() { X = NewJoint.Position.X, Y = NewJoint.Position.Y, Z = NewJoint.Position.Z, W = NewJoint.Position.W }, TrackingState = NewJoint.TrackingState }; } }
When the class is instantiated, the Joints collection is also instantiated with a "blank" Joint object for every joint defined by the Kinect (the complete list is defined by the Microsoft.Research.Kinect.Nui.JointID enumeration). Then, the UpdateJoint method is called to overwrite those blank joints with the real values. I also use this method in the unit tests to precisely place the joints I was interested in, just before running a given test.
I thought I would end up needing to mock out portions of the class, so I created an interface for it as well:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Research.Kinect.Nui; public interface ISkeletonData { }
As it turns out, I didn’t need to mock anything out – I can just create SkeletonDataAbstraction classes, and pass them directly into UpdatePositions. I decided to keep the interface around, just in case I later found something that required a mock.
I also needed to be able to construct a JointsCollection object (what the SkeletonData.Joints property is defined as), but that was also marked sealed with no public constructors. So, I created a JointsCollectionAbstraction object for it:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using Microsoft.Research.Kinect.Nui; using System.Collections.ObjectModel; using System.ComponentModel; public class JointsCollectionAbstraction : List<Joint>, IEnumerable { public Joint this[JointID i] { get { return this[(int)i]; } set { this[(int)i] = value; } } }
After putting these together, I rewrote my original application code using the new abstraction layer, to make sure I had captured everything I needed to:
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { List<SkeletonData> ActiveSkeletonsRaw; SkeletonFrame allSkeletons = e.SkeletonFrame; ActiveSkeletonsRaw = (from s in allSkeletons.Skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).ToList(); List<SkeletonDataAbstraction> ActiveSkeletons; ActiveSkeletons = new List<SkeletonDataAbstraction>(); foreach (SkeletonData CurrentSkeleton in ActiveSkeletonsRaw) { ActiveSkeletons.Add(new SkeletonDataAbstraction(CurrentSkeleton)); } this._MyManager.UpdatePositions(ActiveSkeletons); }
That worked like a charm. With each SkeletonFrameReady event-raise, I copy the key pieces of information from the Kinect over to my own structures, and use those from that point on. Now the task of writing tests around this could begin in earnest. I wrote a "CreateSkeleton" method for my unit tests that would encapsulate setting one of these up:
private SkeletonDataAbstraction CreateSkeleton(SkeletonTrackingState NewTrackingState, int NewUserIndex) { SkeletonDataAbstraction NewSkeleton; NewSkeleton = new SkeletonDataAbstraction(); NewSkeleton.Position = new Vector(); NewSkeleton.Quality = SkeletonQuality.ClippedBottom; NewSkeleton.TrackingID = NewUserIndex + 1; NewSkeleton.TrackingState = NewTrackingState; NewSkeleton.UserIndex = NewUserIndex; NewSkeleton.UpdateJoint(new Joint() { ID = JointID.HandLeft, Position = new Vector() { X = X_WHEN_HAND_MOVES_AWAY, Y = this._OriginalY, Z = this._OriginalZ, W = this._OriginalW }, TrackingState = JointTrackingState.Tracked }); NewSkeleton.UpdateJoint(new Joint() { ID = JointID.HandRight, Position = new Vector() { X = X_WHEN_HAND_MOVES_AWAY, Y = this._OriginalY, Z = this._OriginalZ, W = this._OriginalW }, TrackingState = JointTrackingState.Tracked }); // Other joints overwritten here... return NewSkeleton; }
(Note, the values for X_WHEN_HAND_MOVES_AWAY, _OriginalY, _OriginalZ, and _OriginalW are merely floats, defined specific to the application.)
Now I could easily create a list of Skeletons to track, with joints positioned just so, and pass that structure into UpdatePositions.
After I had most of this built out, I found a couple of other posts from people doing essentially the same thing:
- http://social.msdn.microsoft.com/Forums/en/kinectsdknuiapi/thread/08344def-b448-45a7-ac1f-2bc2e129fb4f
http://blogs.msdn.com/b/eternalcoding/archive/2011/07/04/gestures-and-tools-for-kinect.aspx
The first one is an interesting forum post where one of the Microsoft guys admits that declaring the SkeletonData and other classes Sealed was probably not the brightest idea.
Thankfully, the wall I hit ended up coming only up to my knees, so after a few bumps and bruises I was over it.
In-Car Traffic Signals
The next time you roll up to an intersection and get caught by the light, stop for a moment and look around its immediate airspace. What do you see?
There’s probably a tall pole on at least two of the corners. If the poles are wooden, they probably have lines (both support and electrical) draped across the road where the traffic lights hang. If they poles are metal, they probably have the lights hung on cantilevered metal poles that dangle out over the road. Either way, you have stuff hanging over your head to let you know when to go and when to stop.
If a driver rolls up and isn’t paying attention to the signal, there’s no reliable secondary mechanism for alerting them (and no, other drivers’ horns don’t count).
And how many times have you been stopped at an intersection, and easily have enough time to go, but can’t because the lights aren’t with you.
What if we changing things around, and moved the traffic signals INTO the car?
With this system, you’d roll up to the intersection, and a display embedded into your windshield tells you that the light is green, and it’s safe to proceed. Or you’re coming up on the signal change, and the display is yellow as you approach, and eventually turns to red. You wait at the light as you normally would and wait for your turn. The light goes green, and you proceed.
Or, perhaps you’re having an animated discussion with your significant other in the car, and you’re not paying enough attention to the intersection ahead of you. The system flashes a yellow/red light onto your windshield, sees that you aren’t slowing down yet, and tells your car to activate an audible warning, bringing your attention back to the road.
Later, the initial in-car system evolves to the point where the intersection can the start tailoring signals to individual cars, thus optimizing traffic flow.
If power were to go out, the car’s system could detect that it wasn’t receiving ANY signals from the intersection, and present the equivalent to a 4-way stop for all approaching cars.
Without any signal lights being hung on or over the roadside, there aren’t any lights to maintain, or to keep clear of snow in the winter, saving maintenance costs.
Is the city commission thinking about widening the road to 6 lanes? Hanging new signals won’t be necessary – just some extra programming.
Finally, taking the lines and poles down would clear out a lot of the visual clutter at the intersection, thus allowing the city to reclaim a little beauty.
Are there challenges here? Absolutely. Taking down the traffic signals means that EVERY car on the road needs to have this system in place and working – in other words, the requirements for overall traffic safety are now moved from the street lights to the individual automobile. That’s a hard sell for anyone on the city commission.
It may also pose a new challenge for traffic incidents, specifically, getting eye witnesses that can vouch for the state of the light when an accident happened. With the system built into the car, victims- and perpetrators-alike could claim their vehicle said it was OK to go. On the flip side, the vehicle data-collection modules (think airplane black boxes, but in cars) could record the actual state of the light as transmitted to the vehicle, and would serve as an objective source for the state of the light.
Traffic lights, in one form or another, have controlled pedestrian and vehicular traffic for over 140 years*. Perhaps it’s time for something new.
* Source: http://www.ideafinder.com/history/inventions/trafficlight.htm
With a little help from my Friends – TDD, Mocking, and InternalsVisibleTo
My current project is building a .NET library that will interface with multiple different web services. Some of those services were not ready when I started the library, and I wanted to push myself further into mocking, so I wrote a .NET interface, and a wrapper class for each web service. That allowed me to mock the services out, and simulate the response for a given request. Once the web service became available, I’d implement that interface, and pass the requests through to the real services.
The goal here was to completely abstract the actual web service calls and responses from the user of the library. However, in order for NUnit to be able to test those interface and other classes, they had to be declared Public. That meant that someone actually using the library would see all of that structure in Intellisense – even when they would never use it, and would probably be confused by it. This was the unfortunate tradeoff of TDD – or so I thought.
One of my colleagues, Doug, found a little assembly attribute called InternalsVisibleTo. Applying this to your assembly (in the AssemblyInfo.vb/AssemblyInfo.cs class) allows non-Public members to be visible to the specified external assembly. That allowed me to change the declaration on the Public classes that I didn’t really want exposed to a consumer of the library to Friend (the not quite equivalent to C#’s "internal" declaration). That meant that I could effectively expose those classes and other items to my test assembly, but hide them from every other assembly. For more information on this attribute, check these links out:
http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx#Y1557
http://devlicio.us/blogs/derik_whittaker/archive/2007/04/09/internalsvisibleto-testing-internal-methods-in-net-2-0.aspx
(Please note, the second is an older post by Derik Whittaker, and at the time he wrote it this was only available to C# assemblies; that has since been remedied – you can use it in VB now as well.)
So I added a line to expose this to my test assembly. Then I started systematically changing Publics to Friends, recompiling, and re-running the unit tests. I ran into a few bumps along the way.
First, I was doing a lot of constructor injection in association with the mocking where the parameter-less constructors would set up the lower-level objects, but the other variants would allow me to pass those objects in (the passed-in objects would be my mock objects). In the course of this rework, I ended up hiding a lot of those classes. Initially, the constructor variants that used them were marked Public, which the compiler had a fit about – I couldn’t expose those classes via the constructor parameters because the classes were now marked as Friend, but the constructors were marked as Public. Changing the constructor designations to Friend solved this.
Second, when I started changing the classes used by my mocking framework, Moq, I found that the InternalsVisibleTo line allowing my test assembly wasn’t enough. I figured the Moq assembly needed to be explicitly allowed, too. I tried the code-roulette approach first, without success. Then I consulted the internets, which of course had the answer. Andrey Shchekin had the solution – DynamicProxyGenAssembly2 (http://blog.ashmind.com/2008/05/09/mocking-internal-interfaces-with-moq/). Yeah, that was totally going to be my next guess. Uh-huh.
So, I have my mocking/TDD cake and get to eat it too. The library footprint is nicely trimmed back, without much of the original clutter, but I can still unit-test to my heart’s content. Many thanks to Doug for finding this little gem!
The only thing I wasn’t able to accomplish with this was hiding the SOAP web service structure. I tried changing the Visual Studio-generated classes to Friend, but that started failing when I tried to call the service. Perhaps there is another attribute that at least hides these from Intellisense. A search for another day.
Type-writer
Many years ago, at my former company, I took the Myers-Briggs Type Indicator, or MBTI, personality test. I relieved to report that I’ve passed this test every time, so you can be assured I have a personality. For a more serious overview of the MBTI, please visit http://www.myersbriggs.org.
I think I’ve gone through this exercise four times in my life, and the result has been the same in all cases – INTJ. There is a lot of meaning behind those four letters, but the points that I frequently come back to are these:
- The "I" stands for "Introvert", which despite popular belief does not mean I shun other people. Rather, being around large groups of people is exhausting for me, while interacting with small groups or just being by myself is frequently energizing. An extrovert would tend to react in the opposite manner in these cases.
- The "N" stands for "Intuitive" and "T" for "Thinker". One of the traits of an "NT" is the ability and drive to constantly improve upon everything around them in the pursuit of perfection.
I most recently went through the MBTI evaluation this past week, and to my great surprise, I found I have apparently mellowed with age. All of the previous times taking this test showed an incredibly strong preference for all four aspects of the type – I would usually peg at least two of the letters at the end of the spectrum, and the other two would be close behind. This time around, the INT all showed moderate or weak preferences (the J was still in the nearly 90 percentile).
What do I make of this? As far as the "I" goes, I don’t run screaming when a party invite comes across my desk. I might still come home and feel exhausted afterward, but I don’t (as frequently) use that as an excuse to avoid them.
As for the "NT", I don’t try to achieve perfection as much any more. I might still aim for it, just so I can say I got "in the neighborhood" of being perfect, but I can still ship something at the end of the day. Looking back, I definitely see a change in how I approach a software release now versus even 5 years ago.
At any rate, if you’d like to take the test, go here first: http://www.humanmetrics.com/cgi-win/JTypes2.asp. Then visit the Myers-Briggs Organization’s site for information on the 16 possible types.
Idea Incubation Site
One of the most recent posts on my company’s corporate blog mentioned a "Twitter Race". Before I got any further than the title, my mind was racing (no pun intended) to figure out what a "Twitter Race" would actually look like. Then I read ahead to see what it actually was.
I will do this frequently, and more times than not, I’ll figure out the core of the idea before I read past the first few words of the description. I say this not to tout my mindreading abilities, but rather to point out that there are some really "duh – why didn’t I think of that?" ideas out there. The fact that I can figure them out based on a five-word description gets me down (just a little) because I DIDN’T think of them already.
So, what did I think "Twitter Race" meant? The first thing that popped into my head was a race that involved geo-tagged tweets – you or a member of your team had to be at specific places between points A and B, had to tweet from there, and had to have your tweets geo-tagged so that a race official could verify that your team actually got all of the checkpoints covered. The actual meaning behind "Twitter Race" was a little different than that.
The fact that I was that far off of the mark got me thinking. What if there was a site that would throw out a phrase like "Twitter Race", and then crowd-source the exploration and definition of that phrase. So, for "Twitter Race", you might get Citroen’s idea, and mine, and 10 others that were nothing like them.
What could you do with this information? Ideas are powerful things. People get an idea – maybe something like "a site where my college buddies and I can stay in touch with each other" – then apply liberal amounts of blood, sweat, and tears to turn them into something real – Facebook.
What does the crowd get out of it? Perhaps points or credits toward submitting their own ideas to the forum. Perhaps they are venture capitalists looking for people and ideas to fund. Perhaps respect in the community that leads to people soliciting your opinion – "hey, if OneCoolUser likes your idea, it means you’ve got a real shot at success!
What about protecting the ideas so people can’t just run with them? What if an idea that started here turns in to a very profitable business – are the people who commented on it and helped shape it entitled to a cut? Does posting the idea on the site count as trademarking it/copyrighting it? Now we’re getting past the "hey, that’s a great idea" to the nitty-gritty logistics. These questions and a hundred others like them would have to be answered before something like this was put into use.
And no, I wouldn’t be surprised if there was already a site out there like this, and I’m just late to the party again.
GE Flyover
GE has a phenomenally cool way to showcase some of their production facilities – flyovers with a camera mounted to an R/C helicopter. Check it out on their YouTube channel:
100% chance of rain (at some point in the future)
For the longest time, I’ve maintained that meteorologists just throw darts to figure out what tomorrow’s weather is going to be. It’s amusing, but it’s an unfair characterization. Meteorologists can tell you a tremendous amount about how weather works, but it’s such a complicated subject that there is a very steep drop-off in the accuracy of predictions even a few hours into the future. Case in point – why do we still have tornado sirens? Those are only good to tell you when one’s actually been sighted. Why can’t we predict even 15 minutes from now when one will form?
At any rate, the few occasions in the past where I’ve actually paid attention to the weather forecasts a week or so leading up to some outdoor event, it seems like the "it’s gonna precipitate / it’s gonna shine" switches at least twice before the day arrives. I write software for a living so I’m all for updating estimates when it’s clear that they are no longer valid. However, when a weather forecast changes daily – or at least it seems to – what’s the value in anything other than a 4 HOUR, not day, forecast? Or, to put it another way, how accurate ARE 1-day, 2-day, 1-week, etc. forecasts?
To find out, I propose an application that pulls together forecasts and actuals from a variety of sources, and then does a statistical analysis to see how well each source actually does at forecasting the weather. Here are some questions I think an application like this could make:
- How accurate are source X’s 1-day, 2-day, 3-day, 1-week (etc.) forecasts?
- How closely does X get to the actual high and low temperature for the day?
- How well do they predict when the sun will shine versus when it will rain/snow?
- How does source X compare to other sources?
- Is source X’s 2-day forecasts more accurate than source Y?
- Does source Y’s 1-week forecasts more accurate than source X?
The forecasts and current conditions are available from several places now in the form of RSS and other feeds. The bulk of the gathering piece to this application would be building the interfaces to those sources, and merging the data together into a common storage structure.
This kind of data gathering could lead to habits such as "if you have to look more than 3 days out, look at Source Z’s forecasts – they are the most accurate. Once you get to the day before, however, then Source W’s forecasts are actually more accurate than Z’s." Then, you could use the data and analysis from this first program to feed into a second that always displays the most accurate information at any given time.
Now, to spice things up a bit, let’s introduce a forecast of our own, and see how it stacks up to the professional ones. These forecasts would be based on some relatively arbitrary formula, taking into account things like month of year, the previous day’s weather, and some random number used to vary the temperatures and probability of precipitation. In other words – would throwing darts be just as accurate after all?
Congressional Time
The inspiration for the "You should totally write that!" series stems from an article I read this past weekend in the Kalamazoo Gazette. The House passed a resolution that reaffirmed "In God We Trust" as the national motto. And by "reaffirmed" I mean this is the third such resolution made by the House – the first being in 1956 and the second in 2002. The Washington Post has the story as I saw it appear in the Gazette.
The thing that really got me going was that they spent 35 minutes debating this topic. Assuming the full House was in the house, that’s 435 x 35 person-minutes of time, or over 10.5 person-DAYS spent talking about this. 10.5 days. Do we really believe this is the most important issue right now? You’d think in an election year, something like, oh, I don’t know, the economy, two wars, even healthcare might take priority.
And that got me thinking. How much time do our elected officials spend debating a given category of topics in a given day, week, or session? For example, the Washington Post article above mentioned that the Democrats sponsored 250 "commemorative" bills in Congress last year. (I’m sure the irony of Republican Trent Franks from Arizona sponsoring the motto resolution will not escape you.) How much time did they spend debating and working through bills like those compared to debating funding bills? What topic gets the most attention? What topic gets the least? Is there a correlation between who controls the House (Democrats or Republicans) if you were to look at the data year over year?
I realize that the floor activities represents only a portion of the time spent on any given bill – officials and staffers have to research the topics (at least I HOPE they do), they have to draft and revise the bills, there’s time spent discussing and polishing the bills in committees, and so on. However, the time spent on the Floor is generally what Joe Plumber or Mark Programmer can see. If an elected official wanted to keep their job, you’d think they’d be very conscious of the face they are displaying to the people who put them there.
To get some of these answers, I started poking around the http://House.gov site to see if I could find transcripts (or at least summaries) of the House floor proceedings – and I found them. Even better, they are available in an XML format, by day:
http://clerk.house.gov/floorsummary/Download.aspx?file=20111102.xml
http://clerk.house.gov/floorsummary/Download.aspx?file=20111103.xml
http://clerk.house.gov/floorsummary/Download.aspx?file=20111104.xml
They don’t go back to the beginning of time, unfortunately – at the time of this writing, January 2011 was not available, but April 2011 was – but they go back far enough that you build a decent history right out of the gate, and then update it with daily pulls. The other key piece included with these feeds are the timestamps – critical if we’re to calculate total time spent. The specific bills are also included in the text of the individual actions, so there would need to be some work done to extract those, and then categorize them into some logical buckets – the wars, jobs-creation, healthcare, pointless commemorative bills, etc. My idea is to build an app that pulls down yesterday’s summary, parse it, and then tally up the time spent on each. I think it would be eye opening to see what our elected officials are really spending their time out.
I then looked to see if there was a similar feed available for the Senate, but wasn’t able to find one that included timestamps of any kind, so unless you watching C-SPAN with a stopwatch, I don’t think this is possible right now.
You should totally write that!
I’m starting a new, open-ended thread today called “You should totally write that!”. As I’m sure many of you can relate, I have more ideas about software that should be written than I have time to write that software. So, I’ve decided to put those ideas down in the hopes that someone will make the time to write them.
Some of these will be one-liner like “an app that lets me geolocate my dog’s favorite neighborhood spots”. Who knows, maybe dogs have been constructing neighborhood-sized connect-the-dots games, and no one was aware until this app got written. In other cases, I spend a fair amount of time researching the idea, possible ways to implement it, and questions that I want answered. All of that information and thought-process will go here now.
Finally, if someone does implement one of these, please let me know. I’d love to update that particular post to include links to your work.
My first “You should totally write that!” should be published later this week.
Meta Insanity – Strings and Meta Tags
It was another one of those days. And this time, I DID go home after I saw this in action.
On many of my past Web Forms sites, I’ve had to include a dynamic meta/description tag in the header. The “dynamic” parts come in when the page being rendered is a product page, a recipe page, or something else where the data is drawn out of a database.
When I first started doing this, I tried something like this*:
<meta name="description1" content="<%=Me.SomeMetaValue%>" />
Where “SomeMetaValue” is a property of the page, or a reference to a shared value somewhere else in the solution. This version fails because the inner left angle bracket gets encoded, thus ruining the server-side expression hole:
<meta name=”description1″ content=”<%=Me.SomeMetaValue%>” />
To get around this, I replaced the entire meta/description tag with an ASP.NET literal, and insert the value I wanted on the server side. That worked.
Recently, this issue came up again. Doug had taken over one of the sites where I had done this, and he refused to believe that the data wouldn’t render correctly in the expression hole. He tried it, and sure enough the < got encoded. Doug kept at it, though, and found that if you removed the double quotes around the expression hole, it rendered the value correctly:
<meta name="description2" content=<%=Me.SomeMetaValue%> />
Unfortunately, this was no longer valid HTML:
<meta name=”description2″ content=Blah blah />
Doug remembered an old issue he and I troubleshot, documented at System.String has me in knots. He modified the original attempt to prepend an empty string:
<meta name="description3" content="<%="" & Me.SomeMetaValue%>" />
That renders perfectly:
<meta name=”description3″ content=”Blah blah” />
Putting the empty string after SomeMetaValue also works just fine:
<meta name=”description3″ content=”<%=Me.SomeMetaValue & “”%>” />
What.
The.
Heck?!?
I had written off the encoded angle bracket to an overly eager web server (Cassini and IIS behaved the same in this case), but why in the world would tacking on an empty string force it to NOT be encoded and allow it to work? Since we’re dealing with silly strings here, I followed the lesson learned in System.String has me in knots, and added .ToString onto the end of Me.SomeMetaValue:
<meta name="description4" content="<%=Me.SomeMetaValue.ToString%>" />
Aaaaaand, we’re back to encoding:
<meta name=”description4″ content=”<%=Me.SomeMetaValue.ToString%>” />
Sigh. Oh Visual Studio. Why must you taunt me so?
For a fully working – er, FAILING – sample of the above, check out the MetaInsanity.zip archive at http://TinyURL.com/MarkGilbertSource.
* I used “description1”, “description2”, etc. just for illustrative purposes for this blog post. The production sites have this value as simply “description”.

