Monday, February 16, 2009

Cross Domain jQuery AJAX Call

In AJAX and jQuery, I talked about how to use jQuery and AJAX to dynamically get data from a separate page. But that example has a limitation: the AJAX call has to be in the same domain of initial page, otherwise the AJAX requests are characterized as Cross-domain Request ("XDR"), and all popular web browsers will deny those cross domain requests due to security consideration. For example, a JavaScript (AJAX call) in a page inside domain abc.com won't be able to talk with bcd.com because abc.com and bcd.com are in different domains.

However there're some workarounds for such issue. jQuery uses the JSONP approach. Following example shows how to dynamically populate weather information from a different domain. The JavaScript and the page content is below:
<script language="javascript">
/* Sample of JSON Return:
({ "Location":{"Code":"CityCode_1141","Name":"HFLaJlrf"},
"WeatherInfoList":[
{"Day":"Mon","Image":"Images\/5.gif","Temperature":"32°\/22°"},
{"Day":"Tue","Image":"Images\/28.gif","Temperature":"20°\/-8°"},
{"Day":"Wed","Image":"Images\/9.gif","Temperature":"7°\/13°"},
{"Day":"Thu","Image":"Images\/5.gif","Temperature":"11°\/-6°"}
]})
*/

/* Dynamically load weather info using cross domain Ajax call with JSON */
/* Refer to: http://docs.jquery.com/Release:jQuery_1.2/Ajax#Cross-Domain_getJSON_.28using_JSONP.29
http://www.theurer.cc/blog/2005/12/15/web-services-json-dump-your-proxy/
*/

function getWeatherJSON() {
var server = "http://myserver/WeatherService.aspx"; // XDR request
var weatherServiceUrl = server + "?location=" + weatherLocation + "&format=json&jsoncallback=?";
$.getJSON(weatherServiceUrl, function(data) {
$("#WeatherTitle").html(data.Location.Name + " Code(" + data.Location.Code + ")");
/* Loop through all items and set weather data*/
$.each(data.WeatherInfoList, function(i, item) {
$("#Weather_Day" + i + "_Day").html(item.Day);
$("#Weather_Day" + i + "_Image").attr("src", item.Image);
$("#Weather_Day" + i + "_Temperature").html(item.Temperature);
});
$("#divWeatherControl").show();
$("#divWeatherLoading").hide();
});
}
</script>

<div id="divWeatherControl" style="border: solid 1px blue; text-align: center; display: none;">
<table>
<tr align="center">
<td colspan="4"><p id="WeatherTitle" /></td>
</tr>
<tr align="center">
<td><p id="Weather_Day0_Day" /></td>
<td><p id="Weather_Day1_Day" /></td>
<td><p id="Weather_Day2_Day" /></td>
<td><p id="Weather_Day3_Day" /></td>
</tr>
<tr align="center">
<td><img id="Weather_Day0_Image" /></td>
<td><img id="Weather_Day1_Image" /></td>
<td><img id="Weather_Day2_Image" /></td>
<td><img id="Weather_Day3_Image" /></td>
</tr>
<tr align="center">
<td><p id="Weather_Day0_Temperature" /></td>
<td><p id="Weather_Day1_Temperature" /></td>
<td><p id="Weather_Day2_Temperature" /></td>
<td><p id="Weather_Day3_Temperature" /></td>
</tr>
</table>
</div>
<div id="divWeatherLoading" style="border: solid 1px blue; text-align: center;">
Loading weather data...
</div>
Note myserver/weatherservice.aspx can be any domain. The code behind of the weatherservice.aspx page (empty html):
using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using System.Text;
using System.Runtime.Serialization.Json;

public partial class WeatherService : System.Web.UI.Page
{
private readonly string WEATHERLOCACTIONNAME = "location";
private readonly string CALLBACKFUNCNAME = "jsoncallback";

protected void Page_Load(object sender, EventArgs e)
{
string html = RenderJSON();
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Write(html);
Response.End();
}

private string RenderJSON()
{
string location = Request.QueryString[WEATHERLOCACTIONNAME];
string callBackFunction = Request.QueryString[CALLBACKFUNCNAME];
if (!string.IsNullOrEmpty(location) && !string.IsNullOrEmpty(callBackFunction))
{
WeatherInfo wloc = BLL.GetWeatherForecast(location);
if (wloc == null) return string.Empty;
DataContractJsonSerializer serializer =
new DataContractJsonSerializer(wloc.GetType());
StringBuilder sb = new StringBuilder();
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, wloc);
sb.Append(callBackFunction + "(");
sb.Append(Encoding.UTF8.GetString(ms.ToArray()));
sb.Append(")");
}
return sb.ToString();
}
return string.Empty;
}
}
The result looks like:

Friday, January 09, 2009

AJAX And jQuery

AJAX (Asynchronous JavaScript and XML) has become a powerful platform for building web applications with extensive client-side interactivity. Unlike older approaches, which require reloading of the entire page with every postback, AJAX uses the JavaScript DOM, the XMLHttpRequest object, XML, and CSS to download and display just the content that needs to change. ASP.NET AJAX library, part of ASP.NET 3.5, wraps up the related AJAX features into a set of JavaScript functions so that developers can easily do tasks like partially page update.

ASP.NET AJAX is great, but more and more ASP.NET AJAX developers move to jQuery. Comparing to ASP.NET AJAX, jQuery is more flexible, efficient and platform independent.

What’s jQuery anyway? jQuery is a lightweight yet powerful JavaScript library that simplifies various task for developers like HTML document traversing, event handling, animating, and Ajax interactions for rapid web development.

jQuery is written by JavaScript and all old JavaScripts are still working fine on jQuery framework. jQuery provides its standard jQuery object under the dollar symbol $. jQuery uses CSS style selectors which makes manipulations on page DOM objects very easy. Following example shows how to dynamically filter images based on the photo’s categories:
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#ddlCategory").change(ddlCategoryChanged);
});
function ddlCategoryChanged() {
var categoryID = $("#ddlCategory :selected").val();
$(".photo").find("li").each(function(i) {
var ids = $(this).find("input:hidden").val();
$(this).show();
if (categoryID != "0" && !hasIDInlist(ids, categoryID)){
$(this).hide();
}
});
}
function hasIDInlist(ids, selectedID) {
if (ids) {
var idSplit = ids.split(',');
for (i = 0; i < idSplit.length; i++) {
if (idSplit[i] == selectedID) {
return true;
}
}
}
return false;
}
</script>
</head>
<body>
Filter photos by category:
<select name="ddlCategory" id="ddlCategory">
<option value="0">All</option>
<option value="1">Outdoor</option>
<option value="2">Indoor</option>
<option value="3">Family</option>
<option value="4">Friends</option>
<option value="5">Colleagues</option>
</select>
<ul class="photo">
<li><img src='photo1.gif' /><br />Photo 1
<input type="hidden" value='1,5'/></li>
<li><img src='photo2.gif' /><br />Photo 2
<input type="hidden" value='2,3'/></li>
<li><img src='photo3.gif' /><br />Photo 3
<input type="hidden" value='1,4'/></li>
<li><img src='photo4.gif' /><br />Photo 4
<input type="hidden" value='1,3'/></li>
<li><img src='photo5.gif' /><br />Photo 5
<input type="hidden" value='2,3'/></li>
<li><img src='photo6.gif' /><br />Photo 6
<input type="hidden" value='5'/></li>
<li><img src='photo7.gif' /><br />Photo 7
<input type="hidden" value='4'/></li>
<li><img src='photo8.gif' /><br />Photo 8
<input type="hidden" value='1,4'/></li>
</ul>
</body>
</html>
Each photo’s category Ids are stored in a hidden field. Instead of putting event handler inside each control like onclick=’javascriptFunction’, the selection dropdown event handler is registered in an unobtrusive way ($("#ddlCategory").change(ddlCategoryChanged);) When event is fired, it will go through all photo containers by selecting <li> HTML element under CSS class of photo; the category Ids are retrieved and are compared with the selected category ID; the photo container’s visibility is set based on the category ID comparison result. All these are accomplished by just a few lines of jQuery code:
    $(".photo").find("li").each(function(i) {
var ids = $(this).find("input:hidden").val();
$(this).show();
if (categoryID != "0" && !hasIDInlist(ids, categoryID)){
$(this).hide();
}});
jQuery has great AJAX support, and the AJAX invocation in jQurey is super concise (could be only one line of code). jQuery version 1.3.2 offers six AJAX function calls:

jQuery.ajax(options): Load a remote page using an HTTP request; the most customizable AJAX function in jQuery.
jQuery.load(url, data, callback): Load HTML from a remote file and inject it into the DOM.
jQuery.get(url, data, callback, type): Load a remote page using an HTTP GET request.
jQuery.getJSON( url, data, callback ): Load JSON data using an HTTP GET request; supports Cross-Domain call.
jQuery.getScript( url, callback ): Loads, and executes, a local JavaScript file using an HTTP GET request.

It's quite simple to use those jQuery AJAX functions. Following example shows how to get current time from a jQuery call. Suppose we have a simple page to display current time (Time.aspx):
<%@ page language="C#" %>
<html>
<head>
<title>Simply show current time</title>
<script runat="server">
void Page_Load(object sender, System.EventArgs e)
{
lblTime.Text = DateTime.Now.ToString();
}
</script>
</head>
<body>
<asp:Label ID="lblTime" runat="server"></asp:Label>
</body>
</html>
Then we can get current time from another page using jQuery ajax call:
<html>
<head>
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#btnGetTime").click(btnClick);
});
function btnClick() {
var searchUrl =
"Time.aspx";
$.ajax({
url: searchUrl,
success: function(data) {
//alert($(data).filter(
"#lblTime").html());
$(
"#divResult").html(data);
}
});
}
</script>
</head>
<body>
<input type="button" value="Get Current Time" id="btnGetTime">
<div id="divResult">
</div>
</body>
</html>
The clean html is another advantage of using jQuery. No postback, no view states are required or generated by jQuery when we use jQuery inside ASP.NET.

Friday, December 19, 2008

Dynamic Javascript Function Invocation

Such dynamic JavaScript call may become handy in some scenario:
    function functionCall(data, option) {
        if (someCondition) {
            var dynamicFunc = function1;
            var args = [data, option, 1];
        } else {
            var dynamicFunc = function2;
            var args = [data, option, 2];
        }
        var value = dynamicFunc.apply(dynamicFunc, args);
        // processing value 
    }

Sunday, December 07, 2008

Design Patterns By Example: Strategy vs Template vs Builder vs Bridge

In this post I will go through a few related design patterns. Unlike many online design pattern tutorials, patterns concept and UML diagrams will not be our focus. Instead I will provide more understandable code examples for the discussion.

Strategy Pattern

Strategy defines an interface common to all supported algorithms or behavior. The implementation of the Strategy is dynamically invoked at run time. Generic list sorting in .NET is a good example of using strategy pattern:

using System;
using System.Collections.Generic;

class test {

    class Person
    {
        public string name { get; set; }
        public int Age { get; set; }
    }

    class PersonSortByAge : IComparer<Person>
    {
        public int Compare(Person p1, Person p2)
        {
            return p1.Age.CompareTo(p2.Age);
        }
    }

    static void Main(string[] args)
    {
        List<Person> people = new List<Person>();
        people.Add(new Person() { name = "Andy Wade", Age = 20 });
        people.Add(new Person() { name = "Cary Lee", Age = 10 });
        people.Add(new Person() { name = "Bob Ford", Age = 30 });

        Console.WriteLine("Original order:");
        people.ForEach(p => Console.WriteLine("Name:" + p.name + " Age:" + p.Age));

        people.Sort((p1, p2) => p1.name.CompareTo(p2.name));
        Console.WriteLine("Sort by name:");
        people.ForEach(p => Console.WriteLine("Name:" + p.name + " Age:" + p.Age));
        //Sort by name:
        //Name:Andy Wade Age:20
        //Name:Bob Ford Age:30
        //Name:Cary Lee Age:10

        people.Sort(new PersonSortByAge());
        Console.WriteLine("Sort by age:");
        people.ForEach(p => Console.WriteLine("Name:" + p.name + " Age:" + p.Age));
        //Sort by age:
        //Name:Cary Lee Age:10
        //Name:Andy Wade Age:20
        //Name:Bob Ford Age:30

        Console.ReadKey();
    }
}

In above example Lambda express and strongly typed IComparer are two different strategy or sorting algorithm, which are used to sort the people list by person's name and age respectively. Following code is another example:

using System;
using System.Collections.Generic;
using System.Linq;

class StrategyPattern
{
    enum Temperature { Cold, Mild, Hot }

    interface IActivity
    {
        string GetActivity(Temperature temperature);
    }

    class DayPlanner
    {
        private Temperature Weather;

        public DayPlanner(Temperature weather)
        {
            this.Weather = weather;
        }

        public void SetPlan(IActivity activity)
        {
            Console.WriteLine("Setting plan for " + activity.GetActivity(Weather));
        }
    }

    class IndoorActivity : IActivity
    {
        public string GetActivity(Temperature temperature)
        {
            return (temperature == Temperature.Cold) ? "Hockey" : "Fitness gym";
        }
    }

    class OutdoorActivity : IActivity
    {
        public string GetActivity(Temperature temperature)
        {
            switch (temperature)
            {
                case Temperature.Cold:
                    return "Ice skating";
                case Temperature.Mild:
                    return "Hiking";
                case Temperature.Hot:
                default:
                    return "Swimmig";
            }
        }
    }

    static void Main(string[] args)
    {
        DayPlanner planner = new DayPlanner(Temperature.Mild);
        
        OutdoorActivity outdoorActivity = new OutdoorActivity();
        planner.SetPlan(outdoorActivity); 
        // print out "Setting plan for Hiking"

        IndoorActivity indoorActivity = new IndoorActivity();
        planner.SetPlan(indoorActivity);  
        // print out "Setting plan for Fitness gym"

        Console.ReadKey();
    }
}

Here the DayPlanner holds a reference of an IActivity instance, an implementation of a strategy. With different strategy assigned, DayPlanner shows different activity. Strategy pattern results in dynamic behavior.

Template Method Pattern

Template method defines a sequence of method calls or some algorithms in base class, and the detail implementation of each method or algorithm is overriden by subclass. One obvious example is the ASP.NET Page life cycle: PreLoad, OnLoad, PreRender, etc. Those events are invoked by base Page class and developers are responsible to fill the detail implementation in code-behind for those events. Following code illustrate how the PersonDayPlanner schedules morning, afternoon and night activities by template method:

using System;
using System.Collections.Generic;

class TemplateMethodPattern
{
    abstract class PersonDayPlanner
    {
        // Template Method defines the skeleton steps
        public void Plan()
        {
            MorningPlan();
            AfternoonPlan();
            NightPlan();
        }

        // Abstract methods implemented by child classes
        public abstract void MorningPlan();
        public abstract void AfternoonPlan();
        public abstract void NightPlan();
    }

    class CollegeStudentSaturday : PersonDayPlanner
    {
        public override void MorningPlan()
        {
            Console.WriteLine("Have a simple breakfast and do cleanup.");
        }

        public override void AfternoonPlan()
        {
            Console.WriteLine("Study for 2 hours then go to gym for exercise.");
        }

        public override void NightPlan()
        {
            Console.WriteLine("Eat out with friends and watch movie after");
        }
    }

    class LittleKidSaturday : PersonDayPlanner
    {
        public override void MorningPlan()
        {
            Console.WriteLine("McDonald's happy meal for breakfast, then play at park.");
        }

        public override void AfternoonPlan()
        {
            Console.WriteLine("Friend's birthday party.");
        }

        public override void NightPlan()
        {
            Console.WriteLine("Play LEGO and watch TV.");
        }
    }

    static void Main(string[] args)
    {
        PersonDayPlanner saturday = new CollegeStudentSaturday();
        saturday.Plan();
        Console.WriteLine();
        //print out a student's plan on Saturday:
        // Have a simple breakfast and do cleanup.
        // Study for 2 hours then go to gym for exercise.
        // Eat out with friends and watch movie after

        saturday = new LittleKidSaturday();
        saturday.Plan();
        //print out a kid's plan on Saturday:
        // McDonald's happy meal for breakfast, then play at park.
        // Friend's birthday party.
        // Play LEGO and watch TV.

        Console.ReadKey();
    }
}

Builder Pattern

The Builder pattern separates the construction logic for an object. This pattern is often used when the construction process of an object is complex. By modifying above DayPlanner code demo we have following builder implementation:

using System;
using System.Collections.Generic;

class BuilderPattern
{
    interface IPersonDayPlan
    {
        void MorningPlan();
        void AfternoonPlan();
        void NightPlan();
    }

    class DayPlanBuilder
    {
        private IPersonDayPlan DayPlan { get; set; }

        public DayPlanBuilder() { } // default constructor

        public DayPlanBuilder(IPersonDayPlan dayPlan)
        {
            this.DayPlan = dayPlan;
        }

        public void SetPersonDayPlan(IPersonDayPlan dayPlan)
        {
            this.DayPlan = dayPlan;
        }

        public void BuildPlan()
        {
            if (this.DayPlan != null)
            {
                this.DayPlan.MorningPlan();
                this.DayPlan.AfternoonPlan();
                this.DayPlan.NightPlan();

                // You can control the steps or add new logic inside the builder
                if (this.DayPlan is CollegeStudentSaturday)
                {
                    Console.WriteLine("Play games no later than 12PM.");
                }
            }
        }
    }

    class CollegeStudentSaturday : IPersonDayPlan
    {
        public void MorningPlan()
        {
            Console.WriteLine("Have a simple breakfast and do cleanup.");
        }

        public void AfternoonPlan()
        {
            Console.WriteLine("Study for 2 hours then go to gym for exercise.");
        }

        public void NightPlan()
        {
            Console.WriteLine("Eat out with friends and watch movie after");
        }
    }

    class LittleKidSaturday : IPersonDayPlan
    {
        public void MorningPlan()
        {
            Console.WriteLine("McDonald's happy meal for breakfast, then play at park.");
        }

        public void AfternoonPlan()
        {
            Console.WriteLine("Friend's birthday party.");
        }

        public void NightPlan()
        {
            Console.WriteLine("Play LEGO and watch TV.");
        }
    }

    static void Main(string[] args)
    {
        DayPlanBuilder planBuilder = new DayPlanBuilder(new LittleKidSaturday());
        planBuilder.BuildPlan();
        //print out:
        // McDonald's happy meal for breakfast, then play at park.
        // Friend's birthday party.
        // Play LEGO and watch TV.

        // changing to student's plan
        planBuilder.SetPersonDayPlan(new CollegeStudentSaturday());
        planBuilder.BuildPlan();
        //print out:
        // Have a simple breakfast and do cleanup.
        // Study for 2 hours then go to gym for exercise.
        // Eat out with friends and watch movie after
        // Play games no later than 12PM.

        Console.ReadKey();
    }
}

The Builder pattern plays a little bit different "director" role compared with the Template method in the build process. In above example BuildPlan method can have different build steps for different IPersonDayPlan types; while the Template method has fixed run steps. Builder is creational pattern and it is mainly used to create complex object. Template method is behavior pattern and it defines skeleton of running procedure.

Bridge Pattern

Both Template method and Builder pattern use inheritance to implement different behaviors or algorithms. The situation would become messy when more and more objects join and play in the hierarchy. In above DayPlanner example, we could have AdultMonday, AdultTuesday...SeniorMonday, SeniorTuesday...etc. of many other combination for sub classes. Bridge pattern resolves the problem by decoupling an abstraction from its implementation so that the two can vary independently. Modify the code example again the Bridge version looks like:

using System;
using System.Collections.Generic;

class BridgePattern
{
    interface IDayPlanner
    {
        string DayOfWeek { get; }
        void Plan(int age, bool inSchool);
    }

    abstract class Person
    {
        public int Age { get; set; }
        protected IDayPlanner DayPlanner { get; set; }

        public void SetDayPlanner(IDayPlanner dayPlanner)
        {
            this.DayPlanner = dayPlanner;
        }

        public abstract void PlanDay();
    }

    class CollegeStudent : Person
    {
        public CollegeStudent(int age)
        {
            base.Age = age;
        }

        public override void PlanDay()
        {
            Console.WriteLine("College student's " + this.DayPlanner.DayOfWeek + " schedule:");
            this.DayPlanner.Plan(this.Age, true);
        }
    }

    class LittleKid : Person
    {
        public LittleKid(int age)
        {
            base.Age = age;
        }

        public override void PlanDay()
        {
            Console.WriteLine("Little kid's " + this.DayPlanner.DayOfWeek + " schedule:");
            this.DayPlanner.Plan(this.Age, false);
        }
    }

    class SaturdayPlanner : IDayPlanner
    {
        public void Plan(int age, bool inSchool)
        {
            if (age < 6)
            {
                Console.WriteLine("Play at park, friend's birthday party, and play LEGO.");
            }
            else if (age > 18 && inSchool)
            {
                Console.WriteLine("Study, gym exercise and social activities.");
            }
            // plan for other cases
        }

        public string DayOfWeek { get { return "Saturday"; } }
    }

    class MondayPlanner : IDayPlanner
    {
        public void Plan(int age, bool inSchool)
        {
            if (age < 6)
            {
                Console.WriteLine("Kindergarten.");
            }
            else if (age > 18 && inSchool)
            {
                Console.WriteLine("Classes, library and lab.");
            }
            // plan for other cases
        }

        public string DayOfWeek { get { return "Monday"; } }
    }

    static void Main(string[] args)
    {
        Person kid = new LittleKid(5);
        kid.SetDayPlanner(new SaturdayPlanner());
        kid.PlanDay();
        //Little kid's Saturday schedule:
        //Play at park, friend's birthday party, and play LEGO.

        Person student = new CollegeStudent(20);
        student.SetDayPlanner(new MondayPlanner());
        student.PlanDay();
        //College student's Monday schedule:
        //Classes, library and lab.

        Console.ReadKey();
    }
}

Now person and weekday are separated, and we don't have to do their combinational sub-classes anymore, known as "prefer composition over inheritance" for such scenario. The Provider model in .NET framework, such as Membership Provider and Session State Provider, is an example of using Bridge pattern.

Last but not least, design patterns are useful to resolve certain problems but they are not a silver bullet. Overusing them could introduce unnecessary complexity and cost. We should't force to use patterns as what I do in this posting. The pattern examples I presented above are just for demonstration purpose and it doesn't mean they are the best practices. In reality we should consider those patterns when having a code smell in our work.

Thursday, November 20, 2008

.NET XmlSerializer Memory Leak

Production maintenance team reports the memory usage of IIS worker process keeping growing in one high-traffic site, which indicating the memory leak. After investigation, one of culprits is from XmlSerializer:
Type[] relatedTypes = new Type[1];
type[0] = typeof(AppObject);
XmlSerializer serializer = new XmlSerializer(typeof(AppConfig), relatedTypes);
Every time this serializer is created, a dynamic assembly is also generated at run time and is loaded into memory to do the XML serialization. The problem is that once a .NET assembly (dynamic or static) is loaded, there's no way you can clean it through code, and it will only be removed from the memory until the whole application is unloaded. The result is a memory leak with more and more dynamic XML serialization assemblies added into memory.

The solution is use XmlSerialzer constructor with only Type parameter:
XmlSerializer serializer = new XmlSerializer(typeof(object));
Alternative is to cache the XmlSerialzer object for the first time when you can't use such constructor, and reuse it later. In fact .NET caches XmlSerialzer that created only by Type constructor.

This seems to be an known issue. We google it and found many people having same problem. A good article showing the details of tracing this issue can be found here.

Sunday, November 09, 2008

ASP.NET Cache Callback

ASP.NET Cache Callback

ASP.NET Cache supports CacheItemRemovedCallback option since .NET 1.1 (http://msdn.microsoft.com/en-us/library/aa478965.aspx), and we can do some interesting things such as logging inside the callback function. But a big limitation on it is that we can’t do cache validation to keep or refresh cache data in this callback function:

"One potential use for this feature would be to refresh cached data in the background so that users never need to wait for the data to be populated, but the data is kept relatively fresh. Unfortunately in practice, this doesn't work very well with the current version of the caching API, because the callback doesn't fire or complete execution prior to the cached item being removed from the cache. Thus, a user will frequently make a request that will try to access the cached value, find that it is null, and be forced to wait for it to repopulate."

From .NET 3.5, we have a new CacheItemUpdateCallback delegate for caching handling (http://msdn.microsoft.com/en-us/library/system.web.caching.cacheitemupdatecallback.aspx). Now we can periodically update the cache by the callback function. The new overloading Cache Insert method is:
HttpRuntime.Cache.Insert(
stringKey,
objectValue,
cacheDependencies,
dateTimeAbsoluteExpiration,
timeSpanSlidingExpiration,
cacheUpdateCallback)
The callback function signature is:

public delegate void CacheItemUpdateCallback(
string key,
CacheItemUpdateReason reason,
out Object expensiveObject,
out CacheDependency dependency,
out DateTime absoluteExpiration,
out TimeSpan slidingExpiration
)
This new feature is very handy when we need to automatically refresh the cache in background.

Tuesday, October 21, 2008

Visitor Pattern By Example

Visitor pattern separates some algorightm or computation work to its own class. Being able to "visit" visitable objects, different algorithm implementations can do their work without modification of original objects. Let's say a person has different kind of valuables/assets, and the value calculations could have their own implementation:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        public interface IValuable  // Interface for visitable objects 
        {
            void Value(IValueCalculator calculator);
        }

        public interface IValueCalculator   // Interface for visitor implementation
        {
            decimal GetTotal();
            void Calculate(BankAccount bankAccount);
            void Calculate(Loan load);
        }

        public class NetWorthCalculator : IValueCalculator
        {
            private decimal Total = 0;

            public decimal GetTotal()
            {
                return Total;
            }

            public void Calculate(BankAccount bankAccount)
            {
                Total += bankAccount.Balance;
            }

            public void Calculate(Loan loan)
            {
                Total -= loan.Amount;
            }
        }

        public class MonthlyIncomeCalculator : IValueCalculator
        {
            private decimal Total = 0;

            public decimal GetTotal()
            {
                return Total;
            }

            public void Calculate(BankAccount bankAccount)
            {
                Total += (bankAccount.Balance * bankAccount.InterestRate) / 12;
            }

            public void Calculate(Loan loan)
            {
                Total -= loan.MonthlyPayment;
            }
        }

        public class BankAccount : IValuable
        {
            public string Name { get; set; }
            public decimal Balance { get; set; }
            public decimal InterestRate { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Loan : IValuable
        {
            public string Name { get; set; }
            public decimal Amount { get; set; }
            public decimal MonthlyPayment { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Person : IValuable // Composite pattern: Person itself is also IValuable
        {
            public string Name { get; set; }
            public List<IValuable> Valuables = new List<IValuable>();

            public void Value(IValueCalculator calculator)
            {
                foreach (IValuable item in Valuables)
                {
                    item.Value(calculator);
                }
            }
        }

        static void Main(string[] args)
        {
            Person person = new Person() { Name = "new graduate student" };
            person.Valuables.Add(new BankAccount()
            {
                Name = "Saving Account",
                Balance = 5000,
                InterestRate = 0.05m
            });
            person.Valuables.Add(new BankAccount()
            {
                Name = "Cheque Account",
                Balance = 2000,
                InterestRate = 0.01m
            });
            person.Valuables.Add(new Loan()
            {
                Name = "Student Loan",
                Amount = 5000,
                MonthlyPayment = 500
            });

            NetWorthCalculator netWorth = new NetWorthCalculator();
            person.Value(netWorth);
            Console.WriteLine("Assets' net worth is: " + netWorth.GetTotal());

            MonthlyIncomeCalculator monthlyIncome = new MonthlyIncomeCalculator();
            person.Value(monthlyIncome);
            Console.WriteLine("Monthly income from Assets: " + monthlyIncome.GetTotal().ToString("#.##"));

            Console.Read();
        }
    }
}

Run the console app will show following result:

    Assets' net worth is: 2000
    Monthly income from Assets: -477.5

The NetWorthCalculator and MonthlyIncomeCalculator are totally separated from the target IValuable objects. We can implement other type of calculation without any modification on existing code. When adding new IValuable type, the ICalculator interface and its implementations need to include the new type. Back to our example, assume the student found a job after graduation from school, paid off most of the student loan in six months and bought some Microsoft stocks. Two new IValuable types are introduced:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        public interface IValuable  // Interface for visitable objects
        {
            void Value(IValueCalculator calculator);
        }

        public interface IValueCalculator   // Interface for visitor implementation
        {
            decimal GetTotal();
            void Calculate(BankAccount bankAccount);
            void Calculate(Loan load);
            void Calculate(Job stock);
            void Calculate(Stock stock);
        }

        public class NetWorthCalculator : IValueCalculator
        {
            private decimal Total = 0;

            public decimal GetTotal()
            {
                return Total;
            }

            public void Calculate(BankAccount bankAccount)
            {
                Total += bankAccount.Balance;
            }

            public void Calculate(Loan loan)
            {
                Total -= loan.Amount;
            }

            public void Calculate(Job job)
            {
                // Do nothing
            }

            public void Calculate(Stock stock)
            {
                Total += stock.Price * stock.Share;
            }
        }

        public class MonthlyIncomeCalculator : IValueCalculator
        {
            private decimal Total = 0;

            public decimal GetTotal()
            {
                return Total;
            }

            public void Calculate(BankAccount bankAccount)
            {
                Total += (bankAccount.Balance * bankAccount.InterestRate) / 12;
            }

            public void Calculate(Loan loan)
            {
                Total -= loan.MonthlyPayment;
            }

            public void Calculate(Job job)
            {
                Total += job.Salary / 12;
            }

            public void Calculate(Stock stock)
            {
                // Do nothing
            }
        }

        public class BankAccount : IValuable
        {
            public string Name { get; set; }
            public decimal Balance { get; set; }
            public decimal InterestRate { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Loan : IValuable
        {
            public string Name { get; set; }
            public decimal Amount { get; set; }
            public decimal MonthlyPayment { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Job : IValuable
        {
            public string Name { get; set; }
            public decimal Salary { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Stock : IValuable
        {
            public string Name { get; set; }
            public decimal Price { get; set; }
            public int Share { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Person : IValuable // Composite pattern: Person itself is also IValuable
        {
            public string Name { get; set; }
            public List<IValuable> Valuables = new List<IValuable>();

            public void Value(IValueCalculator calculator)
            {
                foreach (IValuable item in Valuables)
                {
                    item.Value(calculator);
                }
            }
        }

        static void Main(string[] args)
        {
            Person person = new Person() { Name = "6-month after graduation" };
            person.Valuables.Add(new BankAccount()
            {
                Name = "Saving Account",
                Balance = 20000,
                InterestRate = 0.05m
            });
            person.Valuables.Add(new BankAccount()
            {
                Name = "Cheque Account",
                Balance = 5000,
                InterestRate = 0.01m
            });
            person.Valuables.Add(new Loan()
            {
                Name = "Student Loan",
                Amount = 1000,
                MonthlyPayment = 500
            });
            person.Valuables.Add(new Job()
            {
                Name = "Software Developer",
                Salary = 60000
            });
            person.Valuables.Add(new Stock()
            {
                Name = "Microsoft",
                Price = 20,
                Share = 100
            });

            NetWorthCalculator netWorth = new NetWorthCalculator();
            person.Value(netWorth);
            Console.WriteLine("Assets' net worth is: " + netWorth.GetTotal());

            MonthlyIncomeCalculator monthlyIncome = new MonthlyIncomeCalculator();
            person.Value(monthlyIncome);
            Console.WriteLine("Monthly income from Assets: " + monthlyIncome.GetTotal().ToString("#.##"));

            Console.Read();
        }
    }
}

Run the app again and now the net worth and monthly income are both positive:

    Assets' net worth is: 26000
    Monthly income from Assets: 4587.5

The Visitor Pattern is quite useful for some scenarios. But again we use the design patterns to resolve certain problems, and let the code more extensible and maintainable. They may not be suitable for some situations and over using them may make the code unnecessarily complicated.

Friday, October 03, 2008

Invoke Generic Method Dynamically In .NET

Generic method was first introduced in .NET 2.0, and we can write method with dynamic types like:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

class Test
{
public class Foo
{
public string Name { get; set; }
public Foo(string name)
{
Name = "Foo" + name;
}
}
public static List<T> ParseValues<T>(string[] data)
{
List<T> values = new List<T>();
Type type = typeof(T);
if (type == typeof(int))
{
foreach (string str in data)
values.Add((T)((object)int.Parse(str)));
}
else if (type == typeof(double))
{
foreach (string str in data)
values.Add((T)((object)double.Parse(str)));
}
else if (type == typeof(Foo))
{
foreach (string str in data)
values.Add((T)((object)new Foo(str)));
}
return values;
}

static void Main()
{
string[] values = new string[] { "1", "2", "3" };
List<int> numbers = ParseValues<int>(values);
List<double> doubles = ParseValues<double>(values);
List<Foo> foos = ParseValues<Foo>(values);

//Print 1 2 3 1 2 3 Foo1 Foo2 Foo3
numbers.ForEach(i => Console.Write(i + " "));
doubles.ForEach(i => Console.Write(i + " "));
foos.ForEach(i => Console.Write(i.Name + " "));

Console.Read();
}
}
In order to invoke a generic method you have to declare the type statically, and it will be initiated at compile time. Is there a way to get a generic type dynamically? We can do something like:
    Type genericListType = typeof(List<>).MakeGenericType(typeof(double));
var list = Activator.CreateInstance(genericListType);
But that doesn't resolve our problem because we can't determine the T type at compile time to invoke the method of public static List<T> ParseValues<T>(string[] data).

One way I can think of is use the reflection and invoke the method dynamically:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

class Test
{
public class Foo
{
public string Name { get; set; }
public Foo(string name)
{
Name = "Foo" + name;
}
}
public static List<T> ParseValues<T>(string[] data)
{
List<T> values = new List<T>();
Type type = typeof(T);
if (type == typeof(int))
{
foreach (string str in data)
values.Add((T)((object)int.Parse(str)));
}
else if (type == typeof(double))
{
foreach (string str in data)
values.Add((T)((object)double.Parse(str)));
}
else if (type == typeof(Foo))
{
foreach (string str in data)
values.Add((T)((object)new Foo(str)));
}
return values;
}

static void Main()
{
string[] values = new string[] { "1", "2", "3" };
List<int> numbers = ParseValues<int>(values);
List<double> doubles = ParseValues<double>(values);
List<Foo> foos = ParseValues<Foo>(values);

//Print 1 2 3 1 2 3 Foo1 Foo2 Foo3
numbers.ForEach(i => Console.Write(i + " "));
doubles.ForEach(i => Console.Write(i + " "));
foos.ForEach(i => Console.Write(i.Name + " "));
Console.WriteLine();

Type numberType = typeof(int);
MethodInfo genericMethod = typeof(Test).GetMethod("ParseValues").MakeGenericMethod(numberType);
var dynamicList = genericMethod.Invoke(null, new object[] { values });

// Print 1 2 3
foreach (var item in dynamicList as IEnumerable)
Console.Write(item + " ");

Type fooType = typeof(Foo);
genericMethod = typeof(Test).GetMethod("ParseValues").MakeGenericMethod(fooType);
dynamicList = genericMethod.Invoke(null, new object[] { values });

// Print Foo1 Foo2 Foo3
foreach (var item in dynamicList as IEnumerable)
Console.Write((item as Foo).Name + " ");

Console.Read();
}
}
Bear in mind that using Reflection is costly and it would affect performance significantly.

Friday, September 12, 2008

ASP.NET Substitute Custom Control In Output-cached Page

ASP.NET output cache is great. For dynamic content inside output-cached pages, ASP.NET 2.0 introduces Substitution concept, where the dynamic content is retrieved and substituted for the Substitution control at run time.

Usually Substitution content is just a string. But we can extend it to render a custom server control. For example there's a custom control named MyCustomControl that needs to be displayed dynamically in a output-cached page. First we need to declare a Substitution:
<asp:Substitution runat="server" ID="subControl" MethodName="GetControlString" />
Inside the GetControlString static method:
    public static string GetControlString(HttpContext context)
{
StringWriter output = new StringWriter();
Page pageHolder = new Page();
MyCustomControl control = MyCustomControl();
//control.SetParameters();
//pageHolder.Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8");
pageHolder.Controls.Add(control);

context.Server.Execute(pageHolder, output, false);
context.Response.ContentEncoding = Encoding.GetEncoding("UTF-8");

return output.ToString();
}

[2009/06 Updated] HttpContext.Response.ContentEncoding needs to be defined specifically if you encounter the wrong character encoding issue inside the custom control.

Wednesday, September 03, 2008

ASP.NET Cache Info Page

This is an ASP.NET page to show Cache usage of current w3wp process:



CacheInfo.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CacheInfo.aspx.cs" Inherits="CacheInfo" %>

<!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 runat="server">
<title>Cache Info/Test Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<div>
<p style="text-align: center">
<asp:Label ID="Label4" runat="server" Text="Cache Info" Font-Size="Large" Font-Bold="true"></asp:Label></p>
<p>
<asp:Label ID="lblSysInfo" runat="server" EnableViewState="false"></asp:Label>
<asp:Label ID="lblInfo" runat="server" EnableViewState="false"></asp:Label>
</p>
<p>
<asp:Label ID="lblCache" runat="server" EnableViewState="false"></asp:Label><br />
<asp:GridView ID="gvCache" runat="server" AutoGenerateColumns="False" BorderWidth="1px"
BackColor="White" CellPadding="4" BorderStyle="Solid" BorderColor="#3366CC" Font-Size="Small"
AlternatingRowStyle-ForeColor="ActiveCaption" EnableViewState="false">
<HeaderStyle ForeColor="White" BackColor="#003399" HorizontalAlign="Left"></HeaderStyle>
<Columns>
<asp:TemplateField ItemStyle-Width="20" ItemStyle-Font-Size="X-Small">
<ItemTemplate>
<%# Container.DataItemIndex + 1 %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Key" DataField="Key" ReadOnly="true" ItemStyle-Width="420px"></asp:BoundField>
<asp:BoundField HeaderText="Type" DataField="Type" ReadOnly="true" ItemStyle-Width="180px"></asp:BoundField>
<asp:BoundField HeaderText="Note" DataField="Note" ReadOnly="true" ItemStyle-Width="180px"></asp:BoundField>
</Columns>
<EmptyDataTemplate>
<asp:Label ID="lblEmptyMessage" runat="server" Text="No feature found."></asp:Label>
</EmptyDataTemplate>
</asp:GridView>
</p>
<p>
<asp:Label ID="Label3" runat="server" Text="Add cache with size in MB"></asp:Label>
<asp:DropDownList ID="ddlCacheSize" runat="server" AutoPostBack="false">
<asp:ListItem>50</asp:ListItem>
<asp:ListItem>100</asp:ListItem>
<asp:ListItem>200</asp:ListItem>
<asp:ListItem>300</asp:ListItem>
<asp:ListItem>400</asp:ListItem>
<asp:ListItem>500</asp:ListItem>
<asp:ListItem>600</asp:ListItem>
<asp:ListItem>700</asp:ListItem>
<asp:ListItem>800</asp:ListItem>
<asp:ListItem>900</asp:ListItem>
<asp:ListItem>1000</asp:ListItem>
<asp:ListItem>2000</asp:ListItem>
<asp:ListItem>3000</asp:ListItem>
<asp:ListItem>4000</asp:ListItem>
<asp:ListItem>5000</asp:ListItem>
<asp:ListItem>6000</asp:ListItem>
<asp:ListItem>7000</asp:ListItem>
<asp:ListItem>8000</asp:ListItem>
<asp:ListItem>9000</asp:ListItem>
<asp:ListItem>10000</asp:ListItem>
</asp:DropDownList>&nbsp;&nbsp;
<asp:Label ID="Label1" runat="server" Text="Cache Expire in seconds"></asp:Label>
<asp:DropDownList ID="ddlExpir" runat="server" AutoPostBack="false">
<asp:ListItem>10</asp:ListItem>
<asp:ListItem>20</asp:ListItem>
<asp:ListItem>30</asp:ListItem>
<asp:ListItem>40</asp:ListItem>
<asp:ListItem>50</asp:ListItem>
<asp:ListItem>60</asp:ListItem>
<asp:ListItem>70</asp:ListItem>
<asp:ListItem>80</asp:ListItem>
<asp:ListItem>90</asp:ListItem>
<asp:ListItem>100</asp:ListItem>
<asp:ListItem>110</asp:ListItem>
<asp:ListItem>120</asp:ListItem>
<asp:ListItem>180</asp:ListItem>
</asp:DropDownList>&nbsp;&nbsp;
<asp:Button ID="btnAddCache" runat="server" Text="Add Test Cache" OnClick="btnAddCache_click" />
</p>
</div>
</div>
</form>
</body>
</html>

CacheInfo.aspx.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.Caching;
using System.Text;
using System.Data;

public partial class CacheInfo : System.Web.UI.Page
{
protected class CacheInfoItem
{
public string Key { get; set; }
public string Type { get; set; }
public string Note { get; set; }
public CacheInfoItem(string key, string type)
{
Key = key;
Type = type;
}
}

protected class CacheData
{
public Byte[] Data { get; set; }
public CacheData(int totalBytes)
{
Data = new Byte[totalBytes];
for (int i = 0; i < totalBytes; i += 123)
{
Data[i] = (byte)(i % 256);
}
}
}

protected string TestCacheKey = "Cache_Test_Key";

protected void btnAddCache_click(object sender, EventArgs e)
{
try
{
int totalBytes = int.Parse(ddlCacheSize.SelectedValue) * 1024 * 1024;
CacheData data = new CacheData(totalBytes);
int seconds = int.Parse(ddlExpir.SelectedValue);
HttpRuntime.Cache.Insert(TestCacheKey, data, null, DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration);
lblInfo.Text = "Successfully added test data to cache (expire in " + seconds + " seconds).";
}
catch (Exception ex)
{
lblInfo.Text = "Insert Cache error: " + ex.Message;
}
}

protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
List<CacheInfoItem> cacheItems = new List<CacheInfoItem>();

// Populate System Info
System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
long totalMemBytes = currentProcess.WorkingSet64;
DateTime startTime = currentProcess.StartTime;
Cache cache = HttpRuntime.Cache;
StringBuilder sbInfo = new StringBuilder();
sbInfo.Append(Server.MachineName + " " + currentProcess.MachineName + " ");

sbInfo.Append(currentProcess.ProcessName + " start time: " + startTime.ToString("yyy-MM-dd HH:mm") + " ");
sbInfo.Append("Process memory usage (MB): " + totalMemBytes / (1024 * 1024) + "<br>");
lblSysInfo.Text = sbInfo.ToString();

// Populate Cache Info
sbInfo = new StringBuilder();
if (cache != null)
{
foreach (DictionaryEntry item in cache)
{
try
{
Type type = item.Value.GetType();
string typeInfo = type.ToString();

CacheInfoItem ci = new CacheInfoItem(item.Key.ToString(), typeInfo);
cacheItems.Add(ci);

if (type == Type.GetType("System.DateTime"))
{
ci.Note = "Time: " + Convert.ToDateTime(HttpRuntime.Cache[item.Key.ToString()]).ToString("yyy-MM-dd HH:mm");
}
else if (type == Type.GetType("System.String"))
{
ci.Note = "Value: " + cache[item.Key.ToString()].ToString();
}
else
{
Object obj = cache[item.Key.ToString()];
if (obj != null)
{
if (obj is IList)
{
ci.Note = "Item Count: " + ((IList)obj).Count.ToString();
}
else if (obj is DataSet && (DataSet)obj != null && ((DataSet)obj).Tables[0] != null)
{
ci.Note = "Item Count: " + ((DataSet)obj).Tables[0].Rows.Count.ToString();
}
else if (obj is DataTable && (DataTable)obj != null)
{
ci.Note = "Item Count: " + ((DataTable)obj).Rows.Count.ToString();
}
}
}
}
catch (Exception ex)
{
sbInfo.Append("Get cache info error for " + item.Key + ":" + ex.Message + "<br>");
throw;
}
}
}
lblInfo.Text += sbInfo.ToString();

lblCache.Text = "Total Cache item count: " + cacheItems.Count.ToString();
cacheItems.Sort((i, j) => i.Key.CompareTo(j.Key));
gvCache.DataSource = cacheItems;
gvCache.DataBind();
}
}