Extraneous attributes. Default styles. Stray markup. Sometimes, ASP.NET server controls just don't render the way you want them to. Even in those cases where Microsoft is just trying to be "helpful", sometimes I just want them to get out of the way and let me do my thing. Here, I'll demonstrate a quick-and-dirty way to get rid of that extra markup, using the <asp:Image> tag as an example.
I was greeted this morning by this blog post from my friend Anthony Grace over at CodersBarn.com . In it, Anthony writes:
Recently, I have been experiencing some difficulty applying CSS correctly to some of the OOTB (out-of-the-box) ASP.NET controls. Earlier today, I was trying to apply a CSS image border using the ASP.NET image control, but couldn't get it to render correctly. In the end, I had to use a regular HTML img tag.
Ouch. It seems he's been bitten by the ASP.NET Image Border Style Bug um, Feature. And if you've ever tried to apply border styles via CSS to the <asp:Image> server control, perhaps you've been bitten too.
How ASP.NET Renders the Image Server Control
You see, when you place an Image server control on a page, like this:
<
asp:Image
ID
="Image1"
runat
="server"
ImageUrl
="~/Images/girl.jpg"
/>
Figure 1
It renders onto the page as follows:
<img id="Image1" src="Images/girl.jpg" style="border-width:0px;" />
See that inline style="border-width:0px;" attribute in the img tag? We didn't put that there, Microsoft did. I suspect they do this to get rid of the ugly default border that is applied by most browsers to image hyperlinks. I don't really know. All I know is this a big P.I.T.A. when you're trying to style the <asp:Image> tag via CSS, as you can see from the following example:
<%@ Page Language="C#" %>
<!
DOCTYPE
html
PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
<
html
xmlns
="http://www.w3.org/1999/xhtml"
>
<
head
>
<
title
>
Image Border</
title
>
<
style
type
="text/css"
>
.imageStyle {
padding: 6px;
background-color: #CCCCCC;
border: 2px solid #0099CC;
}
</
style
>
</
head
>
<
body
>
<
form
id
="form1"
>
<
asp:Image
ID
="Image1"
runat
="server"
ImageUrl
="~/Images/girl.jpg"
CssClass
="imageStyle"
/>
</
form
>
</
body
>
</
html
>
Figure 2
The page above results in the following source output:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Image Border</title>
<style type="text/css">
.imageStyle {
padding: 6px;
background-color: #CCCCCC;
border: 2px solid #0099CC;
}
</style>
</head>
<body>
<form id="form1">
<img id="Image1" class="imageStyle" src="Images/girl.jpg" style="border-width:0px;" />
</form>
</body>
</html>
Which, when rendered onto the page, looks like this:
Figure 3
You can see back in Figure 2, we've defined our .imageStyle class and properly specified it via the CssClass property of the Image tag. The background color and padding render fine. So, where did our pretty blue border go? If you understand the cascade part of CSS, you know that the inline style="border-width:0px;" attribute added by the default rendering overrides any border styles we set from the page level, or from an external CSS stylesheet.
Recently, I have been experiencing some difficulty applying CSS correctly to some of the OOTB (out-of-the-box) ASP.NET controls. Earlier today, I was trying to apply a CSS image border using the ASP.NET image control, but couldn't get it to render correctly. In the end, I had to use a regular HTML img tag.
< asp:Image ID ="Image1" runat ="server" ImageUrl ="~/Images/girl.jpg" />
<%@ Page Language="C#" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< title > Image Border</ title >
< style type ="text/css" >
.imageStyle {
padding: 6px;
background-color: #CCCCCC;
border: 2px solid #0099CC;
}
</ style >
</ head >
< body >
< form id ="form1" >
< asp:Image ID ="Image1" runat ="server" ImageUrl ="~/Images/girl.jpg"
CssClass ="imageStyle" />
</ form >
</ body >
</ html >
<head>
<title>Image Border</title>
<style type="text/css">
.imageStyle {
padding: 6px;
background-color: #CCCCCC;
border: 2px solid #0099CC;
}
</style>
</head>
<body>
<form id="form1">
<img id="Image1" class="imageStyle" src="Images/girl.jpg" style="border-width:0px;" />
</form>
</body>
</html>
The Solution
There are actually several workarounds for this. You can override the style in the page's OnPreRender event. You can set the border width on all Image tags at the control level by setting the BorderWidth property (though this pretty much defeats the advantages of using CSS). And of course, you can use a regular HTML tag, which is what Anthony did.
Or, you can forget about using a "workaround" and fix the real problem. You can do that by deriving a new class from System.Web.UI.WebControls.Image and applying it automatically to all <asp:Image> tags in your site via an often-overlooked feature called tag mapping .
First, create a new class (I'm calling this one ImageBorderless ) that derives from Image :
using
System.Web.UI.WebControls;
public class ImageBorderless : Image
{
public override Unit BorderWidth
{
get { return base .BorderWidth.IsEmpty ? Unit.Pixel(0) : base .BorderWidth; }
set { base .BorderWidth = value ; }
}
}
Figure 4
Then, in your web.config file, in the <pages> section of <system.web> , add a tag mapping as follows:
< pages >
< tagMapping >
< add tagType ="System.Web.UI.WebControls.Image" mappedTagType ="ImageBorderless" />
</ tagMapping >
</ pages >
Figure 5
This tag mapping simply maps all instances of the Image tag to the ImageBorderless type.
Rerun the page, and you'll see that pesky style attribute is now gone, and that the page renders correctly.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Image Border</title>
<style type="text/css">
.imageStyle {
padding: 6px;
background-color: #CCCCCC;
border: 2px solid #0099CC;
}
</style>
</head>
<body>
<form id="form1">
<img id="Image1" class="imageStyle" src="Images/girl.jpg" />
</form>
</body>
</html>
Figure 6