2
votes

I am getting the following exception from my ASP page during rendering:

Cannot have multiple items selected in a DropDownList.

at System.Web.UI.WebControls.DropDownList.VerifyMultiSelect() at System.Web.UI.WebControls.ListControl.RenderContents(HtmlTextWriter writer) at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) at System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) at System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) at System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) at System.Web.UI.Control.Render(HtmlTextWriter writer) at System.Web.UI.Page.Render(HtmlTextWriter writer) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

None of my code is in the stack trace, and my page has seven drop down lists on it. I am setting the selected rows on the drop down lists in my code based on data from several database tables as well as rules about default selections. So it is quite possible I have a bug where I set the selected item on one of my fields. But how can I tell which field is causing the problem?

In Global.asax I have

    void Application_Error(object sender, EventArgs e) 
    {
        // Code that runs when an unhandled error occurs
        Exception lastException = Server.GetLastError();
    }

Which I am able to set a breakpoint on but nothing in the exception seems to tell me which field was being rendered when the exception got thrown.

Any hints on where to find this information or debugging strategies that will help me find it?

4
Of course I've tried debugging. The compile phase of creating the page will break and highlight the line but once it gets into rendering the controls it doesn't do that.verisimilidude
I'm just having this problem myself. Thank you for asking the question and doing a better job of it than I would!user645280
@Marko If you knew anything about this exception you would know validation happens in a later rendering phase. Why didn't you look at the provided stack trace? Doesn't that show you the error is not raised during function calls on the object in question?user645280

4 Answers

2
votes

Your code helped me a lot. I now have pinpointed which DDL is a the culprit in my own code.

I took a few liberties with your code, here is my version:

protected List<Control> RecursivelyFindAllDropDownLists(
    Control parent, List<Control>listDropDowns
    )
{
    foreach (Control c in parent.Controls)
    {
        if (c == null || !(c is Control) )
            continue;
        else if (c is DropDownList)
            listDropDowns.Add(c);
        else
            RecursivelyFindAllDropDownLists(c, listDropDowns);
    }
    return listDropDowns;
}
protected void Page_PreRender(object sender, EventArgs e)
{
    List<Control> ddls = new List<Control>();
    RecursivelyFindAllDropDownLists(this, ddls);  // find ddls automatically.  
    foreach(DropDownList ddl in ddls)
    {
        Boolean oneSelected = false;

        // loop over all the list items in the drop down
        foreach (ListItem itm in ddl.Items)
        {
            if (itm.Selected && !oneSelected)
                oneSelected = true;
            else if (itm.Selected) // should never happen
                throw new Exception(String.Format(
                    "Multiple values in DropDownList: " + ddl.ID
                    ));
        }
    }
}

Thanks again for sharing your struggle with the rest of us!

1
votes

Launch exception dialog using Ctrl+Alt+E option and on "Common Language Runtime Exceptions" row select "Thrown" checkbox. Attach the worker process and it will directly take you to the line that is causing the problem.

1
votes

What I had to do was check all the drop down controls in the pre-render to find which ones where causing the problem. Once I could find that I was able to zero in on which fields where causing the problem and found my bug. The bug was caused because setting the Selected property of a list item in a drop down does not unselect other items, but setting the DropDownList's SelectedItem or SelectedIndex property does unselect previously selected items.

Since this is my code I could stop on it with the debugger when it found two items selected. Using quickView you can examine the field ddl.SelectedIndicesInternal.Count, a protected field that will tell you directly (with the need for the loop) how many (and which ones, if you look into the array) elements are selected. Unfortunately this is a protected field and can't be checked by my code without getting around the protection level.

1
votes

In hope that it may be useful to others fighting a similar bug, here is the code I used to check what items were selected:

        protected override void OnPreRenderComplete(EventArgs e)
        {
            base.OnPreRender(e); if (IsPostBack) return;

            // check that only one element is selected in a dropdown list
            DropDownList[] ddls = { ddl_0, ddl_1, ddl_2, ddl_3, ddl_4, ddl_5};
            foreach(DropDownList ddl in ddls)
            {
                // loop over all the list items in the drop down
                Boolean oneSelected = false;
                foreach (ListItem itm in ddl.Items)
                {
                    if (itm.Selected && !oneSelected)
                    {
                        oneSelected = true;
                    } else if (itm.Selected)
                        // should never happen
                        throw new Exception(String.Format(
                            "Multiple values in DropDownList");
                }
            }
        }