CSS Adapters cause multiple PostBacks in IE RRS feed

  • Question

  • User550500492 posted

    Hello CSS Adapter team (and Adapter users)!

    Recently I've been trying to use CSS Adapters along with the Membership/Roles/Provider controls and I've come across an issue where the Adapters cause the page to PostBack twice when using IE. (I tested using IE7 and FF 2.0... but others have confirmed the issue exists in IE6 as well).

    For example, when using the CreateUserWizard and it's Adapter, clicking the submit button (which kicks off the CreateUserWizardStep) causes the page to PostBack twice in a row. From an end-user point of view an error message is displayed on the screen, and rightly so. By stepping through the code in debug mode, I was able to verify that the first PostBack successfully created a user (and the user shows up in the aspnet_Membership table). However when they wizard tries to create the user for the 2nd PostBack it fails b/c the user already exists. Hence, an error is thrown and shown to the user.

    A similar situation occurs with the PasswordRecovery control - the password is actually reset twice, and two emails are sent to the user.

    You can confirm the double PostBack using Fiddler.

    1. fire up Fiddler and go to a page using one of the above controls (and their respective Adapter of course).
    2. Use the control.
    3. Look in the Fiddler "HTTP Sessions" window and you'll see duplicate POST requests for the same page.

    Others have reported the same issue, though they didn't root-cause it as being a double-PostBack issue. See here (http://forums.asp.net/thread/1638129.aspx). The only "solution" I've found so far is to disable the Control Adapter for the CreateUserWizard and PasswordRecovery controls.

    Oh, and I do apologize for coming off a bit rude in the other post(s)... it was late, I was tired and frustrated... but now I'm in a much better state of mind.

    So, to recap:

    • using RTM version of CSS Adapters
    • using asp.net 2.0 Membership/Profile/Roles controls with CSS Adapters
    • Membership controls + CSS Adapters work fine with FF 2.0
    • some (possibly all?) Membership controls + CSS Adapters cause double PostBack with IE7 (and others have confirmed same issue with IE6).

    Please let me know if there is anything I can to do help resolve this issue.

    Thank You!



    Wednesday, April 18, 2007 11:15 PM

All replies

  • User1324923368 posted
    I'm facing the same issue with the CreateUserWizard too. [:(] Hopefully there will be a fix for this soon!
    Thursday, April 19, 2007 1:31 AM
  • User550500492 posted

    How did I miss this? http://www.codeplex.com/cssfriendly

    As best I can tell, the CSS Friendly Adapters are now hosted and run from CodePlex - meaning all bug reports, suggestions, etc... should be submitted over there.

    Can someone at this forum (Russ?) confirm that? And if so... I'll get busy over there so we can try to get this issue fixed.

    Thanks all!

    Thursday, April 19, 2007 3:11 PM
  • User-534056067 posted
    Go for it. http://forums.asp.net/thread/1609640.aspx
    Thursday, April 19, 2007 3:30 PM
  • User653031191 posted

    Well this is my first ever forum post so please forgive me if it is a bit verbose or lacking in any way [:)]

    After spending a bit of time debugging the double postback problem with the CreateUserWizardAdapter I've found that it's caused by a slight problem with the html that is being rendered out for the create user button and I have come up with a fix for it that involves changing the CSS Control Adapter code. The solution for this problem can also be used to fix the double postback problems caused by the PasswordRecoveryAdapter, ChangePasswordAdapter, and LoginAdapter. Hopefully someone that looks after the sourcecode for the CSS Adapter project adds the fix to the project soon because it is affecting quite a few people!

    Double Postback Problem - Cause (skip this if you just want the fix!):

    Buttons that reside within the controls that are adapted by the CSS Control Adapters, for example the CreateUserWizard.CreateUserButton, are rendered out differently depending on the button type (which is set for example via CreateUserWizard.CreateUserButtonType = ButtonType.Link). The default button type used by the membership controls is Button. The following html controls are rendered out for the different System.Web.UI.WebControls.ButtonType enum values:

    ButtonType.Button: input, type=submit
    ButtonType.Image: input, type=image
    ButtonType.Link: anchor

    Both of the input controls will automatically cause the form that they reside within to be posted back to the server when they are clicked, whereas the anchor will not - instead it needs some javascript to cause a postback. This is where the problem is - all three html controls are rendered out with javascript attached to post the form back to the server on a click event, which allows buttons of type 'Link' to work correctly but causes buttons of type 'Button' and 'Image' to postback twice - the first time due to the javascript and the second because of the native postback.

    The javascript method used to cause the postback is as follows:

    WebForm_DoPostBackWithOptions(WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit))

    In order to stop 'Button' buttons and 'Image' buttons firing twice we just need to set the clientSubmit parameter to false when these types of buttons are rendered out.

    Other problems (specific to the CreateUserWizardAdapter control)

    Once the double postback problem was fixed two other problems popped up. The first was that users still weren't being created. This was because the id and name (which is derived from the id) being used for the create user button was missing an underscore.

    The other problem was that the cancel button didn't work. It was also missing an underscore from its name and also wasn't registered for Event Validation.

    Code change to fix the Double Postback Problem in the CreateUserWizardAdapter (applicable to the other adapters too):


    PostBackOptions options = new PostBackOptions(btn, "", "", false, false, false, clientSubmit, true, wizard.ID);


    bool clientSubmit = (wizard.CreateUserButtonType == ButtonType.Link);
    PostBackOptions options = new PostBackOptions(btn, "", "", false, false, false, clientSubmit, true, wizard.ID);

    Code change to fix all of the problems caused by the CreateUserWizardAdapter:

    Replace the WriteCreateUserButtonPanel with the following: 
    private void WriteCreateUserButtonPanel(HtmlTextWriter writer, CreateUserWizard wizard)
        string btnParentCtrlId = "__CustomNav0";
        Control btnParentCtrl = wizard.FindControl(btnParentCtrlId);
        if (btnParentCtrl != null)
            string createUserBtnId = btnParentCtrlId + "_StepNextButton";
            string idWithType = WebControlAdapterExtender.MakeIdWithButtonType("StepNextButton", wizard.CreateUserButtonType);
            Control btn = btnParentCtrl.FindControl(idWithType);
            if (btn != null)
                bool clientSubmit = (wizard.CreateUserButtonType == ButtonType.Link);
                PostBackOptions options = new PostBackOptions(btn, "", "", false, false, false, clientSubmit, true, wizard.ID);
                string javascript = "javascript:" + Page.ClientScript.GetPostBackEventReference(options);
                javascript = Page.Server.HtmlEncode(javascript);
                WebControlAdapterExtender.WriteBeginDiv(writer, "AspNet-CreateUserWizard-CreateUserButtonPanel", "");
                Extender.WriteSubmit(writer, wizard.CreateUserButtonType, wizard.CreateUserButtonStyle.CssClass, createUserBtnId, wizard.CreateUserButtonImageUrl, javascript, wizard.CreateUserButtonText);
                if (wizard.DisplayCancelButton)
                    string cancelBtnId = btnParentCtrlId + "_CancelButton";
                    string cancelBtnIdWithType = WebControlAdapterExtender.MakeIdWithButtonType("CancelButton", wizard.CancelButtonType);
                    Control cancelBtn = btnParentCtrl.FindControl(cancelBtnIdWithType);
                    if (cancelBtn != null)
                        Extender.WriteSubmit(writer, wizard.CancelButtonType, wizard.CancelButtonStyle.CssClass, cancelBtnId, wizard.CancelButtonImageUrl, "", wizard.CancelButtonText);


    So now we can all get on and do the actual stuff we were trying to achieve before we ran into this problem [:)].


    Tana Isaac
    Solintex Limited (NZ)

    Saturday, April 21, 2007 1:12 PM
  • User-534056067 posted

    Dear Tana, thank you for your posting (above). It will be great when folks start reporting back on this thread to discuss their results. I'm really hoping that you've nailed the solution finally. This one has alluded folks for a long time and has been a constant headache for many users. Again, thank you for both your proposed solution and for the detailed way in which you reported it.

    If this does, indeed, fix it for most folks (or everyone), how would you feel about joining the CodePlex project where the community now maintains these adapters? See http://forums.asp.net/thread/1609640.aspx and http://forums.asp.net/thread/1610083.aspx. You might want to contact Brian Demarzo who kindly set up that CodePlex project and is helping to administer and run it. Brian's info registered at this forum is http://forums.asp.net/members/bdemarzo.aspx. The CodePlex project is at http://www.codeplex.com/cssfriendly.

    It is super-important that we get enough of a core of great devs contributing to this ongoing CodePlex effort so we have enough vibrancy with the adapters to keep folks interested in continuing to use them. So I'm really hoping that folks like you will agree to at least consider making a few contributions via the CodePlex mechanism. In any case, I want to applaud your proposed solution (above) and its thoughtful analysis.

    Saturday, April 21, 2007 3:50 PM
  • User653031191 posted

    Cheers for the compliment Russ and the invitation to contribute to the project. I am happy to help out where possible as I have enjoyed the benefits of using the CSS Adapters in several projects now and it would only be fair to give something back in return. I'll flick Brian a message now and ask him to sign me up.



    Sunday, April 22, 2007 12:33 AM
  • User-1385398420 posted

    Has anyone tried implementing this fix and did an analysis to see if it (1) fixes the problem and (2) doesn't break anything? It seemed OK in my testing, but that's far from comprehensive.


    Tuesday, May 1, 2007 10:06 AM
  • User550500492 posted

    I applied the changes to an app that I'm working on and they seem to have solved the issues described. I've did a cursory glance at the other controls and didn't notice anything wrong with them after making the changes... but as you said, that's far from being completely tested.

    Probably the best thing would be to get the changes into CodePlex (I'll submit a patch if you let me know what patch format you want) with the changes so they can be applied and at least that will get the changes into a build so others can easily test/use them.


    Tuesday, May 1, 2007 10:16 AM
  • User-1385398420 posted

    Patch format? I don't think CodePlex has one. Just send me the updated files and I'll apply them and look at diffs locally.

    Actually I've already added the patched code referenced above in a local version -- I just haven't checked in the changes. I guess it's time to do so to get more feedback on them.


    Tuesday, May 1, 2007 10:35 AM
  • User550500492 posted

    >> Patch format? I don't think CodePlex has one.

    Right... it's actually TFS that lacks built-in patch generation and application (which is yet another reason it is a bad choice for an OSS code repostiory/management tool), but that's for another thread, another time... like the one Ayende has been having as of late. [:)]

    Anyhow, I didn't know if you used WinMerge (my fav) or some other graphical diff tool that is able to generate and apply patches. If so I could send you the patch that way. But if you've already applied the changes locally, then I suppose there is no point in me duplicating your work when you could just them directly into the repository... unless you'd rather do it that way?

    Tuesday, May 1, 2007 10:48 AM
  • User-1385398420 posted

    I'm a heavy Subversion user (and reader of Ayende's blog, for that matter) so I have most diff tools installed. I use TortoiseMerge most often (quick and easy) but have others installed.

    Probably best to send over your patch file and I'll toss it into my local install (which isn't on the PC I'm at right now) so I can compare our changes and make sure we cover both bases. Once I do it I'll check it in and we can compare notes.


    Tuesday, May 1, 2007 10:53 AM
  • User-42637473 posted


    Hello. I am using CSS Adapter for one of my site and I am facing the same problem with CreateUser Adaptor. I am using VB.NET so i translated the WriteCreateUserButtonPanel method that you posted and replaced it in my code. But now the user is not getting creating. Can anyone help me ? It would be great if someone could update the adaptor and make it available for others to download.


    Thursday, May 17, 2007 2:45 PM
  • User653031191 posted

    Hi there,

    Have you tried debugging the code when you click the create button? How about giving us some more info, like:

    - Is the form posting back to server (i.e. it's not getting stopped by javascript validation)?

    - If you examine the Request.Form items collection do you see the values that you entered on the screen?

    - If you examine the properties on the CreateUser control after the page load event fires are they populated with the values that you entered?

    It might be worth posting a snippet of your code up so that we can have a look at it too - assuming it doesn't contain any sensitive information that is.



    Sunday, May 20, 2007 7:06 AM
  • User806608047 posted

    Hi Tana,

    I have difficulty getting ChangePassword control to work properly, ie, user enters correct current password and valid new password, new password is updated in DB but control shows error.

     How can I go about implementing the above-mentioned code? Where should I place them?


    Friday, July 6, 2007 8:18 AM
  • User653031191 posted

    Hi there,

    It sounds like the double postback problem - give the following a go:

    In the ChangePasswordAdapter.cs file locate the WriteSubmitPanel method. In this method locate the following line of code:

    PostBackOptions options = new PostBackOptions(btn, "", "", false, false, false, true, true, changePwd.UniqueID);

    and replace it with these lines: 

    bool clientSubmit = (changePwd.ChangePasswordButtonType == ButtonType.Link);
    PostBackOptions options = new PostBackOptions(btn, "", "", false, false, false, true, true, changePwd.UniqueID);

    Give it a go and let us know how you get on. I tried it locally and it worked for me anyway [:)].



    Saturday, July 7, 2007 2:51 AM
  • User653031191 posted

    Sorry I pasted the wrong code in my last reply - the correct patch is as follows:

    bool clientSubmit = (changePwd.ChangePasswordButtonType == ButtonType.Link);
    PostBackOptions options = new PostBackOptions(btn, "", "", false, false, false, clientSubmit, true, changePwd.UniqueID);
    The previous post didn't actually use the clientSubmit variable [:P]
    Saturday, July 7, 2007 3:09 AM
  • User806608047 posted


    In the ChangePasswordAdapter.cs file locate the WriteSubmitPanel method. In this method locate the following line of code:



    Hi Tana,

    thanks for your reply. I don't have a ChangePasswordAdapter.cs file. Do I have to create one? I don't remember using a control adapter. All I did was dropped a ChangPassword control onto a .ascx and wrote validation/update routines.


    Monday, July 9, 2007 4:29 AM
  • User-1385398420 posted

     I'm adding these fixes to the CodePlex site. I think they've been thoroughly hashed out enough.

    Thanks again to Tana for uncovering this fix! 

    Friday, July 20, 2007 4:38 PM
  • User-347312995 posted

    I'm having an odd isse with Double-Sumit...only it only occurs in Firefox.

     I have a static method that returns a string which I attach to the 'onclick' attribute of the button on its Load event.  This script will disable the button when clicked, only if the page validators pass. 

    The script works, but for some reason Firefox wants to double post data. The one caveat is the button is inside an updatepanel and there is an asycronous postback trigger defined.   Here is the code (sorry for the mess):



    <asp:UpdatePanel id="updComments" runat="server" ChildrenAsTriggers="false" UpdateMode="conditional" >
                        <asp:AsyncPostBackTrigger ControlID="btnSubmitComment" EventName="Click" />
                    <ContentTemplate >
                    <div id="dvComments" style="clear: both;width: 640px; border: none 1px red; ">
                        <div id="dvCommentHeader_General"><h3>comments / all labels</h3></div>
                        <div id="dvCommentHeader_Specific" style="display: none;"><h3>comments / label specific</h3></div> 
                        <div id="dvCommentThread" runat="server" style="border: none 1px blue; ">
                            <div id="dvCommentInput" style="margin-top: 20px;">
                                <div id="dvCommentText" style="float: left; width: 300px; border: none 1px blue; ">
                                    <h4>Leave a Comment</h4>
                                    <div id="dvCommentTextValid" runat="server" style="border: none 1px black; ">
                                        <asp:TextBox ID="txtComment" 
                                        MaxLength="200" runat="server" 
                                        Columns="35" Rows="7" 
                                        Style="overflow: hidden; " 
                                        onkeyup="MonitorTxtComment(this);" onfocus="new ResizingTextArea(this);"
                                         <br />
                                        <uc3:PopText id="ucPopText" runat="server" TargetControlID="txtComment" DefaultMode="Append" />
                                        <br />
                                        <asp:Button ID="btnSubmitComment" runat="server" Text="Submit" 
                                        OnClick="btnSubmitComment_Click" OnLoad="btnSubmitComment_Load" ValidationGroup="vldCommentGroup" />                   
                                         <asp:RequiredFieldValidator ID="vldReqTxtComment" ValidationGroup="vldCommentGroup" 
    'margin-top: 15px;'>A comment is required</div>" CssClass="ValidationCss"/> <asp:RegularExpressionValidator id="vldRegExTxtComment" runat="server" ControlToValidate="txtComment" ValidationGroup="vldCommentGroup" ValidationExpression="^[\s\S]{0,200}$" ErrorMessage="
    'margin-top: -15px;'>Comment length limited to 200 chracters</div>" EnableClientScript="true" CssClass="ValidationCss" > </div> <div id="dvCommentTextInvalid" runat="server" style="border: none 1px blue;"> <span class="ContrastText" style="font-weight: bold; font-size: 1.5em;">Want to leave a comment?</span> <br /> <br /> <asp:linkbutton ID="btnSignUp" runat="server" Text="Sign Up" OnClick="btnSignUp_Click" PostBackUrl="~/viewImage.aspx" /> (new members) <br /><br />or <br /><br /> <asp:linkbutton ID="btnSignIn" runat="server" Text="Sign In" OnClick="btnSignIn_Click" /> (existing members) </div> </div> <div id="dvBrand" style="float: left; width: 320px; border: none 1px red; margin-left: 10px;"> <h4>Brand this Label</h4> <uc1:BrandCloud id="TagCloud1" runat="server" ShowAutoSuggest="true" ShowResetButton="true" ShowRealOrFake="true" /> </div> </div> <div id="dvClear2" style="clear: both;"></div> </div> </ContentTemplate> </asp:UpdatePanel>

     Here is the script call:

    1     protected void btnSubmitComment_Load(object sender, EventArgs e)
    2        {
    3            btnSubmitComment.Attributes.Add("onclick", Utils.GetLockButtonJscript(Page, btnSubmitComment, btnSubmitComment.Text, new ArrayList(), ""));
    4        }

     And the method:

    1    /// <summary>
    2    /// Generates auto-disable butotn
    3    /// </summary>
    4    /// <param name="p">Page Instance</param>
    5    /// <param name="btn">Button Instance</param>
    6    /// <param name="disabledText">Text to display on button when clicked</param>
    7    /// <param name="aCol">Optional: Collection of controls on page to disable as well</param>
    8    /// <param name="customScript">Optional: Custom script to run before disabling the button</param>
    9    /// <returns></returns>
    10       public static string GetLockButtonJscript(Page p, Button btn, string disabledText, ArrayList aCol, string customScript)
    11       {
    12               disabledText = disabledText == "" ? "Processing..." : disabledText;
    13               disabledText = disabledText.Replace("'", "");
    15               StringBuilder sb = new StringBuilder();
    16               if (btn.CausesValidation && p.Validators.Count>0)
    17               {
    18                   sb.Append("if (typeof(Page_ClientValidate) == 'function') { ");
    19                   sb.Append("if (Page_ClientValidate('"+btn.ValidationGroup+"') == false) { return false; }} ");
    20               }
    21               if (!String.IsNullOrEmpty(customScript))
    22               {
    23                   sb.Append(customScript);
    24               }
    25               PostBackOptions opt = new PostBackOptions(btn, "", "", false, false, false, true, true, btn.ValidationGroup);
    26               sb.Append(p.ClientScript.GetPostBackEventReference(opt));
    27               sb.Append(";");
    28               sb.Append("this.disabled='true';this.value='" + disabledText + "';");
    29               foreach (Control c in aCol)
    30               {
    31                   if (c is Button)
    32                   {
    33                       sb.Append("" + c.UniqueID + ".disabled='true';");
    34                   }
    35               }
    37               return sb.ToString();
    39       }
    I've read that setting the 4th boolean variable on PostBackOptions to FALSE would potentially fix double-postback..but it doesn't - the page doesnt post back at all when in an updatepanel.
    I suspect the updatepanel is submitting the data twice because of the register trigger?
    Any suggestions?
    Tuesday, August 21, 2007 12:46 AM
  • User-347312995 posted

    As a folowup, I just realized the problem - but I'm baffled why IE and Firefox behave differently.

    Here is the rendred button output:


     <input type="submit" name="ctl00$ContentPlaceHolder1$btnSubmitComment" value="Submit" onclick="if (typeof(Page_ClientValidate) == 'function') { if (Page_ClientValidate('vldCommentGroup') == false) { return false; }} WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$ContentPlaceHolder1$btnSubmitComment", "", true, "vldCommentGroup", "", false, true));this.disabled='true';this.value='Submit';WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$ContentPlaceHolder1$btnSubmitComment", "", true, "vldCommentGroup", "", false, false))" id="ctl00_ContentPlaceHolder1_btnSubmitComment" />                   

     Obviously the issue is the WebForm_DoPostBackWithOptions is being added twice ....

    Can anyone think of a workaround?


    Tuesday, August 21, 2007 12:55 AM
  • User-2068359330 posted

    I have tried implementing your change into my project http://www.bridgelabs.info and it does not work. Know the control doesn't create the user and the error message no longer displays. It just returns to the create user screen.

     Did this actually work for anyone else...



    Tuesday, September 18, 2007 3:32 PM
  • User-1587293064 posted

    Dean I had this problem and I realized that with the latest CSS adapters (as of this post date), you don't need the underscore fix anymore. Instead of grabbing the whole Create function as recommended previously, just put the 2 lines in the appropriate place:

    bool clientSubmit = (wizard.CreateUserButtonType == ButtonType.Link);
    PostBackOptions options = new PostBackOptions(btn, "", "", false, false, false, clientSubmit, true, wizard.ID);
     I have not tested the Cancel button of the control since I use my own.



    Wednesday, November 21, 2007 10:23 AM
  • User1567340215 posted

    Okay, I converted the code from C# to VB.NET (courtesy the code translators over at developerfusion.co.uk), and it's fixed the submittal problem; however, I'm running into two new issues:

    1. The form submits, only once, and creates the user in the database.  However, it postbacks to the CreateUserWizard form, with the username of the newly registered used populated in the UserName field.  I'm wondering if something got lost in the translation from C# to VB.NET that would normally take care of this.

    2. I have a second step to my wizard, where the user can edit a profile and save it.  However, it seems that the wizard skips over this, and as I said above, postbacks to the empty form (excluding the UserName).  Is this an error in my code, or something else in the adapter?

    Code for CreateUserWizard:

    <asp:CreateUserWizard CssSelectorClass="mchcreate" runat="server" ID="CreateUserWizard1" AutoGeneratePassword="False"

    ContinueDestinationPageUrl="~/Default.aspx" FinishDestinationPageUrl="~/Default.aspx">

    <MailDefinition BodyFileName="~/RegistrationMail.txt" From="webmaster@motorcyclehound.com"

    Subject="MotorcycleHound.Com: New User Registration ">



    <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">


    <asp:WizardStep ID="WizardStep1" runat="server" Title="Set preferences">

    <div class="sectiontitle">

    Set-up your profile</div>

    All settings in this section are optional. The address information is required

    only if you want to order products from our e-store. However, we ask you to fill

    in these details in all cases, because they help us know our target audience,

    and improve the site and its contents accordingly. Thank you for your




    <mb:UserProfile ID="UserProfile1" runat="server" />


    <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">




    EDIT: I take that back, I removed the initial fix and just replaced the two lines as suggested above, now the control throws a "Unable to cast object of type 'System.Web.UI.WebControls.WizardStep' to type 'System.Web.UI.WebControls.TemplatedWizardStep'." error in the adapter.  Any ideas?

    Friday, February 8, 2008 12:24 AM