Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

ASP.NET Image Control With Fallback URL

What happens when the URL that your image is pointing to does not exist or cannot be reached? Well, all browsers I know of resort to displaying something like:

Sometimes, however, we may be able to anticipate that a given image won’t be accessible and instead choose to serve something else. For that, we can rely on the DOM onerror event; in the case of img tags, this event is raised when the target image cannot be displayed. In that situation, we have the opportunity to change its src property to point to a valid, alternative, location.

One control that we use to display images in ASP.NET is the venerable Image. What if we could change this control so that it supports an alternative URL, in case its target image cannot be loaded? It turns out, it is very easy to achieve this! Let’s start with some code:

   1: <asp:Image runat="server" ImageUrl="NonexistentImage.png" FallbackUrl="AlternativeImage.png" />

As you can see, I added an extra FallbackUrl attribute to the control’s declaration. Image won’t mind, because it implements IAttributeAccessor, which, in case you don’t know, allows for having extra attributes, that is, attributes that cannot be mapped to actual properties.

There are two ways to proceed:

  1. Having a control adapter inject some JavaScript onerror handler for all Image with an attribute FallbackUrl (mind you, I talked about control adapters before);
  2. Having a control derived from Image that does the JavaScript injection.

This time, I’ll go for option 2. Let’s implement one such control:

   1: public class ImageWithFallback : Image
   2: {
   3:     [DefaultValue("")]
   4:     [Description("An alternative URL in case the image cannot be loaded")]
   5:     public String FallbackUrl
   6:     {
   7:         get;
   8:         set;
   9:     }
  10:  
  11:     protected override void OnLoad(EventArgs e)
  12:     {
  13:         if (String.IsNullOrWhiteSpace(this.FallbackUrl) == false)
  14:         {
  15:             this.Attributes["onerror"] = String.Format("this.src = '{0}'", this.ResolveUrl(this.FallbackUrl));
  16:         }
  17:  
  18:         base.OnLoad(e);
  19:     }
  20: }

OK, now I have this control, but I have hundreds of already existing declarations of Image. There’s no way I can replace them all… Enter tag mappings!

Tag mappings, as its name implies, allow mapping one tag to another, that is, effectively replacing all instances of a control declared on markup for another control. This other control must be a class that inherits from the declared one. This is the case in my example. Here’s the way to go:

   1: <pages>
   2:     <tagMapping>
   3:         <add tagType="System.Web.UI.WebControls.Image" mappedTagType="MyNamespace.ImageWithFallback, MyAssembly"/>
   4:     </tagMapping>
   5: </pages>

And that’s it! All Image controls on your site, provided you add them a valid FallbackUrl property, will display an alternative image if the target image cannot be found! Easy, don’t you think? Winking smile

Comments

paritosh said:

Sweet and very clean :)

# January 25, 2013 2:25 AM

nideeshm said:

fantastic, learned something new about tag mapping

# January 28, 2013 1:47 AM

peter said:

Is that any way you can saw us how to do it with asp.net mvc3 or 4

# January 29, 2013 4:09 PM

webguy07 said:

I know this is a noob question but I'm running my application as a website and not a project so I don't have a namespace declaration. So my question is, how do I write my <tagMapping> in the web.config? Would it be like below?

<tagMapping>

       <add tagType="System.Web.UI.WebControls.Image" mappedTagType="ImageWithFallback"/>

     </tagMapping>

# January 30, 2013 10:21 AM

webguy07 said:

Nevermind... I solved it :-)

# January 30, 2013 10:32 AM

Ricardo Peres said:

webguy:

Hope you found out about the "App_Code" assembly...?

;-)

# January 31, 2013 2:58 AM

Ricardo Peres said:

peter:

You just need to have an "onerror" event handler to all your images, that's it.

# February 2, 2013 4:54 AM

Ashwin said:

To do it in ASP.NET MVC or any other framework which does not have server controls like these you can use this <img onerror="thi.src=YourImageSrc.png" />

# February 5, 2013 10:35 AM