ASP.Net validation summary causes page to jump to top

I have a simple form with a few required field validators and a validation summary control. When I submit the form, the client validation will cause the form to jump to the top of the page. If i remove the validation summary, the page does not move.

Heres a quick example:

<asp:TextBox ID="test" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="testrequired" runat="server" ControlToValidate="test">*</asp:RequiredFieldValidator>
<asp:ValidationSummary ID="summary" runat="server" />
<asp:Button ID="submit" runat="server" Text="submit" />

I've tried setting SetFocusOnError="true" in the required field validator and MaintainScrollPositionOnPostback="true" for giggles - even though this isn't a postback - without any luck. Is there a known solution for this problem?

EDIT:

I've found the problem in the js generated by WebResource.axd. Seems to come down to a single line in the ValidationSummaryOnSubmit() function.

line 534: window.scrollTo(0,0);

Any ideas on how to remove or bypass this?

EDIT2:

Quick work around for the time being:

  • set EnableClientScript="false" for all validation controls (disabling client validation)
  • set MaintainScrollPositionOnPostback="true" in Page directive

Still hoping for a client side solution...

EDIT3:

It seems a better work around is to just override the window.scrollTo() function so that it does nothing when called by the validation script:

<script type="text/javascript">
    window.scrollTo = function() { }
</script>

Adding the above anywhere on the page leaves the client validation in tact, but disables the window.scrollTo() method throughout the page


Two possible work arounds:

Disable client validation and jump to correct position on post back:

* set EnableClientScript="false" for all validation controls (disabling client validation)
* set MaintainScrollPositionOnPostback="true" in Page directive

Disable the scrollTo function in javascript:

<script type="text/javascript">
    window.scrollTo = function() { }
</script>

This is a known bug, as documented on Microsoft Connect. The relevant issue has the basis for the best work around:

var ValidationSummaryOnSubmitOrig = ValidationSummaryOnSubmit;
var ValidationSummaryOnSubmit = function() {
    var scrollToOrig = window.scrollTo;
    window.scrollTo = function() { };
    var retVal = ValidationSummaryOnSubmitOrig();
    window.scrollTo = scrollToOrig;
    return retVal;
}

Instead of

<script type="text/javascript">
    window.scrollTo = function() { return true; }
</script>

which would indiscriminately override the ScrollTo function for all postbacks, I put the function in my OnClientClick event of the button. As below.

onClientClick="window.scrollTo = function(x,y) { return true; };"

Not sure if it's the best solution, but it seems to have done the job for me.


As stated by cleek's answer, this is a known bug having workarounds.

Here is bdukes one, which looks to me as the best currently available.

(function () {
  var originalValidationSummaryOnSubmit = window.ValidationSummaryOnSubmit;
  window.ValidationSummaryOnSubmit = function (validationGroup) {
    var originalScrollTo = window.scrollTo;
    window.scrollTo = function() { };
    originalValidationSummaryOnSubmit(validationGroup);
    window.scrollTo = originalScrollTo;
  }
}());

(He has not posted it directly here on SO, and now the connect issue seems to require registration for being seen, which renders his workaround harder to access.)


I use this: (requires jquery and jquery.scrollTo)

First you put an anchor with a specific class above your validation summary, like so:

<a class="custom_valsum_anchor" />
<asp:ValidationSummary ID="valSum" runat="server" EnableClientScript="true" />

then include this bit of javascript:

$(document).ready(
        function () {
            var $valSum = $(".custom_valsum_anchor");
            if ($valSum.size() > 0) {
                var backup_ValidationSummaryOnSubmit = ValidationSummaryOnSubmit;
                ValidationSummaryOnSubmit = function (validationGroup) {
                    var backup_ScrollTo = window.scrollTo;
                    window.scrollTo = function () { };
                    backup_ValidationSummaryOnSubmit(validationGroup);
                    window.scrollTo = backup_ScrollTo;
                    setTimeout(function () { $("body").scrollTo($valSum); }, 1);
                };
            }
        }

);

Basicaly, it replaces, when necessary, the ValidationSummaryOnSubmit function with a version that temporarily disables window.scrollTo and scrolls to the anchor. It should not be to hard to modify so that it does not use jquery.