stevenkuhn.net a special blend of windows, linux, and .net with a touch of randomness

27Aug 08

Extension method to sort ListItems in a ListControl in ASP.NET

Yesterday I needed a way to sort the items in a ListControl (in this case, a DropDownList) after the list had been populated. The reason for that is after I databound my DropDownList from a collection of items, I inserted a few more ListItems depending on certain circumstances. Instead of trying to hack some method of inserting those items in my original collection, I wanted a more elegant solution. After I came across a post on Google I came up with a solution using an extension method and LINQ:

public static void Sort(this ListItemCollection items)
{
  IList<ListItem> itemList = new List<ListItem>();
  foreach (ListItem item in items)
    itemList.Add(item);

  IEnumerable<ListItem> itemEnum =
    from item in itemList orderby item.Text select item;

  items.Clear();
  items.AddRange(itemEnum.ToArray());
}

//example - assume MyDropDownList is a DropDownList on the aspx page
MyDropDownList.DataSource = SomeMethodThatReturnsAList();
MyDropDownList.DataBind();
MyDropDownList.Items.Insert(0, 
	new ListItem("My Display String", "My List Value"));

//this will sort all the items based on ListItem.Text
MyDropDownList.Items.Sort();

I wanted a simple solution so I didn’t do any performance metrics on it. Things I might change is add ability to sort by ListItem.Value, add the ability to change the sort direction, or perhaps sort by a custom comparer. So if you want a way to sort a ListItemCollection, give this a try and let me know what you think! :)

Update (July 16, 2009) The post that I found http://coercedcode.blogspot.com/2007/08/sorting-listitem-collections-in-aspnet.html no longer works. If I find it, I’ll update this post.

13Aug 08

Using TypeMock to mock nHibernate's ISession.Load<T>

The development team I work with uses nHibernate for our data-access and data persistence needs. We also use Typemock Isolator to mock classes and methods during unit tests. This is especially handy to mock certain nHibernate API calls to make sure our unit tests are more isolated. Today, I needed a way to mock nHibernate’s ISession.Load<T>() for all data objects in the project that use nHibernate. To mock a generic method (like ISession.Load<T>()) I would normally do the following:

Mock<ISession> mock = 
	MockManager.MockObject<ISession>(Constructor.Mocked);
mock.AlwaysReturn("Load", new DynamicReturnValue(
	(parameters, context) =>
	{
		// assume MyClass has a constructor with int Id parameter
		return new MyClass( (int)parameters[0] );
	}), typeof(MyClass));

That means anytime I call ISession.Load<MyClass>(1);, I get back a new MyClass object with 1 passed into the constructor. But what if I have 50 different classes similar to MyClass that I want to mock like this? The simplest way is to iterate over a list of types needed and mock them as well, like below:

Mock<ISession> mockSession =
	MockManager.MockObject<ISession>(Constructor.Mocked);

// Retrieve all the types in the same assembly as MyClass
// and mock those types that have the "Id" property
Assembly assembly = Assembly.GetAssembly(typeof(MyClass));
foreach (Type type in assembly.GetTypes())
{
   Type objType = type; // this line is needed because 'type' will 
                        // cause issues with the anonymous method
                        // below.

   if (objType.GetProperty("Id") != null)
   {
      mockSession.AlwaysReturn("Load", new DynamicReturnValue(
      (parameters, context) =>
      {
         return Activator.CreateInstance(objType, parameters[0]);
      }), objType);
   }
}

Obviously you can change the foreach loop to use whatever list of types you need, but this certainly beats having to duplicate code!

04Aug 08

An error was discovered processing the <Security> header

A coworker and I were troubleshooting an issue we were having concerning a .NET call to a webservice that used WSE Security. Our client derived from Microsoft.Web.Services2.WebServicesClientProtocol and every time we tried to call the webservice this error would appear:

An error was discovered processing the <Security> header

A quick search on Google returned a quick, easy solution: verify that client and server have their system time in synch (a 5 minute window is allowed). Once the server time (about 6 minutes apart) was fixed the issue immediately disappeared.

Recent Tweets

Recent Posts