Softwire Blog

Responding to audio “Range” requests in ASP.NET MVC

18 November 2013, by

Range requests are used to request a portion of a file (for example, the first half of an mp3 file).  This is achieved by sending a “Range” header in the HTTP request.

As we found for one of our customers recently, getting this to work for ASP.NET MVC can be a bit tricky.  If you find yourself in a similar position, there are a few things worth bearing in mind:

1. IIS Supports Range Requests natively

IIS already responds appropriately to “Range” request headers and has done so for a long time.  So if your multimedia files are simply being served through IIS, range requests should all just work.  Unfortunately this wasn’t the case for us – all of our audio files live in an Amazon S3 bucket, which means that our requests have to go through the MVC website.

2. ASP.NET does not support range requests natively

This is exactly why it didn’t work for us – as we were going through our MVC site, the requests were being handled by ASP.NET (not IIS), which ignores the “Range” request header.  This is true for .NET Framework up to and including 4.

3. To add support in ASP.NET MVC, you need to write a custom ActionResult

This is what we did to support Range requests.  In the end, we took some code written by someone else (see the first web link at the bottom) and heavily modified it to fit our particular needs.  If you don’t use MVC, then a Request Handler would suffice – indeed, the code we used was for a custom request handler!

4. The ASP.NET Development Server doesn’t like Response Header changes

Generally speaking, the ASP.NET development server is pretty good.  However it does have its limitations – a particularly relevant one is that it can’t handle adding response headers (which is required to properly respond to a “Range” request).  However it doesn’t throw an error; instead it silently fails (though if you put a breakpoint in the right place, it says “This operation requires IIS integrated pipeline”.

So, in order to test the new ActionResult \ Request Handler, you’ll need to deploy to IIS.

5. Amazon S3 doesn’t respect content types

As noted earlier, the audio files are hosted in a bucket on Amazon S3.  When retrieving files from here, the content type returned was always “application/octet-stream” and not, for example, “audio/mpeg” for an mp3 file.

This causes problems down the line – many browsers expect a specific content type to be returned from its range-enabled request and, if the content-type doesn’t match, it just doesn’t work.  We got around this by looking at the file extension and manually changing it (not very elaborate, but it worked in our case!).

6. The Firefox Inspector is annoying for debugging

Browser inspectors were invaluable in confirming this was all working.  However, Firefox’s specific inspector was very frustrating to use as, for some reason, when it sent a request for an audio file it refused to store the request details in the “Network” tab!  Even navigating to the audio file directly didn’t work (it was there for a split second… then gone!).

When you get to testing this, I would recommend doing the initial testing in something else and then confirming Firefox works!

7. Firefox prefers ogg files to mp3

Audio file support for Html 5 isn’t great, with some people supporting mp3, others supporting ogg etc.  Firefox, as of version 21, apparently supports both of these formats.  However, it still seems to prefer ogg over mp3 and will actively ask for that first.

The following web pages were very useful in getting this all working: – By far the most useful page – discusses the problem of range requests in ASP.NET and gives a solution.  This is what we ultimately started with and modified to fit our needs. – Describes an alternative to the code above. – Some background on defining a Custom ActionResult

Continuous Integration Traffic Lights Revamp

26 September 2013, by

The traffic lights I converted to monitor our Continuous Integration builds have been poorly for a bit, but I finally made some time to fix them up.

There were three main issues which needed addressing: a blown lamp holder, an aging relay board and a lack of suitable housing.


Friday Lunch and Learns: C# and .NET

26 April 2013, by

Every Friday lunchtime at Softwire we all get lured into a meeting room with the promise of free food, and one of our colleagues gives a talk on something they’ve been working on recently.

We filmed this talk on C# and .NET, by Sam Carr, so that others can enjoy it too.

NCrunch: Unit testing, the right way?

4 September 2012, by

NCrunch is an automated parallel continuous testing tool for Visual Studio .NET. It intelligently takes responsibility for running automated tests so that you don’t have to, and it gives you a huge amount of useful information about your tests (such as code coverage) inline in your IDE while you work. Basically, it runs your unit tests for you, simplifying your workflow.


Grouping with LINQ

20 August 2012, by

previous article in series

When I was first starting out with LINQ, the method I had most trouble getting my head round was GroupBy. So I wanted to finish this series of posts with a quick how-to on grouping, in case others find the same problem.

In SQL, GROUP BY seems so straightforward. Somehow in LINQ it seems to contrive to cause problems though. But it’s easy when you know how.


Don’t be too lazy – LINQ’s lazy evaluation gotchas

13 August 2012, by

previous article in series

Having discussed how to take advantage of lazy evaluation in LINQ, it only seems right to discuss some of the surprises this might cause you. I’ve picked out a few examples from my own experience of where understanding what’s going on behind the scenes is important to avoid falling into a trap.


Lazy LINQing

6 August 2012, by

previous article in series

This post looks at one reasonably important aspect of how LINQ works under the hood – lazy evaluation.


Simplify with LINQ

30 July 2012, by

Using LINQ to simplify your code

previous article in series

LINQ is all about manipulating data. But actually, so is a remarkably large amount of programming. We’ve already looked at some things you can do with your list of beers using LINQ, but actually if you go back to the example I used to introduce generics, that’s all about manipulating data too:


An introduction to LINQ

23 July 2012, by

previous article in series

This series of posts is about Language Integrated Query (LINQ, pronounced “link”) – a set of libraries providing a means of querying data in C#. It is intended very much as a beginner’s guide, although those who have a basic knowledge of LINQ but don’t have a full understanding of its principles might still find some points of interest.


Generic collections in C#

16 July 2012, by

Over the next few weeks I’ll be publishing a short series of posts introducing Language Integrated Query (LINQ). However to use LINQ well it’s important to have a basic understanding of Generics, so my first post covers this topic. For nostalgia value, I’ve included a little bit of history from the heady days of .NET 1.1, and some advice for anyone who’s coming back to .NET programming having not used it since those days.