Monthly Archives: October 2008

Query a specific Google Calendar

Despite the multiple copies of the API Developer’s Guide: .NET i found i was unable to find how i should query a specific calendar (not the default). Anyway, it can be done by using the CalendarEntry.Content.BaseUri as the query uri. Here is an example:

public class CalendarHelper
{
 public const string OwnedCalendarsUrl = "http://www.google.com/calendar/feeds/default/owncalendars/full";

 private readonly CalendarService svc;

 public CalendarHelper(string username, string password)
 {
  this.svc = new CalendarService("demo");
  this.svc.setUserCredentials(username, password);
 }

 public IEnumerable<calendarEntry> FindOwnedCalendars()
 {
  CalendarQuery query = new CalendarQuery(OwnedCalendarsUrl);
  CalendarFeed result = this.svc.Query(query);
  foreach (CalendarEntry entry in result.Entries) yield return entry;
 }

 public CalendarEntry GetCalendar(string name)
 {
  return (
   from calendar in this.FindOwnedCalendars()
   where calendar.Title.Text == name
   select calendar).SingleOrDefault();
 }

 public IEnumerable<atomEntry> FindEvents(CalendarEntry calendar, DateTime begin, DateTime end)
 {
  EventQuery myQuery = new EventQuery(calendar.Content.AbsoluteUri);
  myQuery.StartTime = begin;
  myQuery.EndTime = end;
  EventFeed result = this.svc.Query(myQuery);
  for (int i = 0; i < result.Entries.Count; ++i) yield return result.Entries[i];
 }
}

private static void Main()
{
 CalendarHelper helper = new CalendarHelper("user@gmail.com", "xxx");

 DateTime begin = new DateTime(2008, 1, 1);
 DateTime end= new DateTime(2009, 12, 31);

 IEnumerable<calendarEntry> calendars = helper.FindOwnedCalendars();
 foreach (CalendarEntry calendar in calendars)
 {
  Console.WriteLine(calendar.Title.Text);

  IEnumerable<atomEntry> calendarEvents = helper.FindEvents(calendar, begin, end);
  foreach(AtomEntry calendarEvent in calendarEvents)
  {
   Console.WriteLine("{0}: {1}", calendarEvent.Updated, calendarEvent.Title.Text);
  }

  Console.WriteLine();
 }

 Console.Write("{0}Press any key to continue...", Environment.NewLine);
 Console.ReadKey();
}

Refactoring Application Environment (Part 2)

Luca Milan notified me of a design issue. Until now the ApplicationEnvironment had an Instance property as following:

public static ApplicationEnvironment Instance { get { ... } }

A lot of flexibility can be added by extracting an interface IApplicationEnvironment and use that as return type for the property:

public static IApplicationEnvironment Instance { get { ... } }

Now that we have Common Service Locator i have decided to completely remove the Instance property. Code that requires an instance of the IApplicationEnvironment will have to resolve it via the ServiceLocator:

IApplicationEnvironment appEnv = ServiceLocator.Current.GetInstance<iapplicationEnvironment>();

How does the controller know which action method to invoke?

Yesterday i attended another great VISUG event on ASP.NET presented by Maarten Balliauw. He demonstrated a custom filter but did not dig into the mechanics of action method resolving. With the aid of of the ActionName attribute we can map different methods to the same action. The following methods will all map to the same “Detail” action:

public ActionResult Detail(int productId) { ... }
public ActionResult Detail(int productId, string name) { ... }
[ActionName("Detail")] public ActionResult DisplayDetail(int productId) { ... }
[ActionName("Detail")] public ActionResult ModifyDetail(int productId, string name) { ... }

So how does the Controller know which method to invoke? The answer can be found in the ActionMethodSelector which tries to find the method as following:

public MethodInfo FindActionMethod(ControllerContext controllerContext, string action)
{
 List<methodInfo> methodsMatchingName = GetMatchingAliasedMethods(controllerContext, action);
 methodsMatchingName.AddRange(NonAliasedMethods[action]);
 List<methodInfo> finalMethods = RunSelectionFilters(controllerContext, methodsMatchingName);

 switch (finalMethods.Count)
 {
  case 0: return null;
  case 1: return finalMethods[0];
  default: throw CreateAmbiguousMatchException(finalMethods, action);
 }
}

In the RunSelectionFilters method all the found ActionSelection Attributes have their IsValidForRequest method called in the hope that only one potential method remains.

The most common scenario is that we want our controller to behave depending upon the request method (POST vs GET). For this scenario there is the AcceptVerbsAttribute. eg:

[ActionName("Detail")]
[AcceptVerbs("GET")]
public ActionResult DisplayDetail(int productId) { ... }

[ActionName("Detail")]
[AcceptVerbs("POST")]
public ActionResult ModifyDetail(int productId, string name) { ... }

The implementation of the IsValidForRequest method in the AcceptVerbsAttribute is pretty simple:

public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
 if (controllerContext == null) throw new ArgumentNullException("controllerContext");

 string incomingVerb = controllerContext.HttpContext.Request.HttpMethod;
 return Verbs.Contains(incomingVerb, StringComparer.OrdinalIgnoreCase);
}

Adaptive control behavior: LinkButton without javascript

‘Experiment with Adaptive Control Behavior‘ has been an item on my TO-DO list for a very long time and this weekend i finally found some time to do exactly that. Because i hate it that a LinkButton renders as <a href=”javascript:__doPostBackxxx”> i decided to develop a ControlAdapter that makes the LinkButton work without JavaScript. While i was at it i also wrote adapters for the LoginStatus and Login controls. Feel free to play with the Adaptive Rendering Demo.

Revisited the int and string ValueObject templates

After reading The Compare Contract last week i realized that my templates for int and string ValueObjects did not comply with the contract so i decided to add a unittest that reproduces the faulty behavior (and then corrected the implementation):

/// <summary>
/// When comparing instance with null, instance should be greater.
/// </summary>
[TestMethod]
public void ShouldReturnPositiveWhenComparedWithNull()
{
 $classname$ value = new $classname$("0");
 Assert.IsTrue(value.CompareTo(null) > 0);
}

Anyway, feel free to download the corrected IntValueObject and StringValueObject templates.

The Best Damn Windows Server 2003 Book Period

Last week i have read The Best Damn Windows Server 2003 Book Period. Although the book contains some interesting guidance i became annoyed with the fact that the book is overloaded with screenshots. Without those screenshots this book would contain around 250 interesting pages.