strange server-side validation postback

Discussion in 'ASP .Net' started by Tim_Mac, Aug 21, 2006.

  1. Tim_Mac

    Tim_Mac Guest

    hi,
    using .net 2.0, i have a web form with lots of textboxes, drop-down-lists
    etc. There are lots of required field validators and regular expression
    validators. When i click the 'save' button, the client-side validation is
    executed immediately and the errors flash up on screen. However at the same
    time, a post-back is performed and the page is obviously un-usable while it
    is awaiting a response from the server. it looks very poor from a user
    perspective because they see all the errors and have to wait a few seconds
    for the page to re-load just to show the same errors. the average user
    would not be aware that the page was re-loading and would attempt to ammend
    the errors.

    all the validators are set to Display=Dynamic and EnableClientScript=true.

    this happens in up-level browsers Firefox 1.5.0.6 and Internet Explorer 6.
    using the cassini/VS web server.

    any clues why this would be happening?
    thanks
    tim
     
    Tim_Mac, Aug 21, 2006
    #1
    1. Advertising

  2. Hello Tim,

    Long time no see and how are you doing?

    Based on my description here, your ASP.NET 2.0 page will postback even if
    there're client-side validation error occur, correct?

    I think we need to identify which element or script function cause this
    postback. You can start debugging on the web application and add some break
    points in some postback event handlers and other page events to see whether
    the strange postback will hit into any of the breakpoints. Also, in the IIS
    log, you should be able to find the entries associated with this postback.

    In addition, as you mentioned that the problem page is quite a
    large/complex one(with lots of input entry fields ...), is it possible that
    you reproduce the problem behavior through a simplifed test webform? If
    so, we can help perform some tests on our local side.

    Please feel free to let me know if there is anything I've missed.

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead


    This posting is provided "AS IS" with no warranties, and confers no rights.
     
    Steven Cheng[MSFT], Aug 22, 2006
    #2
    1. Advertising

  3. Tim_Mac

    Tim_Mac Guest

    hi Steven,
    thanks for the reply. yes i've been tied up with development for a good
    while! good to be back.

    you're right, i did some further debugging and the button click event
    handler was indeed firing. The reason is because i was using an extended
    Button class i wrote, called "SmartButton", which you actually helped me out
    with in september last year on this group. it uses javascript to manually
    submit the form, having disabled itself and changed its text to "Please
    wait...", in order to prevent duplicate clicks by the user, and to provide a
    visual cue that the page is busy. the javascript code i was using doesn't
    work with the new way .Net 2 submits a form, e.g.

    onclick="javascript:WebForm_DoPostBackWithOptions(new
    WebForm_PostBackOptions("btnSave", "", true,
    "", "", false, false))

    the full code for my 1.1 version is listed on my blog:
    http://tinyurl.com/owh9y
    the Render method is where the problem is, i tried this simple change in an
    attempt to get it working with .net 2.0:
    {
    this.OnClientClick += ";this.disabled = true; this.value = 'Please
    wait...';";
    base.Render(output);
    }

    but it is too simplistic because the button remains disabled regardless of
    client side validation. it needs to disable itself after successful client
    validation and immediately before the form is actually submitted to the
    server. i can't figure out how to do this because the function
    WebForm_DoPostBackWithOptions is not listed on the page, i guess it's in
    /WebResource.axd...

    would you have any suggestion on how to achieve the same effect with .Net
    2.0?

    many thanks in advance
    tim.
     
    Tim_Mac, Aug 22, 2006
    #3
  4. Thanks for your reply Tim,

    Now I've got that the problem is actually due to the changing of the
    ASP.NET button's postback mechanism.

    As you have found, in ASP.NET 2.0 pages, the Button has exposed a
    "OnClientClick" property to set client-side onclick script handler. And the
    runtime emit a "WebForm_DoPostbackWithOptions" function to replace the
    original "__doPostback" function in 1.0. Also, the built-in script is no
    longer placed in a shared public folder but rendered out through a resource
    handler(webresource.axd)...

    Actually you can still manually request the resource content through the
    generated url, such as:


    <script
    src="/ASPNET/V2/WebSites/NewTestSite/WebResource.axd?d=yDa86RJ5BlmQizOjOSj4H
    M3nrNOaEBU0Q3mZezasA2o1&amp;t=632882923848905939"
    type="text/javascript"></script>


    You can pick the url out and directly access it in brower and get the
    jscript content. I've performed some overview on the built-in scripts.
    "WebForm_DoPostbackWithOptions" function will take a single parameter of
    "Webform_PostBackOption" which contains several constructor params. The
    first is the name of the element which trigger the postback. The last is a
    boolean, indicate whether the function need to explicitly call form.submit
    (for submit button, this is always false). e.g.

    ==============
    WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnSubmit", "",
    true, "", "", false, false));
    ==============

    I've tested in my own button's "OnClientClick" and find that we can call it
    manually in our client-script to trigger the page's client-side vailadtion,
    and then check the "Page_Isvalid" global script variable to determine
    whether the page has validation error. If there is no error, we let it go,
    else wise, we stop our "smart button"'s client-side behavior.


    I've created a test page to demonstrate the work, I've attached the page's
    files in this message. You can get it if you're using outlook express to
    access the newsgroup. If necessary, I can send you via email.


    I'll also paste the page's aspx and codebehind here:


    #btw, I use a hidden disabled button instead of disabling the real button
    since this can avoid additional work to set POSTBACK arguments

    ===========aspx==================
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
    <title>Untitled Page</title>
    <script id="btn_script" language="javascript">
    function btn_click(btn)
    {
    WebForm_DoPostBackWithOptions(new
    WebForm_PostBackOptions("btnSubmit", "", true, "", "", false, false));

    if(!Page_IsValid)
    {
    return false;
    }

    btn.style.display = "none";
    document.getElementById(btn.id + "Fake").style.display = "";

    return true;
    }
    </script>
    </head>
    <body>
    <form id="form1" runat="server">
    <div>
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
    runat="server" ControlToValidate="TextBox1"

    ErrorMessage="RequiredFieldValidator"></asp:RequiredFieldValidator>




    <asp:Button ID="btnSubmit" runat="server" Text="Normal Submit
    Button" OnClick="btnSubmit_Click" />

    <br />smart button <br />
    <hr /><br />

    <span>
    <asp:Button ID="btnSmart" runat="server" Text="Smart Button"
    OnClick="btnSmart_Click" OnClientClick="btn_click(this);" />
    <asp:Button ID="btnSmartFake" runat="server" Text="Smart Button"
    Enabled="false" style="display:none" />
    </span>
    </div>
    </form>
    </body>
    </html>


    ==========code behind================
    public partial class ControlPages_TestButtonPage : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
    Response.Write("<br/>Normal button postback........");
    }
    protected void btnSmart_Click(object sender, EventArgs e)
    {
    Thread.Sleep(2000);

    Response.Write("<br/>Smart button postback........");
    }
    }

    =============================================


    Hope this helps.

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead



    ==================================================

    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.



    Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
    where an initial response from the community or a Microsoft Support
    Engineer within 1 business day is acceptable. Please note that each follow
    up response may take approximately 2 business days as the support
    professional working with you may need further investigation to reach the
    most efficient resolution. The offering is not appropriate for situations
    that require urgent, real-time or phone-based interactions or complex
    project analysis and dump analysis issues. Issues of this nature are best
    handled working with a dedicated Microsoft Support Engineer by contacting
    Microsoft Customer Support Services (CSS) at
    http://msdn.microsoft.com/subscriptions/support/default.aspx.

    ==================================================



    This posting is provided "AS IS" with no warranties, and confers no rights.
     
    Steven Cheng[MSFT], Aug 23, 2006
    #4
  5. Tim_Mac

    Tim_Mac Guest

    hi Steven,
    nice code! thanks for going to all that trouble to post the full working
    code. I will be glad to integrate this into my web library.

    many thanks
    tim
    --------------------------
    blog: http://tim.mackey.ie

    "Steven Cheng[MSFT]" <> wrote in message
    news:...
    > Thanks for your reply Tim,
    >
    > Now I've got that the problem is actually due to the changing of the
    > ASP.NET button's postback mechanism.
    >
    > As you have found, in ASP.NET 2.0 pages, the Button has exposed a
    > "OnClientClick" property to set client-side onclick script handler. And
    > the
    > runtime emit a "WebForm_DoPostbackWithOptions" function to replace the
    > original "__doPostback" function in 1.0. Also, the built-in script is no
    > longer placed in a shared public folder but rendered out through a
    > resource
    > handler(webresource.axd)...
    >
    > Actually you can still manually request the resource content through the
    > generated url, such as:
    >
    >
    > <script
    > src="/ASPNET/V2/WebSites/NewTestSite/WebResource.axd?d=yDa86RJ5BlmQizOjOSj4H
    > M3nrNOaEBU0Q3mZezasA2o1&amp;t=632882923848905939"
    > type="text/javascript"></script>
    >
    >
    > You can pick the url out and directly access it in brower and get the
    > jscript content. I've performed some overview on the built-in scripts.
    > "WebForm_DoPostbackWithOptions" function will take a single parameter of
    > "Webform_PostBackOption" which contains several constructor params. The
    > first is the name of the element which trigger the postback. The last is a
    > boolean, indicate whether the function need to explicitly call form.submit
    > (for submit button, this is always false). e.g.
    >
    > ==============
    > WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnSubmit", "",
    > true, "", "", false, false));
    > ==============
    >
    > I've tested in my own button's "OnClientClick" and find that we can call
    > it
    > manually in our client-script to trigger the page's client-side
    > vailadtion,
    > and then check the "Page_Isvalid" global script variable to determine
    > whether the page has validation error. If there is no error, we let it go,
    > else wise, we stop our "smart button"'s client-side behavior.
    >
    >
    > I've created a test page to demonstrate the work, I've attached the page's
    > files in this message. You can get it if you're using outlook express to
    > access the newsgroup. If necessary, I can send you via email.
    >
    >
    > I'll also paste the page's aspx and codebehind here:
    >
    >
    > #btw, I use a hidden disabled button instead of disabling the real button
    > since this can avoid additional work to set POSTBACK arguments
    >
    > ===========aspx==================
    > <html xmlns="http://www.w3.org/1999/xhtml" >
    > <head runat="server">
    > <title>Untitled Page</title>
    > <script id="btn_script" language="javascript">
    > function btn_click(btn)
    > {
    > WebForm_DoPostBackWithOptions(new
    > WebForm_PostBackOptions("btnSubmit", "", true, "", "", false, false));
    >
    > if(!Page_IsValid)
    > {
    > return false;
    > }
    >
    > btn.style.display = "none";
    > document.getElementById(btn.id + "Fake").style.display = "";
    >
    > return true;
    > }
    > </script>
    > </head>
    > <body>
    > <form id="form1" runat="server">
    > <div>
    > <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    > <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
    > runat="server" ControlToValidate="TextBox1"
    >
    > ErrorMessage="RequiredFieldValidator"></asp:RequiredFieldValidator>
    >
    >
    >
    >
    > <asp:Button ID="btnSubmit" runat="server" Text="Normal Submit
    > Button" OnClick="btnSubmit_Click" />
    >
    > <br />smart button <br />
    > <hr /><br />
    >
    > <span>
    > <asp:Button ID="btnSmart" runat="server" Text="Smart Button"
    > OnClick="btnSmart_Click" OnClientClick="btn_click(this);" />
    > <asp:Button ID="btnSmartFake" runat="server" Text="Smart Button"
    > Enabled="false" style="display:none" />
    > </span>
    > </div>
    > </form>
    > </body>
    > </html>
    >
    >
    > ==========code behind================
    > public partial class ControlPages_TestButtonPage : System.Web.UI.Page
    > {
    > protected void Page_Load(object sender, EventArgs e)
    > {
    >
    > }
    > protected void btnSubmit_Click(object sender, EventArgs e)
    > {
    > Response.Write("<br/>Normal button postback........");
    > }
    > protected void btnSmart_Click(object sender, EventArgs e)
    > {
    > Thread.Sleep(2000);
    >
    > Response.Write("<br/>Smart button postback........");
    > }
    > }
    >
    > =============================================
    >
    >
    > Hope this helps.
    >
    > Sincerely,
    >
    > Steven Cheng
    >
    > Microsoft MSDN Online Support Lead
    >
    >
    >
    > ==================================================
    >
    > Get notification to my posts through email? Please refer to
    > http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    > ications.
    >
    >
    >
    > Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
    > where an initial response from the community or a Microsoft Support
    > Engineer within 1 business day is acceptable. Please note that each follow
    > up response may take approximately 2 business days as the support
    > professional working with you may need further investigation to reach the
    > most efficient resolution. The offering is not appropriate for situations
    > that require urgent, real-time or phone-based interactions or complex
    > project analysis and dump analysis issues. Issues of this nature are best
    > handled working with a dedicated Microsoft Support Engineer by contacting
    > Microsoft Customer Support Services (CSS) at
    > http://msdn.microsoft.com/subscriptions/support/default.aspx.
    >
    > ==================================================
    >
    >
    >
    > This posting is provided "AS IS" with no warranties, and confers no
    > rights.
     
    Tim_Mac, Aug 23, 2006
    #5
  6. Hi Tim,

    Glad that the code is of assistance. However, since we are hacking into the
    internal script library of ASP.NET, such script code like
    "WebForm_DoPostbackWithOptions" is not guaranteed to work among multiple
    versions, this is what we need to take care.

    BTW, you are welcome to post here when you've finished the library so that
    other community members and also reference them :)

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead


    This posting is provided "AS IS" with no warranties, and confers no rights.
     
    Steven Cheng[MSFT], Aug 24, 2006
    #6
  7. Tim_Mac

    Tim_Mac Guest

    hi Steven,
    your approach got me thinking.... i tried to find an approach that wouldn't
    dependant on the WebForm_DoPostbackWithOptions function. I also didn't
    really like having a duplicate Fake button beside the real one, although i
    can see how it does solve some problems.
    what i came up is below, for anyone interested. comments/suggestions
    welcome. Tested in IE6 (win) and FireFox 1.5.0.6, with multiple buttons on
    forms, and tons of client-side validation. The previous version of this
    control had a problem in Firefox, if the user clicked back then the control
    stayed disabled, which was annoying, this isn't a problem with this new
    version.
    i don't think window.onbeforeunload is supported by Mac / Mozilla, but IE +
    FireFox is good enough coverage for me.

    /// <summary>
    /// A button control that disables itself when clicked.
    /// This is to prevent duplicate clicks by impatient or novice users.
    /// It requires the button to be placed in a server form.
    /// </summary>
    [DefaultProperty("Text"), ToolboxData("<{0}:SmartButton runat=server />")]
    public class SmartButton : Button
    {

    /// <summary>
    /// Use the OnClientClick event to set the __EVENTTARGET value to the
    button client ID.
    /// Attach an event to the window.onbeforeunload, to disable the button, so
    that it happens after
    /// successful client validation.
    /// </summary>
    protected override void Render(HtmlTextWriter output)
    {
    this.OnClientClick +=
    String.Format("document.getElementById('__EVENTTARGET').value = '{0}';",
    this.ClientID);

    this.Page.ClientScript.RegisterStartupScript(typeof(string),
    "SmartButton", @"
    <script language='javascript' type='text/javascript'>
    function DisableButton()
    {
    try{
    var target = document.getElementById('__EVENTTARGET').value;
    document.getElementById(target).disabled = true;
    }catch(e){}
    }
    window.onbeforeunload = DisableButton;
    </script>
    ", false);

    base.Render(output);
    }
    }

    in case anyone is wondering why i had to set the __EVENTTARGET manually,
    you'd be right in thinking that this should be done by the
    WebForm_DoPostbackWithOptions function, but it seems not to do it in time
    for the window.onbeforeunload event. i could have used any hidden field, or
    javascript variable, but i thought why not use the EVENTTARGET since that it
    is its purpose anyway.

    if anyone wants to know how to reference a compiled control like this, the
    easiest way in .Net 2.0 is to add this to your web.config:
    <system.web>
    <pages>
    <controls>
    <add tagPrefix="custom" namespace="NameSpaceOfControl"
    assembly="AssemblyContainingControl" />

    then in your aspx, just add a control like so: <custom:SmartButton etc
    />

    cheers.
    tim

    --------------------------
    blog: http://tim.mackey.ie
     
    Tim_Mac, Aug 24, 2006
    #7
  8. Thanks for the followup and sharing the update.

    I think the new idea is good. Actually I also feel a bit hesitate on the
    former solution since I am sure such function like
    WebForm_DoPostbackWithOptions is changable and not quite recommend to
    directly use in our custom code.

    I have tried your new approach and works good as long as the browser
    support the onbeforeunload event.

    Cheers,

    Steven Cheng

    Microsoft MSDN Online Support Lead



    This posting is provided "AS IS" with no warranties, and confers no rights.
     
    Steven Cheng[MSFT], Aug 24, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Colin Mackay
    Replies:
    0
    Views:
    2,710
    Colin Mackay
    Jun 25, 2003
  2. Matt
    Replies:
    14
    Views:
    4,166
    Chad Z. Hower aka Kudzu
    Jan 30, 2004
  3. Mythran
    Replies:
    2
    Views:
    534
    Mythran
    Jan 22, 2005
  4. =?Utf-8?B?dmlkeWE=?=
    Replies:
    1
    Views:
    770
    Kevin Spencer
    Jun 2, 2005
  5. Thor
    Replies:
    1
    Views:
    1,037
    Mikkel Heisterberg
    Jul 2, 2003
Loading...

Share This Page