Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Ad Rotator Widget Control for BlogEngine.NET

4.50/5 (5 votes)
19 Dec 2008CPOL3 min read 45.2K   394  
BlogEngine.NET Ad Rotator Control provides a simple interface for managing and rotating ads on the blog

Introduction

BlogEngine.NET is an open source .NET blogging project that was born out of a desire for a better blog platform. A blog platform with less complexity, easy customization, and one that takes advantage of the latest .NET features. Being an open source, BlogEngine.NET provides great level of customization and extensibility.

Starting a blog couple months ago, I start looking into available extensions you can download and implement into your own BlogEngine.NET installation. Browsing through the long list of available extensions, I was quite surprise not to find any extensions which would allow adding and managing ads on the blog.

Background

Thinking about the requirements I wanted from such a control, I came out with the following list:

  • Should support any Ad Provider
  • Should allow hide ads for authenticated users, to keep correct impression count
  • Should be easy to manage and allow to keep all my ad script in one repository
  • Should provide not only random but also weighted rotation, allowing to customize frequency with which each ad script is displayed to the users. The idea behind it is to distribute ad impressions between different providers to maximize revenue stream.

Using the Code

The widget consists of AdManagementBase.cs file with a set of common classes for the widget and “Sponsored Links” folder with widget code.

To install it, just copy AdManagementBase.cs into BlogEngine\App_Code\Extensions folder and then copy “Sponsored Links” folder to BlogEngine\widgets folder. The widget now should be available in the widget collection of BlogEngine.NET

InstallWidget.jpg Widget.jpg

To see it working, take a look at the Interview Patterns with C# blog.

Points of Interest

LoadWidget Method

BlogEngine.NET provides a very straight forward interface for implementing widgets and custom extensions. AdRotator class inherits from abstract class WidgetBase which is essentially a child of ASP.NET UserControl class. WidgetBase contains only one abstract method and two abstract properties which need to be implemented:

C#
//This method works as a substitute for Page_Load. 
//You should use this method for data binding etc. instead of Page_Load.
public abstract void LoadWidget();
// Gets the name, must be exactly the same as the folder that contains the widget
public abstract string Name { get; }
// Gets whether or not the widget can be edited.
public abstract bool IsEditable { get; }

The heart of the widget control is the LoadWidget method.

C#
public override void LoadWidget()
{
ASPCache aspCache=new ASPCache(this.Page);
StringDictionary settings = GetSettings();
Boolean hideForAuthenticatedUsers= true;

List<Ad> ads = AdManagementBase.DeSerializeAds
		(settings[AdManagemenConstants.AdCollectionKey]);

ads.ForEach(delegate(Ad ad) { totalWeight += ad.RWeight; });

Boolean.TryParse(settings[AdManagemenConstants.HideAdsForAuthZUsersKey],
			out hideForAuthenticatedUsers);

adManager = new AdManagementBase(aspCache, ads);

if (!IsPostBack)
{
if ((!System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated) || 
			(!hideForAuthenticatedUsers))
ShowAds(totalWeight);
else
adHolder.InnerHtml = AdManagemenConstants.AuthZUserMessage;
}
}

Class WidgetBase isolates widget developers from implementation of settings storage retrieval mechanism by providing GetSettings() function which returns StringDictionary with widget settings specified on the edit screen. Unfortunately this interface works only with strings and doesn't have any internal logic to serialize complex objects. To solve this problem, AdManagement base class uses XmlSerializer and StringWriter to serialize list of Ad objects and persist it in widget settings collection.

C#
public static string SerializeAds(List<Ad> ads)
{
if ((ads == null) || (ads.Count == 0)) return string.Empty;

XmlSerializer serializer = new XmlSerializer(typeof(List<Ad>));
StringWriter stream = new StringWriter();
serializer.Serialize(stream, ads);
return stream.ToString();
}


public static List<Ad> DeSerializeAds(string serializedStream)
{
if (string.IsNullOrEmpty(serializedStream)) return new List<Ad>();

XmlSerializer serializer = new XmlSerializer(typeof(List<Ad>));
return (List<Ad>)serializer.Deserialize(new StringReader(serializedStream));
}

The check for CurrentPrincipal property CurrentPrincipal.Identity.IsAuthenticated allows to display default text instead of ads for all authenticated users and avoid false impressions.

AuthZUser.jpg

Editing Settings

As per BlogEngine documentation, the only way a widget can be editable is by adding a edit.ascx file to the widget folder. However, there are a couple more things that need to be done:

  1. Widget needs to override IsEditable property of WidgetBase class to return true
  2. Widget should contain edit.ascx file with base class inherited from WidgetEditBase
  3. Save method should be implemented to provide logic to save widget settings
C#
public abstract class WidgetEditBase : UserControl
{
// Saves the basic widget settings such as the Title.
public abstract void Save();

// Get settings from data store
public StringDictionary GetSettings()
{
...
}

// Saves settings to data store
protected virtual void SaveSettings(StringDictionary settings)
{
...
}

public static event EventHandler<EventArgs> Saved;
// Occurs when the class is Saved
public static void OnSaved()
}

SponsoredLinks widget overrides Save method and saves two parameters: collection of ad providers and boolean value indicating if the ads should be hidden for authenticated users:

C#
public override void Save()
{
doUpdate();
StringDictionary settings = GetSettings();
settings[AdManagemenConstants.AdCollectionKey] = 
		AdManagementBase.SerializeAds(adCollection);
settings[AdManagemenConstants.HideAdsForAuthZUsersKey] = 
				cbAuthZAds.Checked.ToString();
SaveSettings(settings);
HttpRuntime.Cache.Remove(AdManagemenConstants.WidgetSettingsKey);
HttpRuntime.Cache.Remove(AdManagemenConstants.SerializedAdsKey); 
CurrentIndex = 0;
}

The Ad object also contains such information as name for the script you are using, JavaScript code snippet provided by ad network (Google, YPN, Microsoft, Bride, etc.) and the rotation weight. Use rotation weight to influence the ration of ads delivered from each ad provider. Note: If all of your scripts have weight equal to zero, the ads will have equal probability to be shown. If any of your scripts have weight greater than zero, all the ads with zero weight will not be shown at all.

EditScreen.jpg

Click here for the demo.

History

  • 20th December, 2008: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)