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