Dev did work: Moved to Octopress / GitHub Pages

I won’t be posting here anymore, and will be migrating old posts soon. New stuff is over on my own domain, which I’ve had for a while but was redirecting here. For now, you can subscribe to the new stuff using http://www.davidruttka.com/atom.xml. Not sure yet if I’ll go with a provider like FeedBurner.

It’s possible that this site will stick around for a while, for as long as the other authors want. As for me, my only reason to keep it is not to break old links.

Posted in Uncategorized | Leave a comment

Dev at work: Moving to GitHub Pages

I finally created a repo on GitHub Pages. I didn’t have time to put much there, but I do plan to start relocating to my own property, so to speak.

Seems like it only took about five minutes. The documentation for getting set up was crazy simple, so I am not going to reproduce that information here.

And to think, I could have been playing Candy Crush!

Posted in Uncategorized | Leave a comment

How to run your ASP.NET Web Application when you start debugging instead of launching the page / view you’re editing

I sent Michael on a wild goose chase because I wasn’t paying attention to a project setting. A project setting that I’ve used multiple times, including this week. An incredibly simple project setting that will change your life.

Web project settings

Project Properties > Web > Start Action. Above, I chose Specific Page but left it blank so that it navigates to the root and starts the app. Current Page is the default, which I recall all too painfully from F5-ing ASP.NET MVC views a couple of years ago. There’s also a “Don’t open a page” option down there at the bottom, which is my new favorite setting when working on Web API projects. Will and I used this option earlier this week, and there was much rejoicing.

On a side note, if you’re working on single page apps and want the magic of Scripts.Render without pulling in the entirety of MVC, check out Michael’s Bundler. I’m using it, and it is super groovy. He’s got a couple of blog posts introducing it here and here.

Just remember that if you consume it, his code will not work at all unless you actually execute it.

Posted in Uncategorized | Leave a comment

ScriptBundle subdirectories no longer work in Microsoft.Web.Optimization 1.1.0 when optimizations are off

Just a heads up for now. I’ll track down where to report this or to whom in the morning. Excuse any spelling, grammar, sloppiness of screenshots, etc., I’m doing this pretty quickly before heading out for the day.

tl;dr If you create ScriptBundles that recurse through subdirectories, and if you want to keep optimizations off for debug, stay on Microsoft.AspNet.Web.Optimization 1.0.0. If you go to 1.1.0, force EnableOptimizations=true, or your scripts from subdirectories won’t come through.

I had the good fortune to do a File > New Project a couple of days ago. When I did, I grabbed the bundling package

Install-Package Microsoft.AspNet.Web.Optimization

To keep this simple (i.e., to provide a reduction), I am including just two scripts here. Scripts/foo.js logs “foo”, and Scripts/subdir/bar.js logs “bar”.

image

I create a simple, standard ScriptBundle that should pick these up.

BundleTable.Bundles.Add(new ScriptBundle("~/scripts/bundle")
.IncludeDirectory("~/Scripts", "*.js", true));

When I include these on the Home/Index view using

@System.Web.Optimization.Scripts.Render("~/scripts/bundle")

Only foo gets logged.

image

But if I downgrade to 1.0.0

Uninstall-Package Microsoft.AspNet.Web.Optimization
Install-Package Microsoft.AspNet.Web.Optimization –version 1.0.0

Then they both get logged.

image

If we update back to the 1.1.0 package, we can look in Fiddler and see the problem.

image

Optimization is recognizing that there’s a bar.js somewhere, but the bundle loses track of the fact that it’s in a subdirectory. Of course, this is in debug mode where the optimizations are not enabled and the scripts are still delivered separately. Let’s see if enabling the optimization to deliver the bundle itself will help us.

BundleTable.EnableOptimizations = true;

Now both statements are logged.

image

Of course, looking at the delivered bundle, we can see that the contents of both scripts are there. In other words, you wouldn’t see this problem in Release or if you’re explicitly forcing the optimizations into effect.

image

I lost a fair bit of time the other day thinking that I had mistyped something setting up my ScriptBundle or a similar mistake. Even after I saw the 404s in Fiddler, I blamed myself and kept looking for my own error. Then I realized that the package version was different and took this wild guess =) Hope this helps save someone from similar trouble until the problem is resolved.

Posted in Uncategorized | 5 Comments

How can I preselect an option element in a select box?

I have some friends trying to wire up some pages. Several pages link to a destination page that has a select box, and they want to have a given option preselected based on where the user is coming from. After several emails, I decided a quick screencast might explain it more quickly and clearly. So here it is, my first public* screencast.

* A few jobs back, I did several internal training videos for new hires. They had great names loaded with all kinds of puns. I’m pretty sure Joey still has them.

Posted in Development | Tagged , , , , , | Leave a comment

Where did Attribute Routing go when updating from Web API 5.0.0 -pre to Web API 2?

This is just a heads up for moving to Web API 2 from the prerelease bits. If you weren’t using Web API 5.0.0-pre bits, you can probably ignore this and never know any different. I’m not going to cover Attribute Routing itself here – plenty of posts have already done that.

tl;dr – instead of HttpGet(“route”), you now use Route(“route”), and optionally use HttpGet with no arguments if you need to explicitly define the HTTP method. Same goes for HttpPost, etc.

I updated a project from the Web API prerelease to the official Web API 2 a few nights ago, and it broke my build. The HttpGet and HttpPost attributes take no arguments, so [HttpGet(“someroute”)] and [HttpPost(“otherRoute”)] were no longer valid.

Now, you just use [Route(“theRoute”)], and it will take it’s best guess about which HTTP Method to use. It’s usually right (especially if you use the preexisting conventions). I felt the need to find a contrived example where it chooses wrong to confirm how to make it right.

Let’s say we want this X to get wired up as GET /api. It actually gets wired as a POST, and if you try to GET, it throws 405 Method Not Allowed.

[RoutePrefix("api")]
public class ValuesController : ApiController
{
  [Route("")]
  public int X()
  {
    return 42;
  }
}

In reality, I’d just rename this from X to Get, but this is a contrived example! Let’s pretend someone put a note on the work item that the implementation method must be named X. We can turn the world right-side-up again by stacking the Http* method attribute. The following works as GET /api, and attempting to POST throws 405.

[RoutePrefix("api")]
public class ValuesController : ApiController
{
  [Route("")]
  [HttpGet]
  public int X()
  {
    return 42;
  }
}

Hope this saves someone a few minutes sometime.

Posted in Uncategorized | 1 Comment

MSBuild String Manipulation Chaos

The other day, I was trying to split a string and then get the various parts of it from within an MSBuild project, but it went totally nuts on me. When I tried to access the item at a given index of the split result, I’d get nonsense including semicolons that weren’t there in the first place! Why are semicolons suddenly appearing in the result of a String Split when there were none in the original string?

Once I realized I should take this to the command line and break it down, it made a lot more sense and was quickly resolved (isn’t that usually the case?). I’m posting this so that maybe someone else will find it useful later.

The Goal

Imagine that you have a property that you want to split, and then rejoin all or some of the parts later. A build number seems like a good general example here. You’ve got access to String.Split here, so it seems a natural solution.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <BuildNumber>8.67.5309.9001</BuildNumber>
    <Split>$(BuildNumber.Split('.'))</Split>
  </PropertyGroup>
  
  <Target Name="Dump">
    <Message text="$(BuildNumber)" />
    <Message text="$(Split[0]).$(Split[1]).$(Split[2]).$(Split[3])" />
  </Target>
</Project>

I expected Split[0] to be 8, Split[1] to be 67, etc. What really happened was:

Dump:
8.67.5309.9001
8.;.6.7

Huh?

Where did that semicolon come from, and why do I get 6 and 7 instead of 67? I’ll admit I hacked and searched on this for way too long before turning to the old standby of “echo something out,” but once I did…

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <BuildNumber>8.67.5309.9001</BuildNumber>
    <Split>$(BuildNumber.Split('.'))</Split>
  </PropertyGroup>
  
  <Target Name="Dump">
    <Message text="$(BuildNumber)" />
    <Message text="$(Split)" />
  </Target>
</Project>

I got some very informative output…

Dump:
8.67.5309.9001
8;67;5309;9001

The Property Is A String

What is happening here is that the property that I’m creating is a string, not an array. It gets rejoined automatically, with semicolons as the delimiters. What I ended up doing was immediately capturing the chunks as separate properties.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <BuildNumber>8.67.5309.9001</BuildNumber>
    <Major>$(BuildNumber.Split('.')[0])</Major>
    <Minor>$(BuildNumber.Split('.')[1])</Minor>
    <Build>$(BuildNumber.Split('.')[2])</Build>
    <PowerLevel>$(BuildNumber.Split('.')[3])</PowerLevel>
  </PropertyGroup>
  
  <Target Name="Dump">
    <Message Condition="$(PowerLevel)&gt;9000" text="IT'S OVER 9000!" />
  </Target>
</Project>
Dump:
IT'S OVER 9000!

I’ve heard that there are some extensions out there that will split and assign to multiple properties a bit more fluidly, but this worked in a pinch. I’d be interested in hearing about other ways people have attacked this problem.

Posted in Development, Stories | 2 Comments

Why Speak?

Recently I was discussing my upcoming trip to speak at devLink and was asked why I do it. I figured that’s a better topic than some of the others I’ve thrown up lately.

Do they pay you?

No. =)

I don’t earn a speaker fee. In most cases, I don’t even earn any reimbursement from the organizers. When I’m lucky, my employer will cover any travel expenses and/or meals, but otherwise it’s all on me. The exception has been when it’s a user group affiliated with INETA, in which case they throw some gas money at you. Highly appreciated, but I haven’t done these to turn a profit.

If not money, then what?

Instead of throwing out simple generic answers, I figured I’d go through some of the gigs I’ve had in the past few years and reflect on the specific motivation for each.

TechMixer University Oct 2011 – Committed to Good Commits

I don’t remember how I heard about the event, but I suppose it was likely a tweet. Probably from Michael Crump or Leverett Powell. Regardless, I remember recognizing it as an opportunity. An opportunity for what? To share, to network, and to perform.

I’ve always liked teaching and sharing. I was a tutor in college, and it wasn’t to pay the bills. One of my favorite students was a guy who was probably 32 years old and taking remedial math. Some joked around and called it “big pencil math,” but you know…really simple stuff. One day, I watched him continually pull out a calculator to multiply numbers by powers of ten. I gently showed him the shortcut of counting the zeroes. He didn’t quite get it at first. Two meetings later, he reached for the calculator and then shook his head and moved the decimal point to the right. It’s great when you see it click and know that you’ve helped someone through a challenge.

There was also the selfish reason which really doesn’t need explanation. Getting your name out there is a good thing. Having speaking engagements on your resume never hurts. Most people don’t realize that you can get yourself into speaker lineups at lesser conferences even if you have no idea what you’re talking about. I will neither confirm nor deny that I’ve done that myself Winking smile The point is: recruiters who can’t differentiate between C# and Node will just see that you’ve delivered presentations at formal events.

Finally, despite the fact that I can be quiet around new crowds (I open up more over time, and as I get to know a smaller group), this disappears if I’m “on stage”. From participating in theater programs in high school to the karaoke fever I developed in college, I enjoy performing. While my talks involve a delivery of technical information, there’s also some showmanship that goes into making sure people don’t fall asleep.

Agile Birmingham Nov 2011 – Continuous Integration

After TechMixer, a member of the TMU committee invited me to speak at Agile B’ham about Continuous Integration. What? This came out of the blue; I didn’t feel like I had done so well at my first gig, and I was certainly no CI expert. I remember recognizing this as…well, an opportunity!

In addition to the given stuff above – networking and performing – this one opened up a new facet of speaking engagements. This time, I could dive a little deeper into the concepts behind some of the practices I had simply been consuming. I remember boning up on Fowler’s seminal piece pretty intensely, but I needed a twist. Everyone would have already seen the high level concepts of what CI was – how could I make it interesting for an hour? Then I realized that I had heard a lot of people say they didn’t do CI because it’s too hard to set up. So, zero to hero in an hour would be fun…

In addition to covering the concepts for anyone who wasn’t yet aware of them, I took a bare Ubuntu VM into a fully functioning CI (actually CD) server with Team City. We had code building on check in, packaging artifacts, running tests, and automatically deploying to staging where SQA could verify the latest changes. “Too hard to setup” was no longer a valid excuse. I felt like this one went a lot better than TMU, and there might be a very low quality recording of it somewhere on YouTube.

HUNTUG 2012 – ASP.NET Web API

I had registered with INETA and the Huntsville, AL group got in touch to see if I could do something for them. My sticking point was a topic, so I threw out Web API, which was still in Beta. They said that sounded great, so I did it. The primary motivation was to have a good excuse to dive deep into Web API. I saw Web API as a very promising idea and figured it would go far. Looking at where I am now, I believe that this was a good call.

After the talk, the primary feedback was that I covered way too much, too deeply, for an “Introduction.” Looking back at the outline, I can see that… I’ve tried to incorporate that feedback into later talks.

CodeStock 2012 – Double Whammy (Mind the Gap – PhoneGap, and Committed Redux)

I thought it would be fun to stretch myself and go for a regional conference. CodeStock 2012 was my first. I decided to submit a previous talk and a new one that I’d have to start from scratch. Joey convinced me to do PhoneGap. The motivations here were primarily to go a little deeper into PhoneGap, and given the relative size of the conference, just to see if I could. To my surprise, both sessions were selected…

More HUNTUG

I did a more talks for HUNTUG (Committed for a third time, etc.) and honestly the primary motivation was Cricket’s. I’ll accept almost any excuse to eat at Cricket’s. Seriously, I’m considering making the trip for CHT to HSV during devLink because I will have already come so far from WA…to be so close and still miss Cricket’s might destroy me. I love you, Cricket’s.

This Summer

I submitted talks to both CodeStock and devLink. I was selected for both, but regretfully backed out of CodeStock because two trips across the country amidst all the other relocation / unpacking, settling / new job stuff just seemed overwhelming. devLink notified me of acceptance the earliest, so that’s why I stuck with them.

For these, the primary motivation was to attend the conference in the first place. Some conferences give speakers a ticket, and that makes it a much easier sell when you ask management to attend. I love my topic and am going to give it my all when I present, but I’m equally excited to see what everyone else has to share. Also, due to recent relo, I’m also looking forward to catching up with some old friends (and even family) while I’m over there.

Different For Everyone

Motivations will vary from person to person. Some people might speak to share what they know, others to force themselves to learn. Some might do it to game their resumes, others to game their way into attendance. I don’t think many do it for money (perhaps when you reach a higher level of notoriety, the perks might change). Over time I’ve probably done it for a little bit of all of these, but ultimately in every case, I’ve done it because it’s fun. At the end of the day, that’s probably the only reason you ever should.

Posted in Events, Stories | 4 Comments

Just Try Something

A coworker and I were discussing the finer points of troubleshooting today, and I remembered that I never posted this thought. It’s short and sweet, and for most people it won’t be anything you haven’t heard before, but I can’t let Derek get too far ahead of me.

I recently saw World War Z. Trying not to spoil anything for anyone who would care, let’s say that one character is asked how he or she knew that something he or she had done would work. That character’s answer? “I didn’t.”

Sometimes, if you’re stuck, just try something. Anything to stop standing still. Flip a switch. Clean the solution. Turn it off and on again. As long as what you’re doing won’t make things worse (or even if it can – as long as it can be easily reverted!), you’ll improve the situation. If it works, you’re done. If it doesn’t, then at least you’ve gained that knowledge and ruled out one more variable.

Bonus: In these “just try something” situations, only flip one switch at a time. If you change too much at once, you won’t know what actually fixed the problem.

Extra bonus: Keep track of which changes you make, in which order, and which ones you revert.

Added extra bonus: If you feel that you are often thrashing in debug and troubleshoot cycles, check out Debug It! from PragProg. I read it some time ago, and IIRC it was pure gold.

Posted in Uncategorized | 4 Comments

The Many Adventures of Externalias

The bad news is, I’m not much of an artist.

The good news is, if I draw this in Paint .NET, it’s about the same as if I draw it on the whiteboard and take a picture.

image

His name is Externalias. He has been described as “a kind of Pac-Man thingy, but with one wing on his back, and antenna…and a lot more scary.” His nemesis is Subtopdecor, but that’s for another post. You may ask yourself, “Why is Ruttka sharing this?” I write to you today about Externalias because his origin story contains a useful answer, and despite the silliness (horror?) of the mascot, it’s possible someone could benefit from hearing it.

About two years ago, my friend Chris sat looking at red squiggly. It implied that he was not referencing a required assembly or was missing a using statement. He was definitely referencing it. We found that the using statement also griped that the namespace didn’t even exist. As he manually typed the using statement from scratch, intellisense never showed the namespace that he needed to use for the desired type.

I didn’t know the answer at the time, but when it happened again last week, I recognized it and was able to fix it pretty quickly.

Fast-forward to the present. Here is one way to get into a very similar situation for which the resolution is identical, but overly simplified and contrived for the purposes of illustration in a blog post. Click any of these images to embiggen.

image

I will not be going into how or why such a situation is ever created. What I will say that I’ve seen it on multiple projects with multiple teams in multiple organizations, so it undoubtedly does happen.

When you build, or rather when you try to build, it’s not going to work.

image

The type ‘Foo.Data.Bar’ exists in both ‘c:\src\Externalias\Foo.Data\bin\Debug\Foo.Data.dll’ and ‘c:\src\Externalias\Foo\bin\Debug\Foo.dll’

The error message describes the problem fairly well, but unlike other errors, it doesn’t recommend a solution.

Now, back to that day a few years ago, when I popped into my friend’s cube a little later, he had just found the answer: EXTERNALIAS! Of course, he had said extern alias, but I was in the habit of hearing words mashed together (see also: Subtopdecor).

image

Here’s what you have to do. View the references of the project in which the problem is occurring, and choose one of the colliding assembles (doesn’t really matter which). View the Properties for that reference, and note that it (like all the others, most likely) is only in the “global” alias. Add another, comma separated.

image

Navigate back to the code file in which the problem is occurring. Above all the usings, add

extern alias {theAliasYouJustMadeUp};

And change the using to

using {theAliasYouJustMadeUp}::{whatYouReallyReallyWant}

image

The build succeeds. For the curious, yes the global:: is implied but can be made explicit…

image

Acknowledgments

Thanks, Chris, for being the first person I know to have encountered this. May you never encounter it again.

Thanks, Externalias, for being the greatest doodle I’ve ever created and preserving the memory of this solution in such a whimsical form. May your presence on developer whiteboards be ever increasing.

Update

What I left out is that (long story short) I doodled these characters on our whiteboards. If I remember correctly, Subtopdecor came first. After I misheard “Subtopdecor,” Chris said it sounded like the name of an evil robot. My first sketch of Subtopdecor was somewhat leaner and meaner, but along the way he filled out and got a little more neutral. I prefer the original interpretation, but for some reason I can no longer draw it successfully. For Externalias, the doodle came first, quite randomly. It was only later that I misheard “Externalias” and we applied the name. They have been spotted at venues as grand as the McWane Science Center in Birmingham.

Posted in Development, Stories | Tagged , , | Leave a comment