Default Button Submissions in ASP.NET Pages
A couple of days ago David Cox pointed out a bug in my West Wind Web Store, where if the user submits the Item form by pressing Enter rather than clicking on the Add button, causes the form to fail.
The code for the Page_Load in this form looks something like this:
private void Page_Load(object sender, System.EventArgs e)
{
if (!this.IsPostBack)
this.DisplayItem();
}
{
...
with a btnSubmit handler routine below that is hooked up to the actual Submit button event. The handler among other things performs the task of re-displaying the item in case of failure or submitting the item to the shopping cart.
The code above works on the logic that any databinding and display of the item data only needs to happen during GET operations (ie, first access to the page) and any other operations on this page cause a submission of the form – IOW, the btnSubmit_Click() event would fire.
The code above works fine in most cases. If the user clicks the button – no problem. In most cases when the user just presses enter it also works as text fields on a form are implicitly self-submitting in HTML.
However, Internet Explorer is somewhat flakey in how it submits forms in this way. In this example, doing a trace reveals that the btnSubmit does not get POSTed when doing a submit from the TextBox. The same operation works fine in Firefox, which (correctly I think) submits the form with the single button in it.
There are several other forms in this application where Internet Explorer DOES submit the button. For example, on the OrderProfile.aspx page, users can press ENTER at any point and the form will sumit properly.
I've tried to understand what makes IE behave differently but I can't see any difference. Neither page has any special form submission or button code but one works the other doesn’t. Go figure.
The solution to the problem for the Item page of course is simple, IF YOU KNOW AND TEST FOR THIS SITUATION. And that’s a big if if the browser you’re testing with is sometimes working one way and sometimes another. The quick fix is:
private void Page_Load(object sender, System.EventArgs e)
{
if (!this.IsPostBack)
{
this.DisplayItem();
}
else
{
// *** Must handle case where user is 'auto-submitting'
// without clicking the button.
if ( Request.Form["btnSubmit"] == null )
this.btnSubmit_Click(this,EventArgs.Empty);
}
}
which basically forces the form submission to occur if for whatever reason the form submission button hasn’t been provided.
It might actually make sense to create a DefaultButton property on the form and point it at a handler, and then hook this up in the OnLoad() event of a custom form base class:
// *** In base Page class
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
if ( this.IsPostBack &&
this.DefaultButton != null &&
Request.Form[this.DefaultButton.ID] == null )
{
MethodInfo Meth = this.DefaultButton.GetType().GetMethod("OnClick",
BindingFlags.Instance | BindingFlags.NonPublic);
Meth.Invoke(this.DefaultButton,new object[1] { EventArgs.Empty });
}
}
Note that you have to use Reflection to make this happen since the OnClick() handler that fires the event is protected on the Button object. It actually took me a bit to figure out how to do this. I keep forgetting that you can’t access the Event directly by either calling the method or even as a Delegate like this:
DefaultButton.Click.Invoke(…)
In fact, I don’t know of a way to directly access the event in any way other than assignment (+=) or removal (-=) from client code. Hence the requirement for Reflection. The above also isn’t truly generic – it works on internal knowledge (and convention in the .NET framework) that there’s an OnClick() method that is responsible for firing the event. If there wasn’t such a ‘firing method’ handy, a lot more work would be needed to get the EventInfo object, retrieve the RaiseMethod() and then fire it on the Page object. Yuk…
It sure would be a lot nicer if we could somehow get a reference to the Delegate:
EventHander e = DefaultButton.Click as EventHandler;
e.Invoke(…);
But no such luck. Maybe somebody knows of an easier way to do this.
Anyway, the code above works reliably only if you have a single submit button. If you have more than one button submission on a form you’d need a slightly more elaborate scheme that checks all possible button submissions to make sure you don’t submit if another button was submitted. If you use a common naming scheme (like btn prefix) this is easy and you can modify the code above to check for any button that starts with the prefix in the Form[] collection.
Other Posts you might also like
- Adding minimal OWIN Identity Authentication to an Existing ASP.NET MVC Application
- Resolving Paths To Server Relative Paths in .NET Code
- Map Physical Paths with an HttpContext.MapPath() Extension Method in ASP.NET
- Back to Basics: Rewriting a URL in ASP.NET Core
- Getting the Client IP Address in ASP.NET Core
The Voices of Reason
# re: Default Button Submissions in ASP.NET Pages
1) Change the width to 0
2) Change the readonly property to true.
Worked for me!
Skip Lutz
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
Is this bug described on MSDN ?
Thank you for reply...
# re: Default Button Submissions in ASP.NET Pages
<input type="text" style="display:none" runat="server" />
For some reason I could not get the input type to take the width. And it also showed the button. So that would not work for me. But the above works like a champ.
Hope this helps
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
Your suggestion worked super well for me! Thank you very much!
The above I forgot to mention who I am thanking.
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
But this workaround works for me too. Thanks.
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
Page.RegisterHiddenField( "__EVENTTARGET", myButton.ClientID );
Where myButton is the button you want to be default.
This method will NOT work when you have <asp:Button> objects on the page. In many browser versions (see above) the Button’s will post automatically, and their name/value pair will override the pre-set __EVENTTARGET.
Also, certain controls will re-set the __EVENTTARGET to an empty string.
Thanks
# re: Default Button Submissions in ASP.NET Pages
onload=Form1.txtcity.focus() in <Body> tag to put focus on the text field just as the page loads.
Thanks
# re: Default Button Submissions in ASP.NET Pages
IE 6
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
To fix try this: <input name="hidden_fld" type="text" id="hidden_fld" border="0" style="width:0px;visibility:hidden;display:none;" />
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
the thing is to get the job done.
ZERO WIDTH thanks
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
I did not found a solution for this problem above... what to do?
# re: Default Button Submissions in ASP.NET Pages
Scott Guthrie post a great blog on this topic some time back here...
http://weblogs.asp.net/scottgu/archive/2005/08/04/421647.aspx
I have seem some discussion that in some instances ppl are having problems with the default button in that instance I would try something like this....
<asp:textbox id="t1" runat="server onkeypress="submitForm()" />
<script type="text/javascript"> function submitForm() { if (event.keyCode == 13) { event.cancelBubble = true; event.returnValue = false; theForm.t1.click(); } } </SCRIPT>
Hope this helps...
# re: Default Button Submissions in ASP.NET Pages
Thanks
# re: Default Button Submissions in ASP.NET Pages
# re: Default Button Submissions in ASP.NET Pages
Hears the code.
<form id="form1" runat="server" defaultbutton = "btnLookup" defaultfocus="txtCompany"> <td> <autoComplete:TextBox ID="txtCompany" Name="txtCompany" VarName="gCompanies" ErrorLabel="errorspan" AllowNonMatching="false" ErrorText="Company not covered" runat="server" DisableControl="ctl00_btnLookup" /> </td> <td> <asp:ImageButton ID="btnLookup" runat="server" CssClass="" EnableViewState="False" EnableTheming="false" OnClientClick="return gController.LookupCompany();" /> </td> <td> </form>
I want to call OnClientClick="return gController.LookupCompany();" on click of enter in textbox txtCompany. The above given code works properly in Firefox but not in IE7.
As suggestd i tried putting
<input name="hidden_fld" type="text" id="hidden_fld" border="0" style="width:0px;visibility:hidden;display:none;" />
in first td, but it did not work for me.
# re: Default Button Submissions in ASP.NET Pages
if (!IsPostBack)
{
//set the default button so that IE submits on hitting enter (for the Search)
this.Form.DefaultButton = btnSearch.UniqueID;
}
you can set the DefaultButton in the page declaratively but my Form sits in the MasterPage..
# re: Default Button Submissions in ASP.NET Pages
here is the code in VB.Net:
form1.DefaultButton = tbtn.ClientID
# re: Default Button Submissions in ASP.NET Pages
It seems that IE has a bug (which has been there since at least version 4.0 I believe) where it won't POST the button value if there is only *one* input field on the form (and you hit ENTER instead of clicking on the button). If there are two or more (non-button and non-hidden) input fields, the submit button does get POSTed. This only affects IE, not any other browsers I've tried.
It doesn't seem to matter how many buttons are on the form, but the number of other input fields. I had previously thought that including an extra hidden input field would 'fix' this issue, but even that doesn't seem to work in IE6 right now.