WebForms is not including email input type in form

2019-05-11 01:34发布

问题:

I have an asp:TextBox on a page:

<asp:TextBox ID="edEmail" runat="server" />

And the form is submitted with a normal <asp:Button> control:

<asp:TextBox ID="edEmail" runat="server" />
<asp:Button ID="bbOK" Text="Save User" runat="server" OnClick="bbOK_Click" />

These are rendered into the client as:

<input name="ctl00$MainContent$edEmail" id="ctl00_MainContent_edEmail"></input>
<input name="ctl00$MainContent$bbOK" id="ctl00_MainContent_bbOK"     
       type="submit" value="Save User"
       onclick='javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$MainContent$bbOK", "", true, "", "", false, false))' >

When the form is submitted through a regular <asp:Button> everything sends correctly. Reading html forms is painful, but the formatted request body is:

  • &ctl00%24MainContent%24edEmail = asdf%40here.net
  • &ctl00%24MainContent%24bbOK = Save+User

Excellent, the e-mail address is going to the server. Next we will change the type of the input box to the new html5 email type. We do this after installing the appropriate update to the .NET 4 Framework:

<asp:TextBox ID="edEmail" type="email" runat="server" />
<asp:Button ID="bbOK" Text="Save User" runat="server" OnClick="bbOK_Click" />

And now we repeat the same procedure. The rendered HTML is:

<input type="email" name="ctl00$MainContent$edEmail" id="ctl00_MainContent_edEmail" >
<input name="ctl00$MainContent$bbOK" id="ctl00_MainContent_bbOK"
       type="submit" value="Save User" 
       onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;ctl00$MainContent$bbOK&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" >

And when we submit the form, the e-mail address form input is present:

  • &ctl00%24MainContent%24edEmail = asdf%40here.net
  • &ctl00%24MainContent%24bbOK = Save+User

Excellent, the browser (both IE11 and Chrome 30-something) are submitting the contents of the form as expected.

Next we add something to the page that triggers an "auto-postback", an <asp:RadioGroup>:

<asp:TextBox ID="edEmail" type="email" runat="server" />

<asp:RadioButtonList ID="rbAccountType" runat="server" AutoPostBack="true" OnSelectedIndexChanged="rbAccountType_IndexChanged">
    <asp:ListItem>Windows</asp:ListItem>
    <asp:ListItem Selected="True">Local</asp:ListItem>
</asp:RadioButtonList>
<asp:Button ID="bbOK" Text="Save User" runat="server" OnClick="bbOK_Click" />

This gives the rendered HTML of:

<input type="email" name="ctl00$MainContent$edEmail" id="ctl00_MainContent_edEmail" >

<input id="ctl00_MainContent_rbAccountType_0" type="radio" name="ctl00$MainContent$rbAccountType" value="Windows" checked="checked"><label for="ctl00_MainContent_rbAccountType_0">Windows</label>
<input id="ctl00_MainContent_rbAccountType_1" type="radio" name="ctl00$MainContent$rbAccountType" value="Local" 
       onclick="javascript:setTimeout('__doPostBack(\'ctl00$MainContent$rbAccountType$1\',\'\')', 0)">    

<input name="ctl00$MainContent$bbOK" id="ctl00_MainContent_bbOK"
       type="submit" value="Save User" 
       onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;ctl00$MainContent$bbOK&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" >

But when this form "auto-postsback", the email field is missing:

  • &ctl00%24MainContent%24rbAccountType = Local&__ASYNCPOST=true&

If i change the email input's type from email to text:

<asp:TextBox ID="edEmail" runat="server" Type="text" />

the rendered radiobutton remains unaffected:

<input id="ctl00_MainContent_rbAccountType_1" type="radio" name="ctl00$MainContent$rbAccountType" value="Local" 
       onclick="javascript:setTimeout('__doPostBack(\'ctl00$MainContent$rbAccountType$1\',\'\')', 0)">

but the postback data now (correctly) contains exactly what it's supposed to:

  • &ctl00%24MainContent%24edUsername = ian
  • &ctl00%24MainContent%24edFullname = Ian%20Boyd
  • &ctl00%24MainContent%24edDescription = foo
  • &ctl00%24MainContent%24edEmail = asdf%40here.net
  • &ctl00%24MainContent%24rbAccountType = Local&__ASYNCPOST=true&

If i change it back to email:

<asp:TextBox ID="edEmail" runat="server" Type="email" />

it again fails, failing to include the email input type

  • &ctl00%24MainContent%24edUsername = ian
  • &ctl00%24MainContent%24edFullname = Ian%20Boyd
  • &ctl00%24MainContent%24edDescription = foo
  • &ctl00%24MainContent%24rbAccountType = Local&__ASYNCPOST=true&

tldr

WebForms is a buggy architecture that i should have stopped using five years ago There's no fix, and Microsoft won't, so i'm just looking for commiserating. doesn't support HTML 5.

What is WebForms doing that uses the browser to not submit all fields in a form? The failure happens in the IE and Chrome client.

Addendum

The title of this question calls out email input type. But the same bug happens for number input type; and presumably all html5 input types.

And marking up hyper-text in code:

protected void Page_Load(object sender, EventArgs e)
{
   edEmail.Attributes["type"] = "email";
   edEmployeeID.Attributes["type"] = "number";

   ...
}

does not solve it. The form still fails to submit its contained values during an "auto-postback" submit (and correctly submitting all values during a "regular" submit).

Impressive that 27 minutes after asking the question, Googling for:

asp.net autopostback not including html5 input types

only gives me as the person experiencing the problem. Apparently i'm the only person trying to shoe-horn HTML5 into WebForms.

回答1:

Found the bug in the generated WebForms client side Javascript code:

ScriptResource.axd

// Name:        MicrosoftAjaxWebForms.debug.js
// Assembly:    AjaxControlToolkit
// Version:     3.5.50401.0
// FileVersion: 3.5.50401
// (c) 2010 CodePlex Foundation
_onFormSubmit: function PageRequestManager$_onFormSubmit(evt)
{
   var count = form.elements.length;

   for (i = 0; i < count; i++) 
   {
       var element = form.elements[i];

       var tagName = element.tagName.toUpperCase();

       if (tagName === 'INPUT') 
       {
          var type = element.type;
          if ((type === 'text') ||
                (type === 'password') ||
                (type === 'hidden') ||
                (((type === 'checkbox') || (type === 'radio')) && element.checked)) 
          {
             formBody.append(encodeURIComponent(name));
             formBody.append('=');
             formBody.append(encodeURIComponent(element.value));
             formBody.append('&');
          }
       }
   }
}

By definition, WebForms will not input HTML5 input types in the form body during a postback. It will by definition only support the few original input types:

  • text
  • password
  • hidden
  • checkbox
  • radio
  • color unsupported
  • date unsupported
  • datetime unsupported
  • datetime-local unsupported
  • email unsupported
  • month unsupported
  • number unsupported
  • range unsupported
  • search unsupported
  • tel unsupported
  • time unsupported
  • url unsupported
  • week unsupported


回答2:

You supposedly need to leave your server control as an <asp:TextBox ... /> but override its type attribute in your code-behind:

edEmail.Attributes["type"] = "email";

[Source]