2011-12-27 17 views
10

Estoy desarrollando un proyecto de código abierto para renderizar HTML5 utilizando ASP.NET. Aquí puede echar un vistazo: http://asphtml5.codeplex.com/UpdatePanel con tipo de entrada que no sea texto en html5

ahora Tengo un problema con el panel de actualización al publicar los valores de entrada que tienen un tipo distinto de 'texto'. como sabrá, html 5 ha introducido varios tipos de entrada, por ejemplo, 'número', 'tel', 'búsqueda', etc. Ahora, si represento dichos controles, todo funciona bien en situaciones normales, pero si los pongo dentro de una UpdatePanel, no se devolverá ningún valor y se restablecerá el valor.

aquí es una pequeña pieza de código que produce el mismo error:

<asp:UpdatePanel runat="server" ID="UP"> 
     <ContentTemplate> 
      <p> 
       Enter A Number: 
       <asp:TextBox runat="server" ID="Number2" type="number" /> 
      </p> 
      <asp:Button Text="Submit" runat="server" ID="BtnSubmit" OnClick="BtnSubmit_Click" /> 
      <p> 
       You entered : 
       <asp:Label Text="" ID="LblValue" runat="server" /> 
      </p> 
     </ContentTemplate> 
    </asp:UpdatePanel> 

si se prueba este código en un navegador compatible con HTML 5, digamos Chrome como un ejemplo, el campo una numérico arriba-abajo se mostrará. pero si hace clic en el botón de enviar, perderá el valor que ha ingresado.

aquí es el código de controlador de eventos:

 protected void BtnSubmit_Click(object sender, EventArgs e) 
     { 
      LblValue.Text = Number2.Text; 
     } 

lo que ya he tratado está leyendo UpdatePanel, scriptmanager y ScriptManagerProxy códigos de clases, no se ha encontrado.

Creo que podría necesitar crear mis propias clases de UpdatePanel y/o ScriptManager para su uso.

¿Alguien podría ayudarme y decirme dónde revisarlo?

+0

creo que esto tiene aslo para hacer con las devoluciones de datos parciales. ¿Puedes crear un ScriptManager del lado del Cliente o del Servidor ...? – MethodMan

+1

Esto se solucionará en la próxima versión de ASP.NET: http://connect.microsoft.com/VisualStudio/feedback/details/651085/partial-postback-updatepanel-do-not-post-new-html5-input- fields-type-number –

+0

Gracias @Tim, pero ¿hay alguna manera de obtener el código fijo y liberarlo parcialmente? ¿O tienes alguna idea de lo que hicieron para solucionarlo? Creo que soy responsable de este problema siempre que publique controles HTML5. –

Respuesta

2

Bien, descubrí una manera de arreglar eso. Antes que nada, encontré el problema con el código provisto por Tim Medora. Todo fue culpa del modificador this.. Así que este JavaScript solucionó el problema:

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('&'); 
... 
} 

ahora tenía que inyectar mi función en ScriptResource.axd. Por ahora encontré una manera que parece funcionar:

Creé una clase ScriptResouceHandler que se extiende System.Web.Handlers.ScriptResourceHandler en el espacio de nombres DotM.Html5.Handlers.

en su ProcessRequest Llamé base.ProcessRequest(context) para hacer su trabajo. Pero quería agregar mi función a la que representa la función original. Descubrí que fue cuando pasó el ZSystem.Web.Extensions,4.0.0.0,,31bf3856ad364e35|MicrosoftAjaxWebForms.debug.js| encriptado.

Otro problema fue que en System.Web.Handlers.ScriptResourceHandler, se llama al método 'Page.DecryptString' que es interno para descifrar la cadena de consulta param. , así que no había forma de invocar ese método mediante la reflexión.

Aquí está el código:

 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); 
     } 

puede llamar a esto una especie de piratería fea ...

2

Curiosamente, el marco ASP.NET 4.0 AJAX parece ser consciente de los tipos de entrada HTML 5 (ver código), sin embargo, como @TimSchmelter señaló, esto es confirmado por Microsoft como un error.

Esto puede darle un punto de partida para depurar el comportamiento y/o anular el comportamiento predeterminado y encontrar una solución.

También podría ser un error en el código de procesamiento del lado del servidor para estos tipos de entrada, aunque no estoy seguro de por qué deberían preocuparse por una devolución de datos asincrónica en comparación con una devolución de datos normal.

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 
+0

Gracias Tim, estoy trabajando como sugirió ... –

+1

Y nuevamente lo suficientemente interesante, el código del lado del cliente que se representa en mi aplicación de prueba, no usa la expresión regular que proporcionó. Comprueba solo los tipos de 'texto', 'contraseña' y 'oculto'. y cuando agregué la entrada de mi número con la Consola de Chrome, funcionó bien. Ahora estoy buscando una forma de piratear esa función y espero que funcione. –

+0

@MaziarTaheri: ASP.NET podría estar enviando diferentes scripts a diferentes navegadores, pero usé Chrome para desplegar los scripts del lado del cliente que DID incluyen los diferentes tipos de texto. Creo que la mejor respuesta es anular la propiedad _textTypes en todos los casos. Si necesita ayuda para encontrar el código real, hágamelo saber. Creo que es solo la propiedad "pública" de un objeto JS. –

1

Esto ya se fijó en .Net 4 Fiabilidad Actualización 1 (también hay una versión 2 , pero que no contiene la primera): http://support.microsoft.com/kb/2533523

pero si está utilizando AjaxControlToolkit, utiliza sus propios MicrosoftAjaxWebForms.js interno que es un tenedor mayor, y todavía no hay una solución oficial para ello - se puede utilizar la solución minera desde aquí: http://ajaxcontroltoolkit.codeplex.com/workitem/27041

Por lo tanto - Puede incluir la ToolkitScriptManager fijo con su proyecto (una hinchazón, lo sé), o se puede tratar de incluir la nueva versión de MicrosoftAjaxWebForms.js mediante la experimentación con propiedades de vainilla scriptmanager AjaxFrameworkMode = "explícita", Scripts o 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> 

Usted puede obtener la nueva versión de MicrosoftAjaxWebForms.js de Recursos de montaje System.Web.Extensions (con reflector .Net) instalado en máquinas con fiabilidad actualización 1.

Cuestiones relacionadas