Introduction
In this article, I would like to present my Banner Rotator control. The idea of it is different from that of the ASP.NET AdRotator control. This control is database-driven, and banners are rotated at a specific time (not during page refresh). Each banner will have a display time (in seconds) to move to the next banner (a JavaScript does the rotation on the client side).
The source code (ASP.NET Server Control Project) and the ASP.NET website for testing the control are attached at the top of this article. I am going to explain, step by step, the following:
- The control features
- How to use it
- The different ways of using the control
- Explanation of the ASP.NET Server Control (Class Library)
The control features
- Database-driven: Banner specifications such as width, height, and if clickable are got from the database, so is the list of banners. The banners load from the database once and they rotate on the client-side.
- Supports most image formats (JPG, GIF, BMP, and PNG, and also Flash files (swf)).
- Cache: User can enable caching in the control and specify the cache duration. This will reduce the load of the database.
- Hit counter functionality for each banner.
- Supports multiple languages.
- Fully customizable by the developer: they can control the way it will be display, repeating vertically and horizontally, reserve the banner area even if there are no banners loaded, and specify a condition for the banner display based on the page URL, querystring and any user-defined conditions.
How to use it
- Copy the DLL file "BannerRotatorControl.dll" into your ASP.NET application's "bin" folder.
- Register the control in your ASPX page:
<%@ Register TagPrefix="BMS" Namespace="BannerRotatorControl"
Assembly="BannerRotatorControl" %>
Use it in your ASPX page like this:
<BMS:BannerRotator runat="server" ID="banner1"
ConnectionString="<%$ ConnectionStrings:bms_db %>"
BannersLanguage="en" LocationCode="TOP"
BannerImagesURL="<%$ appSettings:bms_data %>"
BannerClickFile="~/click.aspx" ScriptsPath="/scripts/"
ShowOnlyActivatedBanners="true" />
There are five mandatory properties of the BannerRotator
control to be set:
ConnectionString
: Connection string of your database that contains the banner control tables. (The files bms_db.mdf, bms_db.ldf are included in the source.)BannersLanguage
and LocationCode
: These are mandatory properties. They are the main properties that tell the BannerRotator
to read data from the database based on the following tables:
BMS_BANNERS_AREAS contains the list of banner areas. In the above ASP.NET control, I have set BannersLanguage="en" LocationCode="TOP"
which tells the control to read the banner area record in which lang="en"
and location_code="TOP"
(highlighted one) and draw a banner area based on the information specified in these record fields:
Widthpx
Heightpx
NoAds_image
: This will control the banner area to be reserved even if there are no banners for this area.
Master table of languages
Master table containing the list of locations (Location means the page location - Left, Right, Top, and Bottom)
BannerImagesURL
: This property tells the control the banner image file location URL. I have set the property above to read from the appSettings
key of the web.config:
<add key="bms_data" value="http://localhost/biznet-data/bms_test/{0}/banners/"/>
"biznet-data" is a virtual directory created in IIS, and points to the folder "c:\Biznet_data\bms_test\en\banners\". Note that I have used {0} to be replaced by the banner language.
Some other properties in the above ASP.NET control code includes:
BannerClickFile
: This will specify if the banner is clickable or not. This is the path of the file click ASPX page in your ASP.NET website. There, you have write code to update the banner click counts and redirect to the specified URL link:
protected void Page_Load(object sender, EventArgs e)
{
string urlstr = BannerRotatorControl.BannerRotator.UpdateBannerClick(
ConfigurationManager.ConnectionStrings["bms_db"].ToString());
if (!string.IsNullOrEmpty(urlstr))
Response.Redirect(urlstr);
}
ScriptsPath
: This property is important if you plan to use Flash files in your banner control. You should specify the Flash JavaScript script path for the Flash loader:
ShowOnlyActivatedBanners
: Set this to true if you want to show only the activated banners, or false to show all banners (set it to false if you use the banner rotator in the Banner Management Admin site).
Different ways of using the BannerRotator control
We can use the control in different scenarios; I am going to list the most common ones:
- Single reserved banner area rotating multiple banners
In this scenario, we want to have a banner area (468 X 60 pixels) on the top of the page which shows an "Advertising Space" image if there are no banners added in this area yet. Otherwise, it will show the banners and rotate them based on the display time (in seconds) specified for each banner.
The BannerRotator
control code will be:
<BMS:BannerRotator runat="server" ID="banner1"
ConnectionString="<%$ ConnectionStrings:bms_db %>"
BannersLanguage="en" LocationCode="TOP"
BannerImagesURL="<%$ appSettings:bms_data %>"
BannerClickFile="~/click.aspx" ScriptsPath="/scripts/"
ShowOnlyActivatedBanners="true" Repeat="NoRepeat" />
Based on the properties set in the control, the control will read the above record, and because the "Repeat
" property is set to "NoRepeat
", it will select the top record ordered by the "ls_order
" field ascending. The result of the banner display will be as follows:
Because no banners were added yet in the "BMS_BANNERS" table under this record, and also the "NoAds_image
" field is not null, this will tell the banner to reserve the area and show the image specified in that field.
We add banner records in the "BMS_BANNERS" table under this record, as in the image below:
Based on the above records image, the banner rotator control will start displaying the banners and rotate them based on the listing order "ls_order
".
- The first banner that will be displayed is "BCCI_en_ad_eztrade468X60.jpg" for 3 seconds, and it will be clickable since "
link_url
" is set to "http://www.eztrade.bh/". - The second banner is "bcci_en_shops_eztrade.gif", displayed for 2 seconds, and it will not be clickable because "
link_url
" is null. - The last one is "bcci_en_banner1.swf" (a Flash banner), displayed for 7 seconds.
- Then it will loop back again.
- Multiple banner areas with a single banner each
In this scenario, we want to display four equal sized banners (202 X 96 pixels) on the left side of the page and listed vertically. They are not clickable.
First, add four records in the "BMS_BANNERS_AREAS" table as below:
Then, add the code in your ASPX page, as below:
<BMS:BannerRotator runat="server" ID="BannerRotator1"
ConnectionString="<%$ ConnectionStrings:bms_db %>"
BannersLanguage="en" LocationCode="LFT"
ScriptsPath="/scripts/" BannerImagesURL="<%$ appSettings:bms_data %>"
Repeat="RepeatY" VerticalSpacing="5"
ShowOnlyActivatedBanners="true"/>
The code above will read all records with location_code="LFT"
and lang="en"
, ordered by "ls_order
" because the "Repeat
" property is set to "RepeatY
" (list vertically). It will not reserve any banner area because all the records have null values in the "NoAds_image
" field. It will only show the banners added in that area, if any.
We add a banner record in the "BMS_BANNERS" table for each banner area above:
Based on the above records, the result of the banner control will be like this:
I have set the "VerticalSpacing
" property to "5".
- Multiple reserved banner areas with multiple banners
In this scenario, we want to have three banner areas with different sizes on the right side of the page. The first two banner areas have a size of 157 X 55 pixels, and the third one is 157 X 264 pixels. We want to list them vertically. All of them should show the "Advertising Space" image, if there are no banners added yet.
The code will be:
<BMS:BannerRotator runat="server" ID="BannerRotator2"
ConnectionString="<%$ ConnectionStrings:bms_db %>"
BannerImagesURL="<%$ appSettings:bms_data %>"
BannersLanguage="en" LocationCode="RGT"
Repeat="RepeatY" VerticalSpacing="5"
ShowOnlyActivatedBanners="true"
BorderWidth="1" BorderColor="Red"
BorderStyle="Solid" BannerClickFile="~/click.aspx" />
Based on the records, the banner control will display three banner areas with the "Advertising Space" image. Because the "NoAds_image
" field is not null for all of them, and there are no banners added yet for all of them, the result will be like this:
We add two records in the "BMS_BANNERS" table under the first banner area:
Base on the above records image, the banner rotator control will start displaying the banners and rotate them based on the listing order "ls_order" (first banner area).
- First banner will be displayed is "bcci_en_btn.jpg" for 4 seconds and it will be clickable since the "link_url" is set to "http://www.bahraintradanet.com/".
- Second banner is "bcci_en_gtn.jpg" for 6 seconds and it will be clickable since the "link_url" is set to "http://www.gulftradanet.com/".
- Then it will loop back again.
- Conditionally displaying banner in a banner area
In this scenario, we are going to take the first scenario and add a little advanced functionality. We want to control the display of banners based on "PageURL
", "QueryString
", "Session
", "Cookies
", and "UserDefined
".
As I mentioned above, the top banner are has three banners: banner_id=14, banner_id=15, and banner_id=16. We want to display banner_id=14 only when the page URL is "/BannerRotator_test/default.aspx" or when we have the query string "q=1".
The ASP.NET code:
<BMS:BannerRotator BannersLanguage="en" ConnectionString="<%$
ConnectionStrings:bms_db %>" LocationCode="TOP"
ScriptsPath="/scripts/" runat="server" ID="banner1"
BannerImagesURL="<%$ appSettings:bms_data %>"
BannerClickFile="~/click.aspx"
ShowOnlyActivatedBanners="true" Repeat="NoRepeat" >
<BMS:BannerDisplayCheck ParameterType="PageURL" />
<BMS:BannerDisplayCheck ParameterType="QueryString" ParameterName="q" />
<BMS:BannerDisplayCheck ParameterType="Session" ParameterName="my_session" />
<BMS:BannerDisplayCheck ParameterType="Cookie" ParameterName="my_cookie" />
<BMS:BannerDisplayCheck ParameterType="UserDefined" />
</BMS:BannerRotator>
The "BannerDisplayCheck
" parameters will tell the banner rotator to check in the "BMS_BANNER_DISPLAY_CRITERIAS" table and compare values and display the banner according to the matching criteria. Here are the parameter types and usage:
PageURL
: This will tell the banner control to lookup "BMS_BANNER_DISPLAY_CRITERIAS
" with a "criteria_code
" equal to "PageURL
" and compare the current ASPX page URL with the "criteria_value
" field. If matched, then the banner_id
of this row can be displayed.QueryString
: This will tell the banner control to lookup "BMS_BANNER_DISPLAY_CRITERIAS
" with a "criteria_code
" equal to "QueryString
" and check the current ASPX page URL querystring name matching "ParameterName
". Then, it compares the querystring value with the "criteria_value
" field. If matched, then the banner_id
of this row can be displayed.Session
: This will tell the banner control to lookup "BMS_BANNER_DISPLAY_CRITERIAS
" with a "criteria_code
" equal to "Session
" and check if there is any session object with the same name as "ParameterName
". Then it compares the session object value with the "criteria_value
" field. If matched, then the banner_id
of this row can be displayed.Cookie
: This will tell the banner control to lookup "BMS_BANNER_DISPLAY_CRITERIAS
" with a "criteria_code
" equal to "Cookie
" and check if there is any cookie object with the same name as "ParameterName
". Then it compare the cookie object value with the "criteria_value
" field. If matched, then the banner_id
of this row can be displayed.UserDefined
: This will tell the banner control to lookup "BMS_BANNER_DISPLAY_CRITERIAS
" with a "criteria_code
" equal to "UserDefined
", and it will compare the value entered by the user in the "UserDefinedParameterValue
" property of the control value with the "criteria_value
" field. If matched, then the banner_id
of this row can be displayed.
The class library
The idea of the control is to get banners from the database and rotate them based on a specified time for each banner. Initially, I utilised AJAX to do the job. I used the AJAX Timer
and UpdatePanel
controls. I used the timer tick event to display the next banner. But that was a very bad approach because it takes up a lot of resources from the server and bandwidth. The biggest disadvantage of the UpdatePanel
is that it still sends all the viewstate back and forth, so you use up a lot of bandwidth. Another one's that most of the page life cycle still gets run.
I continued using AJAX with Web Services for better performance and less bandwidth usage, returning JSON data back and using JavaScript in the browser to make up the HTML and inject it in the page. This enhanced performance, but I was not happy because, again for each timer tick event, I had to read the next banner record from the database.
Finally, I came up with this control, which reads all the banners once from the database and generates HTML and JavaScript to do the rotation on the client side, using the JavaScript function "setTimeout
". This is done in the control "RenderContents
" event. Below is an example of the generated banner rotation code:
<div id="Banner115"></div>
<script type="text/javascript">
var BannerHtml_arr15= new Array();
var swfId_arr15 = new Array();
var DisplayTimeSeconds_arr15 = new Array();
var banner_count15 =0;
var BannerHtml15=null;
var swfId15=null;
var BannerIndex15=0;
banner_count15=3
BannerHtml_arr15[0]="<a href='http://www.codeproject.com/BannerRotator" +
"_test/click.aspx?clickid=6418cd46-791a-40e1-9c11-e3e732977" +
"dc2452¶ms=PageURL%7c%2fBannerRotator_test%2fDefault" +
".aspx' target='_blank' title='Eztrade.bh'><img" +
" src='http://localhost/biznet-data/bms_test/en/banners/" +
"BCCI_en_ad_eztrade468X60.jpg' style='border:Solid " +
"0px black;' width='468' height='60'></a>";
swfId_arr15[0]='';
DisplayTimeSeconds_arr15[0]='3000';
BannerHtml_arr15[1]="<img src='http://localhost/biznet-data/" +
"bms_test/en/banners/bcci_en_shops_eztrade.gif' style='border:" +
"Solid 0px black;' width='468' height='60' title='Eztrade Shops'>";
swfId_arr15[1]='';
DisplayTimeSeconds_arr15[1]='2000';
BannerHtml_arr15[2]="";
swfId_arr15[2]='http://localhost/biznet-data/bms_test/en/banners/bcci_en_banner1';
DisplayTimeSeconds_arr15[2]='7000';
function DisplayBanner15()
{
if (BannerHtml15!=null || swfId15!=null)
{
if (BannerHtml15!=null) {
document.getElementById('Banner115').innerHTML =BannerHtml15;
}
else if (swfId15!=null) {
var lcId15 = new Date().getTime();
var flashProxy15 = new FlashProxy(lcId15,
'/BannerRotator_test/scripts/JavaScriptFlashGateway.js');
var flashObject15 = new FlashTag(swfId15+'.swf',468,60, '8,0,0,0');
flashObject15.setFlashvars('lcId=' + lcId15);
flashObject15.write(document.getElementById('Banner115'));
}
}
if (banner_count15>1)
setTimeout('DisplayBanner15()',
DisplayTimeSeconds_arr15[BannerIndex15],'JavaScript')
BannerIndex15++;
if (BannerIndex15 >= banner_count15)
BannerIndex15=0;
SetValues15();
}
function SetValues15()
{
if (BannerHtml_arr15[BannerIndex15]!=null && BannerHtml_arr15[BannerIndex15]!='')
BannerHtml15 = BannerHtml_arr15[BannerIndex15];
else
BannerHtml15 = null;
if (swfId_arr15[BannerIndex15]!=null && swfId_arr15[BannerIndex15]!='')
swfId15 = swfId_arr15[BannerIndex15];
else
swfId15 = null;
}
function LoadBanners15()
{
if (BannerIndex15==0)
{
SetValues15();
DisplayBanner15();
}
}
LoadBanners15();
</script>
Before I start, here is a screenshot of the banner control database:
The code is called from the "RenderContents
" event of the control. Initially, we get a list of banner areas by calling the following function:
protected DataTable GetBannerArea()
{
DataTable retVal = null;
string sql = "select ";
if (_Repeat == RepeatOptions.NoRepeat)
sql += "top 1 ";
sql += " * from BMS_BANNERS_AREAS where location_code=@location_code" +
" and lang=@lang and Active_flag='1' order by ls_order";
SqlConnection conn = new SqlConnection(_ConnectionString);
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
try
{
da.SelectCommand.Parameters.AddWithValue("location_code", _LocationCode);
da.SelectCommand.Parameters.AddWithValue("lang", _lang);
DataTable dt = new DataTable();
if (_EnableCaching)
{
DataTable dt_c = HttpContext.Current.Cache["AdRotator_" +
_Repeat.ToString() + "_" +
_LocationCode + "_" + _lang] as DataTable;
if (dt_c != null)
dt = dt_c;
else
{
da.Fill(dt);
HttpContext.Current.Cache.Insert("AdRotator_" +
_Repeat.ToString() + "_" + _LocationCode + "_" +
_lang, dt, null,
DateTime.Now.AddMinutes(_CacheDuration), TimeSpan.Zero);
}
}
else
da.Fill(dt);
da.Dispose();
conn.Dispose();
retVal = dt;
}
catch (Exception ex)
{
throw new Exception("Exception Accured in : protected" +
" void GetBannerArea(). For More Details " +
"See Inner Exception Message", ex);
}
return retVal;
}
The above function will retrieve the banner areas from the "BMS_BANNERS_AREAS" table based on "Location_code
" and "Lang
". Each row will define a banner area with a dimension. I call the function to get a DataTable
with the results.
DataTable dt_banner_areas = GetBannerArea();
Then, I loop through the records to render the HTML and JavaScript code. Refer to the generated example above.
foreach (DataRow dr in dt_banner_areas.Rows)
{
_banner_area_id = Convert.ToString(dr["banner_area_id"]);
_Width = Convert.ToString(dr["widthpx"]);
_Height = Convert.ToString(dr["hieghtpx"]);
if (!string.IsNullOrEmpty(Convert.ToString(dr["NoAds_image"])))
_NoAdFile = string.Format(_bms_data_url, _lang) +
Convert.ToString(dr["NoAds_image"]);
_NoAdAlt = Convert.ToString(dr["NoAds_imageAlt"]);
if (dt_banner_areas.Rows.Count > 1)
{
if (_Repeat == RepeatOptions.RepeatX)
sb.Append("" + Environment.NewLine);
else if (_Repeat == RepeatOptions.RepeatY)
sb.Append("" + Environment.NewLine);
}
sb.Append(@"<div id=""Banner1" +
_banner_area_id + @""">" + Environment.NewLine);
sb.Append("</div>" + Environment.NewLine);
sb.Append(@"<script type=""text/javascript"">" +
Environment.NewLine);
sb.Append(@"var BannerHtml_arr" + _banner_area_id +
"= new Array();" + Environment.NewLine);
sb.Append(@"var swfId_arr" + _banner_area_id +
" = new Array();" + Environment.NewLine);
sb.Append(@"var DisplayTimeSeconds_arr" + _banner_area_id +
" = new Array();" + Environment.NewLine);
sb.Append(@"var banner_count" + _banner_area_id +
" =0;" + Environment.NewLine);
sb.Append(@"var BannerHtml" + _banner_area_id +
"=null;" + Environment.NewLine);
sb.Append(@"var swfId" + _banner_area_id +
"=null;" + Environment.NewLine);
sb.Append(@"var BannerIndex" + _banner_area_id +
"=0;" + Environment.NewLine);
sb.Append(GenerateJavascriptArrayItems());
sb.Append(@"function DisplayBanner" +
_banner_area_id + "()" + Environment.NewLine);
sb.Append(@"{" + Environment.NewLine);
sb.Append(@"if (BannerHtml" + _banner_area_id +
"!=null || swfId" + _banner_area_id +
"!=null)" + Environment.NewLine);
sb.Append(@"{" + Environment.NewLine);
sb.Append(@"if (BannerHtml" + _banner_area_id + "!=null) {" + Environment.NewLine);
sb.Append(@"document.getElementById('Banner1" +
_banner_area_id + "').innerHTML =BannerHtml" +
_banner_area_id + ";" + Environment.NewLine);
sb.Append(@"}" + Environment.NewLine);
sb.Append(@"else if (swfId" + _banner_area_id + "!=null) {" + Environment.NewLine);
sb.Append(@"//loading flash object using java script." + Environment.NewLine);
sb.Append(@"var lcId" + _banner_area_id +
" = new Date().getTime();" + Environment.NewLine);
sb.Append(@"var flashProxy" + _banner_area_id +
" = new FlashProxy(lcId" + _banner_area_id + ", '" +
VirtualPathUtility.ToAbsolute("~" + _JavaScriptFlashGateway_path +
"JavaScriptFlashGateway.js") + "');" + Environment.NewLine);
sb.Append(@"var flashObject" + _banner_area_id +
" = new FlashTag(swfId" + _banner_area_id +
"+'.swf'," + _Width + "," + _Height +
", '8,0,0,0');" + Environment.NewLine);
sb.Append(@"flashObject" + _banner_area_id +
".setFlashvars('lcId=' + lcId" + _banner_area_id +
");" + Environment.NewLine);
sb.Append(@"flashObject" + _banner_area_id +
".write(document.getElementById('Banner1" +
_banner_area_id + "'));" + Environment.NewLine);
sb.Append(@"}" + Environment.NewLine);
sb.Append(@"}" + Environment.NewLine);
sb.Append(@"if (banner_count" + _banner_area_id + ">1)" + Environment.NewLine);
sb.Append(@"setTimeout('DisplayBanner" + _banner_area_id +
"()',DisplayTimeSeconds_arr" + _banner_area_id +
"[BannerIndex" + _banner_area_id +
"],'JavaScript')" + Environment.NewLine);
sb.Append(@"BannerIndex" + _banner_area_id + "++;" + Environment.NewLine);
sb.Append(@"if (BannerIndex" + _banner_area_id +
" >= banner_count" + _banner_area_id +
")" + Environment.NewLine);
sb.Append(@"BannerIndex" + _banner_area_id + "=0;" + Environment.NewLine);
sb.Append(@"SetValues" + _banner_area_id + "();" + Environment.NewLine);
sb.Append(@"}" + Environment.NewLine);
sb.Append(@"function SetValues" + _banner_area_id + "()" + Environment.NewLine);
sb.Append(@"{" + Environment.NewLine);
sb.Append(@"if (BannerHtml_arr" + _banner_area_id +
"[BannerIndex" + _banner_area_id +
"]!=null && BannerHtml_arr" + _banner_area_id +
"[BannerIndex" + _banner_area_id + "]!='')" + Environment.NewLine);
sb.Append(@"BannerHtml" + _banner_area_id +
" = BannerHtml_arr" + _banner_area_id +
"[BannerIndex" + _banner_area_id +
"];" + Environment.NewLine);
sb.Append(@"else" + Environment.NewLine);
sb.Append(@"BannerHtml" + _banner_area_id + " = null;" + Environment.NewLine);
sb.Append(@"if (swfId_arr" + _banner_area_id +
"[BannerIndex" + _banner_area_id +
"]!=null && swfId_arr" + _banner_area_id +
"[BannerIndex" + _banner_area_id + "]!='')" + Environment.NewLine);
sb.Append(@"swfId" + _banner_area_id + " = swfId_arr" +
_banner_area_id + "[BannerIndex" +
_banner_area_id + "];" + Environment.NewLine);
sb.Append(@"else" + Environment.NewLine);
sb.Append(@"swfId" + _banner_area_id + " = null;" + Environment.NewLine);
sb.Append(@"}" + Environment.NewLine);
sb.Append(@"function LoadBanners" +
_banner_area_id + "()" + Environment.NewLine);
sb.Append(@"{" + Environment.NewLine);
sb.Append(@"if (BannerIndex" + _banner_area_id + "==0)" + Environment.NewLine);
sb.Append(@"{" + Environment.NewLine);
sb.Append(@"SetValues" + _banner_area_id + "();" + Environment.NewLine);
sb.Append(@"DisplayBanner" + _banner_area_id + "();" + Environment.NewLine);
sb.Append(@"}" + Environment.NewLine);
sb.Append(@"}" + Environment.NewLine);
sb.Append(@"LoadBanners" + _banner_area_id + "();" + Environment.NewLine);
sb.Append(@"</script>" + Environment.NewLine);
}
Note, I call the function "GenerateJavascriptArrayItems
" to generate the array items for the JavaScript. This function is the one that gets all the banner records added under a particular banner area.
protected string GenerateJavascriptArrayItems()
{
string retVal = null;
DataTable dt = GetBannersWithinArea();
int i = 0;
if (dt.Rows.Count > 0)
{
retVal += "banner_count" + _banner_area_id + "=" +
dt.Rows.Count.ToString() +
Environment.NewLine + Environment.NewLine;
foreach (DataRow dr in dt.Rows)
{
GenerateBannerHTML(dr);
retVal += "BannerHtml_arr" + _banner_area_id +
"[" + i.ToString() + "]=\"" +
_BannerHtml + "\";" + Environment.NewLine;
retVal += "swfId_arr" + _banner_area_id + "[" +
i.ToString() + "]='" + _swfId +
"';" + Environment.NewLine;
retVal += "DisplayTimeSeconds_arr" + _banner_area_id +
"[" + i.ToString() + "]='" +
_DisplayTimeSeconds + "';" +
Environment.NewLine + Environment.NewLine;
i++;
_BannerHtml = null;
_swfId = null;
_DisplayTimeSeconds = 0;
}
}
else
{
GenerateBannerHTML(null);
retVal += "BannerHtml_arr" + _banner_area_id + "[0]=\"" +
_BannerHtml + "\";" + Environment.NewLine;
retVal += "swfId_arr" + _banner_area_id + "[0]='" +
_swfId + "';" + Environment.NewLine;
retVal += "DisplayTimeSeconds_arr" + _banner_area_id +
"[0]='" + _DisplayTimeSeconds + "';" +
Environment.NewLine + Environment.NewLine;
}
return retVal;
}
In the above function, I call another function "GetBannersWithinArea
" to get the banners of a particular banner area, then loop through the records to generate the JavaScript array items. I am calling another function "GenerateBannerHTML
". This function will assign the HTML markup to the variable "_BannerHtml
".
protected DataTable GetBannersWithinArea()
{
DataTable retVal = null;
string sql = "select * from BMS_BANNERS";
sql += " where banner_area_id=" + _banner_area_id;
sql += " and CONVERT(varchar(10),expiry_date,121) " +
">=CONVERT(varchar(10),getdate(),121) ";
sql += " and CONVERT(varchar(10),getdate(),121) " +
">=CONVERT(varchar(10),start_date,121) ";
string BannerDisplaySqlConditions = GetBannerDisplaySqlConditions();
if (!string.IsNullOrEmpty(BannerDisplaySqlConditions))
sql += BannerDisplaySqlConditions;
if (_ShowOnlyActivatedBanners)
sql += " and active_flag='1' ";
sql += " order by ls_order";
SqlConnection conn = new SqlConnection(_ConnectionString);
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
DataTable dt = new DataTable();
try
{
if (_EnableCaching)
{
string c_BannerDisplaySqlConditions = null;
if (!string.IsNullOrEmpty(BannerDisplaySqlConditions))
{
c_BannerDisplaySqlConditions = BannerDisplaySqlConditions.Replace(" ", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace("'", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace(">", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace("<", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace("(", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace(")", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace(":", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace("/", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace(@"\", "_");
c_BannerDisplaySqlConditions = c_BannerDisplaySqlConditions.Replace("=", "_");
}
DataTable dt_c = HttpContext.Current.Cache["AdRotator_" + _banner_area_id +
"_" + _ShowOnlyActivatedBanners + "_" +
c_BannerDisplaySqlConditions] as DataTable;
if (dt_c != null)
dt = dt_c;
else
{
da.Fill(dt);
HttpContext.Current.Cache.Insert("AdRotator_" + _banner_area_id +
"_" + _ShowOnlyActivatedBanners + "_" +
c_BannerDisplaySqlConditions, dt, null,
DateTime.Now.AddMinutes(_CacheDuration), TimeSpan.Zero);
}
}
else
da.Fill(dt);
da.Dispose();
retVal = dt;
}
catch (Exception ex)
{
throw ex;
}
finally
{
conn.Dispose();
}
return retVal;
}
The above function will retrieve the banner records from the table "BMS_BANNERS" based on "banner_area_id
".
I would also like to mention that I have implemented a properties collection. These are the "BannerDisplayCheck
" parameters which I mentioned under the title "Conditionally displaying banner in a banner area" above.
For that, I have created a separate class, BannerDisplayCheck
.
using System;
using System.Collections;
using System.ComponentModel;
using System.Web.UI;
namespace BannerRotatorControl
{
[TypeConverter(typeof(ExpandableObjectConverter))]
public class BannerDisplayCheck
{
public enum CriteriaTypes
{
PageURL, QueryString, Session, Cookie, UserDefined
}
protected CriteriaTypes _criteraType = CriteriaTypes.PageURL;
protected string _CriteriaName = null;
public BannerDisplayCheck()
: this(CriteriaTypes.PageURL, string.Empty)
{
}
public BannerDisplayCheck(CriteriaTypes CriteriaType, string Name)
{
_criteraType = CriteriaType;
_CriteriaName = Name;
}
[
Category("Behavior"),
DefaultValue(""),
Description("List of Different types of parameters: " +
"PageURL, QuertString, Session, Cookie"),
NotifyParentProperty(true),
]
public CriteriaTypes ParameterType
{
get
{
return _criteraType;
}
set
{
_criteraType = value;
}
}
[
Category("Behavior"),
DefaultValue(""),
Description("ParameterName: exmaple: Name " +
"of the QueryString, Session,Coookie"),
NotifyParentProperty(true)
]
public string ParameterName
{
get
{
return _CriteriaName;
}
set
{
_CriteriaName = value;
}
}
}
}
Then, in my main class "BannerRotator
", I have implemented the "INamingContainer
" interface:
[ParseChildren(true, "BannerDisplayCheckCollection")]
[PersistChildren(false)]
[ToolboxData("<{0}:BannerRotator runat="server">")]
public class BannerRotator : WebControl, INamingContainer
Then the following public property will take care of collecting attributes information from the user:
[
Category("Behavior"),
Description("The BannerDisplayCheck collection"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerDefaultProperty),
DefaultValue(null), MergableProperty(false), Bindable(false)
]
public List<BannerDisplayCheck> BannerDisplayCheckCollection
{
get
{
if (_BannerDisplayCheck == null)
{
_BannerDisplayCheck = new List<BannerDisplayCheck>();
}
return _BannerDisplayCheck;
}
}
I use the collection in the function "GetBannerDisplaySqlConditions
". This function will build up the lookup part of the SQL statement in the function "GetBannersWithinArea
":
protected string GetBannerDisplaySqlConditions()
{
string retVal = null;
if (_BannerDisplayCheck.Count > 0)
{
retVal += " and banner_id in (select banner_id " +
"from BMS_BANNER_DISPLAY_CRITERIAS where ";
foreach (BannerDisplayCheck bdc in _BannerDisplayCheck)
{
switch (bdc.ParameterType)
{
case BannerDisplayCheck.CriteriaTypes.QueryString:
if (!string.IsNullOrEmpty(
HttpContext.Current.Request[bdc.ParameterName]))
{
retVal += "(criteria_code='" +
bdc.ParameterType.ToString() + "'";
retVal += " and criteria_value='" +
HttpContext.Current.Request[bdc.ParameterName] +
"') or ";
}
break;
case BannerDisplayCheck.CriteriaTypes.PageURL:
retVal += "(criteria_code='" +
bdc.ParameterType.ToString() + "'";
retVal += " and criteria_value='" +
HttpContext.Current.Request.RawUrl.Split('?')[0] +
"') or ";
break;
case BannerDisplayCheck.CriteriaTypes.UserDefined:
if (!string.IsNullOrEmpty(_UserDefinedParameterValue))
{
retVal += "(criteria_code='" +
bdc.ParameterType.ToString() + "'";
retVal += " and criteria_value='" +
_UserDefinedParameterValue + "') or ";
}
break;
case BannerDisplayCheck.CriteriaTypes.Session:
if (!string.IsNullOrEmpty(Convert.ToString(
HttpContext.Current.Session[bdc.ParameterName])))
{
retVal += "(criteria_code='" +
bdc.ParameterType.ToString() + "'";
retVal += " and criteria_value='" +
HttpContext.Current.Session[
bdc.ParameterName].ToString() +
"') or ";
}
break;
case BannerDisplayCheck.CriteriaTypes.Cookie:
HttpCookie cookies =
HttpContext.Current.Request.Cookies[bdc.ParameterName];
if (cookies != null)
{
if (!string.IsNullOrEmpty(Convert.ToString(
HttpContext.Current.Request.Cookies[bdc.ParameterName].Value)))
{
retVal += "(criteria_code='" +
bdc.ParameterType.ToString() + "'";
retVal += " and criteria_value='" +
HttpContext.Current.Request.Cookies[
bdc.ParameterName].Value.ToString() +
"') or ";
}
}
break;
default:
break;
}
}
retVal = retVal.Substring(0, retVal.Length - 3);
retVal += ")";
}
#if (debug)
HttpContext.Current.Response.Write(retVal);
#endif
return retVal;
}
Conclusion
For more details of the source code, please download the source code from the top of this article. The source code is easy and well commented. Download the demo to see the different scenarios of using the control.
Hope this control is useful, and I would like to see comments and votes.