web-dev-qa-db-fra.com

IE10 envoyant des coordonnées de clic de bouton d'image avec des décimales (valeurs à virgule flottante) provoquant une exception ParseInt32 FormatException

Il semble qu'ASP.NET 4.0 ne soit pas préparé pour gérer les événements ImageButton déclenchés par Internet Explorer 10. Le problème est qu'IE10 envoie les coordonnées de clic de l'image sous forme de valeurs doubles (avec décimales) et ASP.NET essaie de les analyser sous forme d'entiers, présentant le type d'erreur suivant:

System.Web.HttpUnhandledException (0x80004005): 
   Exception of type 'System.Web.HttpUnhandledException' was thrown. 
   ---> System.FormatException: Input string was not in a correct format.

   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Web.UI.WebControls.ImageButton.LoadPostData(String postDataKey, NameValueCollection postCollection)
   at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.HandleError(Exception e)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at ASP.members_addtocartlogin_twostep_aspx.ProcessRequest(HttpContext context) in c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\932deaba\63ff7eeb\App_Web_MyPage.aspx.28424a96.oraym_un.0.cs:line 0
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Sur Google, certaines personnes suggèrent de forcer IE10 à s'exécuter dans la vue de compatibilité. Cependant, l'ajout de la balise meta <meta http-equiv="X-UA-Compatible" content="IE=10" /> ne résout rien; et en ajoutant <?xml version="1.0" encoding="UTF-8"> avant <!DOCTYPE> ne fonctionne pas non plus.

Des solutions? Puis-je capturer l'événement de clic avec Javascript et supprimer les décimales d'une manière ou d'une autre?

Remarque: La mise à niveau vers Framework 4.5 et la recompilation corrige le bogue. Pas besoin de changer la version d'exécution, car c'est toujours 4.0.

26
Diego

Une simple installation de .NET Framework 4.5 peut résoudre ce problème.

Cela peut résoudre le problème même si vous ne basculez pas votre pool d'applications vers .NET Framework 4.5.

Dans mon cas, j'ai quitté les pools d'applications sur .NET Framework 3.5. Apparemment, l'installation de .NET Framework 4.5 écrase certains fichiers pour d'autres versions de framework.

Puisqu'il est si facile d'installer la nouvelle version de .NET Framework, cela vaut probablement la peine d'essayer avant de se soucier des correctifs (qui ne fonctionnaient pas pour moi) ou d'autres solutions.

Voir la section des solutions de contournement ici

9
Brian Webster

Il existe des correctifs pour .NET CLR 2.0 et 4.0, comme décrit dans cette entrée de blog de Scott Hanselmann :

Les correctifs mettent à jour les fichiers ie.browser et firefox.browser dans \Windows\Microsoft.NET\Framework\<version>\Config\Browsers avec de nouvelles versions évolutives de ces définitions de navigateur. Rien d'autre n'est affecté.

.NET 4

.NET 2.0

Alternativement, il existe un correctif javascript basé sur le client (initialement publié comme solution de contournement sur le Élément de connexion avec l'ID de bogue: 755419 ):

$(function () {
    // Patch fractional .x, .y form parameters for IE10.
    if (typeof (Sys) !== 'undefined' && Sys.Browser.agent === Sys.Browser.InternetExplorer && Sys.Browser.version === 10) {
        Sys.WebForms.PageRequestManager.getInstance()._onFormElementActive = function Sys$WebForms$PageRequestManager$_onFormElementActive(element, offsetX, offsetY) {
            if (element.disabled) {
                return;
            }
            this._activeElement = element;
            this._postBackSettings = this._getPostBackSettings(element, element.name);
            if (element.name) {
                var tagName = element.tagName.toUpperCase();
                if (tagName === 'INPUT') {
                    var type = element.type;
                    if (type === 'submit') {
                        this._additionalInput = encodeURIComponent(element.name) + '=' + encodeURIComponent(element.value);
                    }
                    else if (type === 'image') {
                        this._additionalInput = encodeURIComponent(element.name) + '.x=' + Math.floor(offsetX) + '&' + encodeURIComponent(element.name) + '.y=' + Math.floor(offsetY);
                    }
                }
                else if ((tagName === 'BUTTON') && (element.name.length !== 0) && (element.type === 'submit')) {
                    this._additionalInput = encodeURIComponent(element.name) + '=' + encodeURIComponent(element.value);
                }
            }
        };
    }
});
22
ENOTTY

Voici une solution de contournement JavaScript. Il remplace la méthode existante, fixe les coordonnées x et y puis appelle la méthode existante avec ces nouvelles coordonnées.

Sys.WebForms.PageRequestManager.getInstance()._origOnFormActiveElement = Sys.WebForms.PageRequestManager.getInstance()._onFormElementActive;
Sys.WebForms.PageRequestManager.getInstance()._onFormElementActive = function(element, offsetX, offsetY){
    if (element.tagName.toUpperCase() === 'INPUT' && element.type === 'image'){
        offsetX = Math.floor(offsetX);
        offsetY = Math.floor(offsetY);
    }
    this._origOnFormActiveElement(element, offsetX, offsetY);
};
6
graham mendick

Comme indiqué dans autre réponse , ce problème a été corrigé dans .NET 4.5.

Pour ceux qui ne peuvent pas mettre à niveau vers .NET 4.5, Microsoft a publié une mise à jour pour résoudre ce problème pour .NET 4.0 ( KB2836939 ) et .NET 3.5 ( KB2836942 et - KB283694 ).

Voici comment ces articles de la base de connaissances décrivent le problème:

Lorsque vous cliquez sur un contrôle ImageButton qui se trouve dans un panneau de mise à jour sur une page Web ASP.NET à l'aide d'Internet Explorer 10 et versions ultérieures, l'opération de publication partielle échoue. En outre, l'événement de clic côté serveur n'est pas déclenché.

Pour référence, voici l'original ImageButton.LoadPostData code qui renvoie FormatException:

protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) {
    string name = UniqueID;
    string postX = postCollection[name + ".x"];
    string postY = postCollection[name + ".y"];
    if (postX != null && postY != null && postX.Length > 0 && postY.Length > 0) {
        x = Int32.Parse(postX, CultureInfo.InvariantCulture);
        y = Int32.Parse(postY, CultureInfo.InvariantCulture);
        if (Page != null) {
            Page.RegisterRequiresRaiseEvent(this);
        }
    }
    return false;
}

Et voici le code fixe:

protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) { 
    string name = UniqueID;
    string postX = postCollection[name + ".x"];
    string postY = postCollection[name + ".y"];
    if (postX != null && postY != null && postX.Length > 0 && postY.Length > 0) {
        x = (int)ReadPositionFromPost(postX);
        y = (int)ReadPositionFromPost(postY);
        if (Page != null) {
            Page.RegisterRequiresRaiseEvent(this);
        }
    }
    return false;
}

internal static double ReadPositionFromPost(string requestValue) {
    NumberStyles style = NumberStyles.AllowDecimalPoint | NumberStyles.Integer;
    return double.Parse(requestValue, style, CultureInfo.InvariantCulture);
}
3
Michael Liu

Il suffit de mettre ceci dans l'en-tête de chaque page ou la page maître:

<meta http-equiv="X-UA-Compatible" content="IE=9" />

Cela forcera IE10 en mode document standard IE9, et il pourra très bien gérer les publications d'image.

0
dougczar

Dans notre cas, sur la page principale, nous avons ajouté la ligne de code ci-dessous sous <head> section:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9">

Cela a fonctionné pour nous car il permet de rendre la page dans la version de IE qui est spécifiée.

0
Bat_Programmer

Si vous appuyez sur F12 et passez à IE9 manuellement, cela fonctionne comme un charme. Notre approche était donc d'utiliser content = "IE = 9" mais cela ne fait que basculer le mode document dans IE10 et non le mode navigateur et cela ne semble pas suffisant.

Peut-être que quelqu'un a une idée sur la façon de changer le mode document aussi?

Une autre solution de contournement qui devient de plus en plus populaire consiste à remplacer LoadPostData, voir

http://www.codeproject.com/Tips/496162/IE10-and-ImageButtons?display=Mobilehttp://forums.asp.net/t/1823287.aspx/ 2/1

Personnellement, j'aurais trouvé le contenu = "IE = 9" la meilleure solution en raison du peu de travail et d'impact supplémentaires.

0
timmkrause

J'ai fini par sous-classer l'ImageButton et à corriger les données avant qu'elles ne soient transmises au traitement.

using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;

namespace Xception.WebControls
{
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal),
    AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
    DefaultEvent("Click"),
    ToolboxData("<{0}:ImageButton runat=\"server\"> </{0}:ImageButton>")]
    public class ImageButton : System.Web.UI.WebControls.ImageButton
    {
        protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
        {
            NameValueCollection newCollection = new NameValueCollection();

            foreach (string key in postCollection.AllKeys)
            {
                if (key.Equals(this.UniqueID + ".x", StringComparison.InvariantCultureIgnoreCase))
                    newCollection[this.UniqueID + ".x"] = Convert.ToInt32(Convert.ToSingle(postCollection[this.UniqueID + ".x"])).ToString();
                else if (key.Equals(this.UniqueID + ".y", StringComparison.InvariantCultureIgnoreCase))
                    newCollection[this.UniqueID + ".y"] = Convert.ToInt32(Convert.ToSingle(postCollection[this.UniqueID + ".y"])).ToString();
                else
                    newCollection[key] = postCollection[key];
            }

            return base.LoadPostData(postDataKey, newCollection);
        }
    }
}
0
Dean Cleaver

En fait, c'est un problème différent de ceux répertoriés par tkrause. Un correctif est disponible, bien que je ne sache pas comment l'appliquer. Voici des informations pour ceux qui savent comment les appliquer:

http://support.Microsoft.com/kb/2784147

Si vous vérifiez que la section ASP.NET contient l'erreur exacte indiquée dans cette question. C'est exactement l'erreur et le problème que j'ai également.

Je pense que je ne peux pas obtenir la mise à jour car j'utilise Server 2003. J'utilise ASP.NET 3.5 et VS 2008, donc la mise à niveau vers 4.x n'est pas une option facile pour moi.

0
eselk

Dans mon cas, je ne suis actuellement pas en mesure de mettre à niveau .Net vers 4.5 et je ne voulais pas utiliser JavaScript pour corriger le bogue.

La solution que j'ai choisie était de convertir mon ImageButton en LinkButton:

C'était mon ImageButton:

<asp:ImageButton ID="MyButton" runat="server" CausesValidation="false" ToolTip="my tooltip" ImageUrl="../Images/button.gif" OnClick="MyButton_Click" ></asp:ImageButton>

Voici le LinkButton avec lequel je l'ai remplacé:

<asp:LinkButton ID="MyButton" runat="server" CausesValidation="false" OnClick="MyButton_Click">
    <asp:Image runat="server" ImageUrl="~/Images/button.gif" alt="my tooltip"/>
</asp:LinkButton>

Du point de vue de l'utilisateur, tout fonctionne de la même manière qu'avant ... mais sans se bloquer dans IE.

0
mezoid