Jeff's Junk

The sillynonsense and .NET musings of Jeff Putz

News

My Sites

Silverlight 3 and Twitter

The Twitterworld or (Twittersphere or whatever silly shit someone made up today) was all abuzz about the release of Silverlight 3 today, and I was shocked at how quickly it made the trends and how overwhelmingly it was positive.

I kind of knew it was coming already for various reasons (spelled NDA), but it makes me happy to see how excited most people are. I think that individually, the new features have been of average importance, but together, this is a really big deal release. My own pet excitement is attached to the out-of-browser feature, and to a lesser degree the H.264 support, but again, it's an overwhelmingly positive reaction.

But of course the haters are, well, haters. There's a lot of noise and hate on Twitter in general, which is why I fire up Tweetdeck once a week and then let it go for a week after that. The militant Adobe and anti-Microsoft camps started their douchebaggery before anyone ever installed the plugin (let alone the dev tools).

What bothers me the most is that it's a sad reflection on our profession. Platform/language zealotry is like a toxic substance that trivializes what we do. I've had a number of gigs where I happily let go of other projects based on Orcale, Java or whatever because they made sense for the situation. My job was to integrate and connect and ultimately make someone more money, and that's what mattered. If the platform met the requirements, I had to roll with it regardless of what I thought of the vendor or people doing the work. Why is that so hard for some people to deal with?

For the record, I'm pretty excited about Silverlight 3, and its new capabilities immediately bring some uses to mind. I recently deployed a small app to one of my sites for limited use, and install stats went from 25% to 35% in a few days. That's encouraging.

304 Your images from a database

I was reading somewhere about some anecdotal evidence that Google doesn't like to index images that don't have some kind of modification time on them. When I relaunched CoasterBuzz last year, I moved all of my coaster pr0n to the database, and I've since noticed that none of the images are in fact indexed. Bummer.

This also pointed out to me that I was doing something annoying. I was reading the data out every time for every image request. Not exactly the most efficient use of resources. Static files come down with information in the headers indicating when they were last modified (IIS, and presumably any other Web server does this), so the next time the browser makes the request, it the server compares the time in the request header with that of the file, and returns a 304 "not modified" response, and no file.

That seemed like an obvious thing to do, even if it has no impact on Google indexing. Fortunately, it just required some refactoring of the IHttpHandler I had doing the work.

Sidebar: This is probably the point at which some people will make a big stink about serving images out of a database, and how it's bad for performance or scalability. That's a fine argument to make, but outside of doing obviously stupid things, this is not an issue here. I'd prefer to address performance and scalability problems if I have them, not when I might have them, or never have them. Seriously, this is a site that does somewhere between a half-million and a million page views a month depending on the season. There are no performance issues here.

So anyway, assuming for a moment that "photo" is a business object in this code, and it was determined by a query value to the handler, this is the meaty part of the ProcessRequest() method of the handler:

if (!String.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"]))
{
    CultureInfo provider = CultureInfo.InvariantCulture;
    var lastMod = DateTime.ParseExact(context.Request.Headers["If-Modified-Since"], "r", provider);
    if (lastMod == photo.SubmitDate.AddMilliseconds(-photo.SubmitDate.Millisecond))
    {
        context.Response.StatusCode = 304;
        context.Response.StatusDescription = "Not Modified";
        return;
    }
}
byte[] imageData = GetImageData(photo);
context.Response.OutputStream.Write(imageData, 0, imageData.Length);
context.Response.Cache.SetCacheability(HttpCacheability.Public);
var adjustedTime = DateTime.SpecifyKind(photo.SubmitDate, DateTimeKind.Utc);
context.Response.Cache.SetLastModified(adjustedTime);

Yes, it probably needs to be refactored, and yes, it should probably be used in an IHttpAsyncHandler. But let's go through what's happening, starting at the bottom.

The last few lines write out the actual bytes of the image (MIME type was set in previous code), then set the cacheability and the modification time of the image, which in my case is stored with the bits. The goofy part is where we create a new DateTime to make its kind known. If you don't explicitly state that it's a UTC time, the SetLastModified() method apparently adjusts it. I happen to store most times as UTC, so that was one less thing to worry about. This adds a header in the response called Last-Modified, and gives it a value that looks something like "Sun, 22 Jun 2003 16:27:19 GMT" (note that it truncates milliseconds and ticks, as you may expect).

Now, on subsequent requests for the same image, the browser adds an If-Modified-Since header to the request, with the same date and time as the value. Here we're checking to see if the value is present on the request, and if so, let's see if we should do a 304. If it's there, we parse it into a DateTime and compare the time with the one stored in the business object. We're stripping off the milliseconds because the database will fill them in on our DateTime, and the incoming request doesn't have the same high resolution. If we have a match, we send out the 304 and return, not sending any more data or reading the bytes from the database.

You can do this pretty easily in ASP.NET MVC as well.

public ActionResult Image(int id)
{
    var image = _imageRepository.Get(id);
    if (image == null)
        throw new HttpException(404, "Image not found");
    if (!String.IsNullOrEmpty(Request.Headers["If-Modified-Since"]))
    {
        CultureInfo provider = CultureInfo.InvariantCulture;
        var lastMod = DateTime.ParseExact(Request.Headers["If-Modified-Since"], "r", provider).ToLocalTime();
        if (lastMod == image.TimeStamp.AddMilliseconds(-image.TimeStamp.Millisecond))
        {
            Response.StatusCode = 304;
            Response.StatusDescription = "Not Modified";
            return Content(String.Empty);
        }
    }
    var stream = new MemoryStream(image.GetImage());
    Response.Cache.SetCacheability(HttpCacheability.Public);
    Response.Cache.SetLastModified(image.TimeStamp);
    return File(stream, image.MimeType);
}

Let me start by saying that this was something I just prototyped. It's in dire need of refactoring, as much of the logic isn't stuff you'd normally put in a controller action. I think there's a method for returning nothing on the Controller base, but I don't remember off the top of my head. If there is, you'd use that instead of Content() in the 304 case.

I hope this helps someone out!

Caught in a flesh storm, with a 90% chance of satisfaction

This makes me laugh, in light of tech pundits who overstate the importance of Twitter.

 

The Colbert ReportMon - Thurs 11:30pm / 10:30c
Jeff Goldblum Will Be Missed
www.colbertnation.com
Colbert Report Full EpisodesPolitical HumorJeff Goldblum

 

The Colbert ReportMon - Thurs 11:30pm / 10:30c
Biz Stone
www.colbertnation.com
Colbert Report Full EpisodesPolitical HumorJeff Goldblum
Webforms vs. MVC, the desire to rewrite everything, an unexpected benefit

I read a good post today about the silly wars that go on in versus debates, in this case the arguments about whether to use Webforms or MVC for ASP.NET. I kind of saw this storm coming when people started describing themselves as part of the alternative "movement" in the ASP.NET community.

The truth is that MVC gets me really excited, for a thousand different reasons. My win comes from the fact that I feel like I'm no longer fighting the statelessness of the Web by conforming to a framework that simulates statefullness. Maybe I never really realized I was doing that. But the nice thing about MVC is that it has forced me to break down what I'm doing into simple actions. There are two benefits developing that I had not previously considered.

The first is that the stripped down nature of the MVC pattern causes you to back off if you're someone who does UI development. It can be argued that many of the apps out there now that get all of the press and attention are ridiculously simple and easy to use because they don't try to do a lot, and, by no coincidence, happen to be developed on another MVC framework, Rails. Whether it be Twitter or my wife's favorite site, Ravelry, there is a simple style that seems representative of sites developed using this design pattern.

The second benefit is that adhering to a strict seperation of concerns, whether it be for reasons of testability or the desire to decouple your pieces parts as much as possible (or because "they" said so), makes your code infinitely easier to maintain.

That said, when bouncing back to a Webforms project, I'm amazed at just how much cleaner everything I write is in terms of keeping the moving parts minimally coupled to each other. It's not that I had 10,000-line code-behind files before, but my mindset has changed enough since spending time in MVC that I'm a better developer now when using Webforms.

And when all of the crazy zealots go on and on about how awesome MVC is, I'm not writing that image gallery control for the hundredth time, because I did it once years ago. The simple content management apps, handlers and diagnostic pieces are all there still for me to use, and now I'm wiring it all together in a much cleaner way.

I love MVC. I mean I really dig it. I can't wait to get some of my projects based on it out into the open (other than my personal blog, anyway). But the truth is that the value already built into years of ASP.NET Webforms is not trivialized or bested by the new framework. Instead, there's a great compliment in place now where I can use which ever gets me to market the fastest. At the end of the day, rewriting things for the sake of science doesn't get me paid. Shipping stuff is what puts food on the table. Now my toolbox is a lot bigger.

Silverlight request: Make it work for iPhone apps
Obviously Silverlight runs on OS X. That much we know, since developers like me use it for non-development tasks instead of Windows. How difficult would it be to adapt it to stand-alone apps on the iPhone? Even if it had to include the runtime and base library (at a few megabytes), it would still be pretty cool, and we wouldn't have to use Xcode (which I'm not impressed with).
The joy of learning and surprise

I just read the JJ Abrams essay in the previous issue of Wired. This essay really struck home about where we get joy out of life, and how we seem so eager to overlook it. This quote sums it up for me:

"True understanding (or skill or effort) has become bothersome—an unnecessary headache that impedes our ability to get on with our lives (and most likely skip to something else). Earning the endgame seems so yesterday, especially when we can know whatever we need to know whenever we need to know it."

That is true on more levels than I can describe. While the Internet has done so much to facilitate communication and bring people together, it has also managed to trivilaize knowledge and the process of acquiring it.

I liken this to a suggestion that a friend made to me last year when I was in the midst of writing code for one of my sites. He asked, "Why don't you just use all of the free stuff out there and stictch it together to make a site?" Aside from issues of integration, I asked what I would get out of that as a developer. The "skill and effort" is important to me. Deeper understanding is important to me. It's the same reason someone may build a table instead of buying one from Ikea. Indeed, sometimes the end product is less interesting than the journey required to get there.

ASP.NET MVC book: Not going to happen (for now)

After a great deal of soul searching (and a PDF draft of chapter 1 posted), I've decided that I'm not going to follow through on this book. I've got a total of four chapters, two of which are at 75%, but there are a number of reasons that I've decided to focus my attention elsewhere.

The biggest issue I have right now is that I don't see an obvious personal benefit to following through at this time, especially when I compare it to other projects. Since I'm essentially "self-employed," and foresee that as a lasting condition for some time given the sad job market, I really want to pour more energy into things that look and smell like income. Self-publishing, for all of the benefits, doesn't pay up front the way an advance does through a mainstream publisher and, you know, I like to eat and do summer stuff.

I've also had a lot of fun in the last two months tweaking and analyzing my existing Web sites. CoasterBuzz is doing very well, with page views up 20%. I've been shooting video and photographing rides for the site too, something I love to do but kind of let go of over the years. I'm really getting back in touch with the stuff that motivated me to get into software in the first place.

Perhaps most important, I'm getting back into some basic level of fitness. I'm married again, and I have to look after myself for someone else's benefit as well. The nasty high stress crappy job I lost really had me pushing aside just common sense eating and exercise, and I want to make sure I'm balancing all of that out.

The content I've written so far will not go away, and it will see the light of day one way or another. Perhaps it'll appear as a finished book for a future release, or as a series of long Web pieces. I haven't decided. The simple blogging app used as the example code will be released as well, probably sooner than later (in part because I'm hell bent on proving that 95% of what you want to do can be achieved by 10% of the average "best practice" or "sample" app).

This wasn't an easy decision, especially given all of the wonderful feedback I've received so far (and even some outright hate mail). At the end of the day, I need to chase what gets me out of bed, and unfortunately, this just wasn't it.

Personal blog moved, powered by ASP.NET MVC

I moved my personal blog to a more appropriate domain name, JeffPutz.com. Hooray for vanity names! I'll continue to keep technical and programming junk here. It seemed appropriate though to have a central location for me stuff, including my resume and various media samples, so this is it.

This is the first MVC app that I've put into production, oddly enough. Well, technically it is, though I've supervised the development of MVC apps elsewhere. This little app is what I've been writing my next book around, and it is purposefully as simple as possible. Most of the sample apps I've tried to disect are entirely too complex, and I think that's a barrier for a lot of people. I'll post the code after I've put it through the paces a bit.

Can you afford to blow off a part of your audience?

The other day, me and Diana were talking about the concept of "supported" browsers, and how big corporations often restrict their online applications for use only with certain browsers. This is a throwback to the days when you needed ActiveX or certain IE-only features, and is rooted in old school corporate IT nonsense.

But there are still a lot of financial institutions in particular that keep telling you what browser to use, and that's just stupid. I was looking at the stats for my sites today, and it shows that 15% of visitors are Mac users, and only about 55% are IE users. Even the iPhone is closing in on 1%, which is crazy.

That's the world we live in. If you blow off 15% of your audience, can you afford that? Imagine if Amazon did this. Their holiday quarter did $225 million in profit. Do you think they'd be OK with leaving $33 million on the table?

I ran into another support issue today, when trying to view the video clips for the Halo prequel and the body control stuff for Xbox. I'd love to watch them, but they use some goofy stream that's presumably Windows Media based and I can't watch them on the Mac. Technologist apologists seem hell bent on declaring that this kind of thing is OK, but especially for marketing intent, why would you exclude any percentage of your audience?

I'm not suggesting we all need to test for IE6 at this point, but come on man... with the standards and frameworks we have, it isn't that hard to reach 99% of your audience.

Twitter FAIL

 

And productivity of nerds everywhere skyrocketed! :)

Posted: May 27 2009, 03:14 PM by Jeff | with 1 comment(s)
Filed under:
More Posts Next page »