2

I have a large legacy application, and I would like to move all of our images to a CDN.

Currently, all of our images reside under the application root itself, so the paths are all like "~/Images/MyImage.jpg." Due to the requirements of our system, I MUST determine the full URL for a given image at runtime if it is to live in the CDN. This gives us tight control on versioning, caching, etc. Making code changes image-by-image will be a very long, tedious, and error prone process.

What I would like to do is be able to hook into some mechanism in ASP.NET where I can decide how I want to resolve a tilde for an image. This would allow all our existing code to remain as-is, and images will be directed to the CDN at runtime.

I found some mentionings of VirtualPathProviders, which sounded like it might be what I was looking for, but when I tested it out, the only paths being passed into the CombineVirtualPaths function were paths that ended with .ASPX, .ASCX, and .MASTER.

Can anyone help me find a clean, low-risk option for this?

Basically, what I need is for anywhere in my app where I have "~/images/myimage.jpg" to be rendered to the browser as "http://mycdnhost.com/myimage.jpg". This will avoid having the browser send a request to our server for the image at all.

Brent Miller
  • 111
  • 4

1 Answers1

3

Using IIS Routing

Serving static content from a different site or server. Your Web application is deployed on multiple servers in such a way that dynamic Web content is located on one site or server and all static content is on a different site or server. You can use the URL Rewrite module together with the IIS Application Request Routing module to forward all requests for static files to a different server, while serving all requests for dynamic Web pages from the current server. This way, ASP.NET routing is used only for dynamic Web content and does not evaluate any URLs for static content.

The following example shows a URL rewrite rule that you can use for this scenario:

<rewrite>
    <rules>
        <rule name="Forward to static file server">
            <match url="^.+\.(?:jpg|bmp|gif)$" />
            <action type="Rewrite" url="http://static_file_server/{R:0}" />
        </rule>
    </rules>
</rewrite>

More info at :http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/

Using HttpModule

  1. You should try creating HttpModule that intercept the image request and try to redirect them to your CDN path. First, you need to mapping file extension of image file to the aspnet_isapi in IIS. Then, add a httpmodule that performs url redirecting for those file extension. For instance, in module's beginrequest method:

    void context_BeginRequest(object sender, EventArgs e) { if(request.url.endwith .jpg/.png ...) redirect to a path relative to the root folder. }

  2. Another option using httpmodule is to intercept the html rendered and replace image urls using regex to point to CDN. here you can see how it works http://shoaibsheikh.blogspot.com/2012/05/change-image-url-in-aspnet-using.html

This method will put overhead on asp.net lifecyle because we will have to intercept the whole page before its been sent to client.

Using Control Adapters

You should try ASP.Net Control Adapters if you want to handle only image controls for hijack Image Control Render method and selectively change path to cdn url. This method is less risk and detachable.

 public class CDNImageControlAdapter : ControlAdapter
    {
        protected override void Render(HtmlTextWriter writer)
        {
            Image img = this.Control as Image;
            if (img == null)
            {
                base.Render(writer);
                return;
            }

            if (img.ImageUrl.Length > 0)
            {
                // Let the HyperLink render its begin tag
                img.RenderBeginTag(writer);

                Image image = new Image();

                if (img.ImageUrl.IndexOf("~") == 0)
                {
                    img.ImageUrl = (img.ImageUrl.Replace("~", "http://mycdn.com/images/"));

                }

                img.RenderControl(writer);
            }
            else
            {
                // HyperLink.RenderContents handles a couple of other
                // cases if its ImageUrl property hasn't been set. We
                // delegate to that behavior here.
                base.Render(writer);
            }
        }
    }

and add All.broswer file this in App_Browsers Folder of application

<!--
    You can find existing browser definitions at
    <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers
-->
<browsers>
  <browser id="Default">
    <controlAdapters>
      <adapter controlType="System.Web.UI.WebControls.Image" adapterType="CDNImageControlAdapter, MyWebApplication" />
    </controlAdapters>
  </browser>
</browsers>

Regards.

Shoaib Shaikh
  • 4,565
  • 1
  • 27
  • 35
  • This solution wouldn't be ideal for me, because this would only address the Image control. I want to address ANYWHERE that an image path is specified with a tilde. This could be any number of properties on any number of WebControls, HtmlControls, or 3rd party controls. I need a universal fix. – Brent Miller May 03 '12 at 17:18
  • alright i was thinking you were only concerned about the Image control. In your case you should try using httpmodule but for that you will have to map images extensions to be passed through managed isapi module that might put overhead on asp.net process on server but this is an option. – Shoaib Shaikh May 04 '12 at 05:03
  • Thanks for your update, but it still does not address the exact requirements I have. I updated my question to hopefully add clarity. Your suggestion requires the image request to first come to our server, then get redirected elsewhere. We need for the markup that is originally rendered to the server to have the image path point to an entirely different host. – Brent Miller May 04 '12 at 19:15
  • i have added another option using IIS routing if you can apply that. check that – Shoaib Shaikh May 06 '12 at 17:07
  • Again, the issue is that each solution you have suggested rewrites the path when the request for the image is received by the server. I need to manipulate the path to the image before the path is even sent to the browser to begin with. – Brent Miller May 09 '12 at 12:16
  • i have added another httpmodule option that will intercept the html markup of your code and change image urls using regex. http://shoaibsheikh.blogspot.com/2012/05/change-image-url-in-aspnet-using.html – Shoaib Shaikh May 10 '12 at 05:52