Introduction
This an ASP.NET web control for generating labels as images. You might want to do that for providing security for e-mail crawlers or to disallow copy paste of the text. Many similar controls have been implemented as HttpHandlers, so you need more configuration to make them work. However, this control does not need any configuration. You just need to use it just like any other ASP.NET control like Label
. Almost all of the label formatting options are included, like font size, backcolor, and forecolor.
How does it work
The code can be separated to two parts: the variable initializations, and the render part. The OnInit
event is used for the preparation of a URL string of the image to be generated. The URL string is stored in a private member of the class with the client to make sure that controls draw themselves. There is a trick here. This control is executed twice by the browser. To make things work, the query string is in a predefined format. The browser tries to display the image specified by a tag, and the init code tries to read whether it is coming from a querystring or not to generate the image.
protected override void OnInit(EventArgs e)
{
if (this.Context.Request.QueryString[QueryStringText()] != null)
{
DrawImage(this.Text);
}
this.m_URL = Context.Request.Url.AbsolutePath + "?" +
secretQueryString+ this.ClientID + "=1";
base.OnInit(e);
}
However, there is another problem. Since the browser is executing twice, the control state is also different, so storing the display text value will not work using the ViewState. As a result, I store it in the session variable, that is cleared after rendering the image. The Text
property of the control handles the session and the automatic code generated by the designer. You know, when you set the text of the control from the designer, after compilation, it is executed by the ASP.NET process. I'm telling this because this control runs two controls with different life cycles. "this.Context.Request.QueryString[QueryStringText()]
" makes sure that we are coming from the main page, rather than the forked control.
public string Text
{
get
{
if (DesignMode)
{
if (ViewState["Text"] == null)
ViewState["Text"] = string.Empty;
return (string)ViewState["Text"];
}
else
{
string s = PossiblequeryString();
if (!string.IsNullOrEmpty(s))
return (string)Context.Session[s];
if (Context.Session[SessionText()] == null)
Context.Session[SessionText()] = string.Empty;
return (string)Context.Session[SessionText()];
}
}
set
{
if (DesignMode)
{
ViewState["Text"] = value;
}
else
{
if (PossiblequeryString() == null)
{
Context.Session[SessionText()] = value;
}
}
}
}
The DrawImage
function draws the image in memory and saves to the Response
object. Since the Response.End
method is executed, Render events will not be fired any more at image generation.
strOutput.DrawString(Message, msgFont, new SolidBrush(foreColor), 1, 1);
MemoryStream memStream = new MemoryStream();
bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Png);
Context.Response.Clear();
Context.Response.ContentType = "image/png";
Context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
memStream.WriteTo(Context.Response.OutputStream);
Context.Session.Remove(SessionText());
Context.Response.OutputStream.Flush();
Context.Response.OutputStream.Close();
Context.Response.End();
The Render
code is used for the rendering of the image. It is simply an image HTML tag pointing to the URL generated previously on onInit
. To make the Visual Studio Designer happy and stop it complaining about exceptions, I also added code to render itself as a normal text control in the designer.
protected override void Render(HtmlTextWriter writer)
{
if (DesignMode)
{
base.Render(writer);
}
else
{
writer.AddAttribute(HtmlTextWriterAttribute.Src, this.m_URL);
writer.RenderBeginTag(HtmlTextWriterTag.Img);
writer.RenderEndTag();
}
}
Conclusion
This control works without any configuration, and is easy to use as any other ASP.NET Web Control. It can be used to hide information from crawlers or robots. Although this is not implemented as a CAPTCHA control, that functionality can easily be added to the image generation.