ASP.NET Tips: DropDownList.ClearSelection() to avoid "Cannot have multiple items selected in DropDownList"

Problem
I was facing the following Exception when I was programmatically assigning Selected Value of a DropDownList with the following piece of code.


ListItem item = DropDownListTest.Items.FindByValue(“Test”);
  if (item != null)
     item.Selected = true;

Exception


Cannot have multiple items selected in a DropDownList.


Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Web.HttpException: Cannot have multiple items selected in a DropDownList.
Source Error:


An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.


Stack Trace:



[HttpException (0x80004005): Cannot have multiple items selected in a DropDownList.]
   System.Web.UI.WebControls.DropDownList.VerifyMultiSelect() +107
   System.Web.UI.WebControls.ListControl.RenderContents(HtmlTextWriter writer) +1825978
   System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +29
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +25
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +121
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +22
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +199
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +20
   System.Web.UI.Control.Render(HtmlTextWriter writer) +7
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +25
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +121
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +22
   CSSFriendly.WizardAdapter.RenderStep(HtmlTextWriter writer, Wizard wizard) +137
   CSSFriendly.WizardAdapter.RenderContents(HtmlTextWriter writer) +93
   System.Web.UI.WebControls.Adapters.WebControlAdapter.Render(HtmlTextWriter writer) +23
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +2116097
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +121
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +22
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +199
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +20
   System.Web.UI.Control.Render(HtmlTextWriter writer) +7
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +25
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +121
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +22
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +199
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +20
   System.Web.UI.UpdatePanel.RenderChildren(HtmlTextWriter writer) +236
 

Solution

The solution is to remember to call ClearSelection() Method before calling FindByValue(“”) or FindByText(“”) Method.

The following piece of code will work fine.


DropDownListTest.ClearSelection();


ListItem item = DropDownListTest.Items.FindByValue(“Test”);
  if (item != null)
     item.Selected = true;

I also noticed, I do not get the “Cannot have multiple items” exception when I use SelectedIndex instead. i.e.

DropDownListTest.SelectedIndex = 12;



Hope this saves some of your time. Happy Coding.


Shahed Khan
CEO Simplexhub
Co-Founder PageFlakes
Founder Smart Code Generator

Reflection Tips: Generate Mock objects for Test Cases.

Filling up Mock objects with random data is possibly one of the most time consuming and boring chapter of writing test cases. Let say we have the following classes and we want to write some mock objects.

SmartDataManagement - Microsoft Visual Studio

 

Mock Object Code Example

       private Client GetMockClient()
        {
            Client Client1 = new Client();
            Client1.FirstName = “Random String 6dc22d70-ad0c-4552-9c86-2925e723a326″;
            Client1.LastName = “Random String 3e08dc98-495a-4a70-bff4-b7b21489b0d0″;

            ClientAddress ClientAddress2 = new ClientAddress();

            ContactAddress ContactAddress3 = new ContactAddress();
            ContactAddress3.Address = “Random String e5957034-893b-4d2c-a29a-5b23e2561c00″;
            ContactAddress3.Phone = “Random String 8d034e87-ece3-42b8-ae97-35fad1639f41″;
            ContactAddress3.Mobile = “Random String 73a6abad-3268-4ae4-b01c-1732ab0f5f52″;
            ClientAddress2.HomeAddress = ContactAddress3;

            ContactAddress ContactAddress4 = new ContactAddress();
            ContactAddress4.Address = “Random String 117ef00d-f29d-4697-97ae-123a6b56da4f”;
            ContactAddress4.Phone = “Random String 8e4d0bbe-f470-4438-8940-06d9889e3943″;
            ContactAddress4.Mobile = “Random String 6f0cba5c-5a88-4e5b-88ae-32a569cffa41″;
            ClientAddress2.ShippingAddress = ContactAddress4;

            Client1.ClientAddress = ClientAddress2;

            Misc Misc5 = new Misc();
            Misc5.OrderDate = DateTime.Now;
            Misc5.Quaitity = 945515547;
            Misc5.DeliveryDate = DateTime.Now;

            Customer Customer6 = new Customer();

            CustomerDemographics CustomerDemographics7 = new CustomerDemographics();
            CustomerDemographics7.FirstName = “Random String 9b9542e6-2eb9-4ac8-bbd9-46272c8531b4″;
            CustomerDemographics7.LastName = “Random String 275ca427-9373-41a7-8249-9a3fd94631bd”;

            ContactAddress ContactAddress8 = new ContactAddress();
            ContactAddress8.Address = “Random String c9d18341-cb7e-4086-ba09-76fd7eb09f71″;
            ContactAddress8.Phone = “Random String d88849f2-f443-46b1-9d21-3eaed1739696″;
            ContactAddress8.Mobile = “Random String 984cfe2b-c35e-46f4-8eb1-27342d3e21b2″;
            CustomerDemographics7.HomeAddress = ContactAddress8;

            ContactAddress ContactAddress9 = new ContactAddress();
            ContactAddress9.Address = “Random String e67ae73f-8edd-47d1-add0-b1e84ddb6b05″;
            ContactAddress9.Phone = “Random String 91b8d44e-3718-4cc7-be8a-194d308b8969″;
            ContactAddress9.Mobile = “Random String a0d19e07-2b80-4f7a-acd2-7a507455c000″;
            CustomerDemographics7.ShippingAddress = ContactAddress9;

            Customer6.CustomerDemographics = CustomerDemographics7;

            Misc5.AlternativeCustomer1 = Customer6;

            Client1.Misc = Misc5;

            return Client1;

        }


As you can see we will need to spare significant amount of time to prepare a Mock object for “Client” class. But you will be happy to know that I did not write a single line of the code that I pasted above. Yes, I generated it using Reflection. Let me share that magical piece of code with you which can save you a heaps of time.

The Mock Helper

    public class MockHelper
    {
        public MockHelper()
        {
            this.MaxDepth = 100;
        }

        int index = 1;   

        Dictionary<string, string> keys = new Dictionary<string, string>();
        List<string> assemblyList = new List<string>();
        StringBuilder codeBuilder = null;

        public int MaxIndexValue { get; set; }
        public string Generate(object obj)
        {
            //Assembly List that we are interested in for recursive calls, add according to your need.
            assemblyList.Add(“SmartDataManagement.Blog”);

            codeBuilder = new StringBuilder();
            GenerateCode(obj, string.Empty);
            return codeBuilder.ToString();
        }       

        private void GenerateCode(object obj, string theKey)
        {         
            string instanceName = string.Format(“{0}{1}”, obj.GetType().Name, index);
            codeBuilder.AppendLine(String.Format(“{0} {1} = new {0}();”, obj.GetType().Name, instanceName));
            keys.Add(theKey, instanceName);
            //Iterate through the list of Public Properties of the object instance
            foreach (System.Reflection.PropertyInfo property in obj.GetType().GetProperties())
            {     
                //Decide to dig deeper, if a PropertyType belongs to the assemblies that we are interested in, we go deep.
                if (GoDeeper(property))
                {
                    index = index + 1;                  
                    //Avoid infinite Loop situation
                    if (index < this.MaxIndexValue)
                    {
                        object propertyInstance = property.GetValue(obj, null);                       
                        if (propertyInstance == null)
                        {
                            //Dynamically create Property Instance
                            propertyInstance = Activator.CreateInstance(property.PropertyType);
                            if (property.CanWrite)
                                property.SetValue(obj, propertyInstance, null);
                            string key = Guid.NewGuid().ToString();
                            codeBuilder.AppendLine();
                            //Recursive call
                            GenerateCode(propertyInstance, key);

                            codeBuilder.AppendLine(String.Format(@”{0}.{1} = {2};”, instanceName, property.Name, keys[key]));
                            codeBuilder.AppendLine();
                        }
                    }
                }
                else if (property.PropertyType == typeof(string))
                {
                    codeBuilder.AppendLine(String.Format(@”{0}.{1} = “”{2}””;”, instanceName, property.Name, GetRandomString()));
                }
                else if (property.PropertyType == typeof(DateTime))
                {
                    codeBuilder.AppendLine(String.Format(@”{0}.{1} = DateTime.Now;”, instanceName, property.Name));
                }
                else if (property.PropertyType == typeof(int))
                {
                    codeBuilder.AppendLine(String.Format(@”{0}.{1} = {2};”, instanceName, property.Name, GetRandomInt()));
                }
            }
        }

        private bool GoDeeper(PropertyInfo property)
        {
            //Dig deeper for interested Assemblies only, Please feel free to extend and put complex logics to serve your purpose.
            foreach (string assemblyName in assemblyList)
            {
                if (property.PropertyType.Assembly.FullName.Contains(assemblyName))
                    return true;
            }
            return false;
        }

        private string GetRandomString()
        {
            return String.Format(“Random String {0}”, Guid.NewGuid().ToString());           
        }

        private int GetRandomInt()
        {
            byte[] buffer = Guid.NewGuid().ToByteArray();
            return BitConverter.ToInt32(buffer, 0);
        }
    }

The above code is self explanatory, I also commented to give an idea of how this is working, In short, I take an instance of the desired class, iterate through all of its Properties using Reflection and generate desired piece of code. While iterating, I also create property instance  as required and loop thorough the properties of the child in a recursive manner until all of them are served. The assemblyList object maintains the list of the assemblies that we are interested in for recursion.  Its worth mentioning the above piece of code has limitations, it will not work in the cases where there are circular references of Types for properties, that is why I kept a check for MaxIndexValue to break the infinite loop scenario.



SmartDataManagement - Microsoft Visual Studio (2) 

Fig, shows an example of circular references of Types, here Client has Misc property (of Type: Misc), and Misc has AlternativeClient1 property (of Type: Client).

The MockHelper has very simple logic to decide to create dynamic instances and to do recursive calls, it will get stuck within Client and Misc for this example. We can definitely overcome this by putting more complex logics and checks. I wanted to keep it simple and moreover it serves my purpose. Also here I cater with int, string and DateTime only, please feel free to extend to serve your purpose. You will notice I used StringBuilder above to accumulate the generated codes, but I normally use my SmartCodeGenerator and write simple templates for this kind of tricks, SmartCodeGenerator provides a lot more flexibility and comes with robust templating feature for purposes like this.

Usage


            MockHelper helper = new MockHelper();
            //Your desired class instance
            Client client = new Client();
            string code = helper.Generate(client);

Its quite simple to use the above helper, just create an instance of the MockHelper, then pass an instance of your desired class, it will return you the mock object code as we have seen above. Infact, the above piece of code can speed you up for any cases where you need to create instances of a class and need to write code to fill all its properties, moreover the generated code can also reduce chances of errors and typos that normally happens when we do it manually.

Thank you for being with me so far, hope this saves you some time, Happy coding :)

Shahed Khan
CEO Simplexhub
Co-Founder PageFlakes
Founder Smart Code Generator