One thing I love about ASP.NET 2.0 and the whole evolution of the Microsoft web platform isn't the "big picture" (stability, performance, interoperability and all that good stuff) but quite often it's the little gems which as a developer suddenly make my life so much easier.

I recently had a fairly simple problem to solve... an existing site that had some images that should only be available to members not casual browsers (yes, I know. right-click, save-as and distribute the file... however once a user does that we're not responsible for who sees it... it wasn't about DRM or restriction... it was about protecting us from accusations of making the content available directly to minors (because, after all, the internet like TV makes a great babysitter)

Now, one of the great things about the combination of IIS6 is that you can create an "application" that allows you to apply custom filters (which you can write in Visual Studio 2005) and use that to control access to any file you like - checking cookies, database settings and a whole host of other information to decide if you want to show the image or something else.

It's surprisingly easy and performance is not impacted noticeably if you keep the code clean and tight

The sample below works on any image which includes "secure" in the filename. It looks for a MembershipID cookie and if it's there displays the image. If not, it replaces it with a default image.... but you could extend it to check user levels against a datasource, or insist on having a valid referrer which matches the current site (to stop leechers) etc....

Imports System
Imports System.Web

Public Class HTTPjpegAccess
    Implements IHttpHandler

    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        Dim MembershipID As String
        Try
            MembershipID = context.Request.Cookies("MembershipID").ToString
        Catch ex As Exception
            MembershipID = ""
        End Try

        Dim FileName As String = context.Server.MapPath(context.Request.FilePath)
        If LCase(FileName).IndexOf("secure") > 0 Then
            If MembershipID <> "" Then
                ' they are a member
            Else
                FileName = System.IO.Path.GetDirectoryName(FileName) & "/restricted.jpg"
            End If
        Else
            ' it's not a secured image
        End If

        context.Response.ContentType = "image/JPEG"
        context.Response.WriteFile(FileName)

    End Sub

    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return True
        End Get
    End Property
End Class

Once the code above has been modified to suit your filenames and/or cookies etc place it (the .dll) in the /bin directory for your site.

In the directory you wish to protect you need to set up a web.config to tell it what handler to use for the filetype - in this case the .jpgs. You will also need to place the default (in this case "restricted.jpg") image in the directory as the failover.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.web>
        <httpHandlers>
            <add verb="*" path="*.jpg" type="HTTPjpegAccess.HTTPjpegAccess, HTTPjpegAccess"/>
        </httpHandlers>
    </system.web>
    
</configuration>

A great article that covers a lot of the theory about how this works, and what else it can do is here at DevX, and also this Microsoft Knowledgebase article