Caching Provider
Since the Q2 2013 SP1 release of Telerik® UI for ASP.NET AJAX, the RadCaptcha makes it possible to create a custom caching provider that allows specifying a storage for the captcha code different than the cache and the session.
The following example demonstrates how to utilize a MS SQL database for this purpose:
-
In the folder App_Code of the web site, a custom class that inherits the abstract class BaseCaptchaCachingProvider is created. The code sample from Example 1 shows the implementation of such class, which uses a database CachingProviderDatabase with table Table_1 that has columns TableKey (type nvarchar) and TableContent (type varbinary):
-
The custom caching provider is registered in the web.config of the web site by setting the fully qualified name of the storage type to the following key. If the captcha is used in a web application scenario, the namespace of the application may need to be included in the fully qualified name:
XML<appSettings> <add key="Telerik.Web.CaptchaImageStorageProviderTypeName" value="DBImageStorageProvider, App_Code.lfcwuanr, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"/> </appSettings>
-
Finally, the property ImageStorageLocation of RadCaptcha is set to Custom:
ASPNET<telerik:RadCaptcha ID="Captcha1" runat="server" ErrorMessage="The entered code is incorrect" CaptchaMaxTimeout="1" ImageStorageLocation="Custom"> </telerik:RadCaptcha>
Example 1: Implementation of custom caching provider (MS SQL database) for RadCaptcha.
using System;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web;
using Telerik.Web.UI;
using Telerik.Web.UI.Captcha;
public class DBImageStorageProvider : BaseCaptchaCachingProvider
{
public DBImageStorageProvider(HttpContext context) : base(context)
{
}
// Defines if a cache dependency should be applied to the cached object.
public override bool ShouldAddCacheDependecy
{
get{ return true; }
}
// Saves the CachedImage into the storage.
public override void Save(string key, CaptchaImage image)
{
using(var conn = GetConnection(connectionString))
{
conn.Open();
using(var command = new SqlCommand("INSERT INTO [Table_1] ([TableKey], [TableContent]) VALUES (@key, @value)", conn))
{
using(var ms = SerializeImage(image))
{
command.Parameters.Add(new SqlParameter("key", key));
command.Parameters.Add(new SqlParameter("value", ms));
command.ExecuteNonQuery();
}
}
}
}
// Retrieves the cached image from the storage.
public override CaptchaImage Load(string key)
{
CaptchaImage result = null;
using(var conn = GetConnection(connectionString))
{
conn.Open();
using(var command = new SqlCommand("SELECT [TableContent] FROM [Table_1] WHERE [TableKey] = @key", conn))
{
command.Parameters.Add(new SqlParameter("key", key));
byte[] bData = (byte[])command.ExecuteScalar();
using(var ms = new MemoryStream())
{
result = DeserializeImage(bData, ms);
}
}
}
return result;
}
// Removes the cached image from the storage.
public override void Clear(string key)
{
using(var conn = GetConnection(connectionString))
{
conn.Open();
using(var command = new SqlCommand("DELETE FROM [Table_1] WHERE [TableKey] = @key", conn))
{
command.Parameters.Add(new SqlParameter("key", key));
command.ExecuteNonQuery();
}
}
}
private static string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|CachingProviderDatabase.mdf;Integrated Security=True;User Instance=True;";
// Creates a new SQL connection.
private SqlConnection GetConnection(string connString)
{
return new SqlConnection(connString);
}
// Serializes image to memory stream.
private MemoryStream SerializeImage(CaptchaImage image)
{
var ms = new MemoryStream();
var bFormatter = new BinaryFormatter();
bFormatter.Serialize(ms, image);
ms.Seek(0,0);
return ms;
}
// De-serializes image from memory stream.
private CaptchaImage DeserializeImage(byte[] bData, MemoryStream ms)
{
var bFormatter = new BinaryFormatter();
ms.Write(bData, 0, bData.Length);
ms.Seek(0, 0);
return (CaptchaImage)bFormatter.Deserialize(ms);
}
}