Skip to content Skip to sidebar Skip to footer

UpdatePanel With Input Type Other Than Text In Html5

I am developing an open source project for rendering HTML5 using ASP.NET. Here you can take a look: http://asphtml5.codeplex.com/ now I have a problem with update panel in posting

Solution 1:

Interestingly enough, the ASP.NET 4.0 AJAX framework does seem to be aware of HTML 5 input types (see code), yet as @TimSchmelter pointed out, this is confirmed by Microsoft as a bug.

This may give you a starting point for debugging the behavior and/or overriding the default behavior and finding a solution.

It could also be an error on the server-side processing code for these input types, although I'm not sure why they should/would care about an async postback versus a normal postback.

this._textTypes = /^(text|password|hidden|search|tel|url|email|number|range|color|datetime|date|month|week|time|datetime-local)$/i;

function Sys$WebForms$PageRequestManager$_onFormSubmit(evt) {
        var i, l, continueSubmit = true,
            isCrossPost = this._isCrossPost;
        this._isCrossPost = false;
        if (this._onsubmit) {
            continueSubmit = this._onsubmit();
        }
        if (continueSubmit) {
            for (i = 0, l = this._onSubmitStatements.length; i < l; i++) {
                if (!this._onSubmitStatements[i]()) {
                    continueSubmit = false;
                    break;
                }
            }
        }
        if (!continueSubmit) {
            if (evt) {
                evt.preventDefault();
            }
            return;
        }
        var form = this._form;
        if (isCrossPost) {
            return;
        }
        if (this._activeDefaultButton && !this._activeDefaultButtonClicked) {
            this._onFormElementActive(this._activeDefaultButton, 0, 0);
        }
        if (!this._postBackSettings || !this._postBackSettings.async) {
            return;
        }
        var formBody = new Sys.StringBuilder(),
            count = form.elements.length,
            panelID = this._createPanelID(null, this._postBackSettings);
        formBody.append(panelID);
        for (i = 0; i < count; i++) {
            var element = form.elements[i];
            var name = element.name;
            if (typeof(name) === "undefined" || (name === null) || (name.length === 0) || (name === this._scriptManagerID)) {
                continue;
            }
            var tagName = element.tagName.toUpperCase();
            if (tagName === 'INPUT') {
                var type = element.type;
                if (this._textTypes.test(type)
                    || ((type === 'checkbox' || type === 'radio') && element.checked)) {
                    formBody.append(encodeURIComponent(name));
                    formBody.append('=');
                    formBody.append(encodeURIComponent(element.value));
                    formBody.append('&');
                }
            }
            else if (tagName === 'SELECT') {
                var optionCount = element.options.length;
                for (var j = 0; j < optionCount; j++) {
                    var option = element.options[j];
                    if (option.selected) {
                        formBody.append(encodeURIComponent(name));
                        formBody.append('=');
                        formBody.append(encodeURIComponent(option.value));
                        formBody.append('&');
                    }
                }
            }
            else if (tagName === 'TEXTAREA') {
                formBody.append(encodeURIComponent(name));
                formBody.append('=');
                formBody.append(encodeURIComponent(element.value));
                formBody.append('&');
            }
        }
        formBody.append("__ASYNCPOST=true&");
        if (this._additionalInput) {
            formBody.append(this._additionalInput);
            this._additionalInput = null;
        }

// truncated for length

Solution 2:

All right then, I figured out a way to fix that. First of all I found the problem with the code that Tim Medora provided. It all was the this. modifier's fault. So this JavaScript fixed the problem:

var _textTypes = /^(text|password|hidden|search|tel|url|email|number|range|color|datetime|date|month|week|time|datetime-local)$/i;
function Sys$WebForms$PageRequestManager$_onFormSubmit(evt) {
...
if (_textTypes.test(type) ||
       (((type === 'checkbox') || (type === 'radio')) && element.checked)) {
       formBody.append(encodeURIComponent(name));
       formBody.append('=');
       formBody.append(encodeURIComponent(element.value));
       formBody.append('&');
...
}

Now I had to inject my function into ScriptResource.axd. For now I found a way that seems to work:

I created a class ScriptResouceHandler that extends System.Web.Handlers.ScriptResourceHandler in namespace DotM.Html5.Handlers.

in its ProcessRequest I called base.ProcessRequest(context) to do its job. But I wanted to add my function to the one rendering original function. I found out that it was when the encrypted ZSystem.Web.Extensions,4.0.0.0,,31bf3856ad364e35|MicrosoftAjaxWebForms.debug.js| was passed.

Another problem was that in System.Web.Handlers.ScriptResourceHandler, 'Page.DecryptString' method which is internal is called to decrypt the query string param. so there was no way for me to invoke that method via reflection.

here is the code:

        protected sealed override void ProcessRequest(HttpContext context)
        {
            base.ProcessRequest(context);
            if (CypherContainsAjax(context.Request.QueryString["d"]))
                context.Response.Write(OnFormSubmit);
        }

        private bool CypherContainsAjax(string cypher)
        {
            var text = DecryptString(cypher);
            if (text == null)
                return true; //Then Add it everywhere. What else could I do? :D
            return text.Contains("MicrosoftAjaxWebForms");
        }

        private string DecryptString(string cypher)
        {
            if (PageDecryptString == null)
                return null;
            return (string)PageDecryptString.Invoke(null, new object[] { cypher });
        }
        private static MethodInfo PageDecryptString;
        static ScriptResourceHandler()
        {
            PageDecryptString = typeof(Page).GetMethod("DecryptString", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
        }

You may call this some kind of ugly hacking ...


Solution 3:

This was already fixed in .Net 4 Reliability Update 1 (there is also a version 2, but it does not contain the first one): http://support.microsoft.com/kb/2533523

But if you are using AjaxControlToolkit, it uses its own internal MicrosoftAjaxWebForms.js which is an older fork, and there is still no official fix for it - you can use mine solution from here: http://ajaxcontroltoolkit.codeplex.com/workitem/27041

So - you can either include the fixed ToolkitScriptManager with your project (a bloat, I know), or you can try to include the new version of MicrosoftAjaxWebForms.js by experimenting with vanilla ScriptManager properties AjaxFrameworkMode="Explicit", Scripts or CompositeScript.

Use the AjaxFrameworkMode property to enable all Microsoft Ajax script files, to disable all Microsoft Ajax script files, or to explicitly include individual script files.

The Scripts collection does not contain the core Microsoft Ajax Library scripts. The scripts in the core library are rendered automatically; they do not have to be registered with the ScriptManager control. However, if you want to override a core script or any control script and substitute a different version of the script, you can add your version to the Scripts collection.

<asp:ScriptManager runat="server">
  <Scripts>
    <asp:ScriptReference Path="~/MicrosoftAjaxWebForms.js" />
  </Scripts>
</asp:ScriptManager>

You can get the new version of MicrosoftAjaxWebForms.js from System.Web.Extensions assembly Resources (with .Net Reflector) on machines with installed Reliability Update 1.


Post a Comment for "UpdatePanel With Input Type Other Than Text In Html5"