46 votes

L'option Post Back ne fonctionne pas après l'écriture de fichiers dans la réponse en ASP.NET

Ce que j'ai ?

J'ai une page ASP.NET qui permet à l'utilisateur de télécharger un fichier. a sur un clic de bouton. L'utilisateur peut sélectionner le fichier qu'il souhaite dans une liste de fichiers disponibles (RadioButtonList) et clique sur le bouton de téléchargement pour le télécharger. (Je ne dois pas fournir de lien pour chaque fichier qui peut être téléchargé - c'est l'exigence).

Qu'est-ce que je veux ?

Je veux que l'utilisateur puisse télécharger plusieurs fichiers un par un en sélectionnant le bouton radio requis et en cliquant sur le bouton.

Quel est le problème auquel je suis confronté ?

Je peux télécharger le fichier pour la première fois correctement. Mais, après le téléchargement, si je sélectionne un autre fichier et clique sur le bouton pour le télécharger, l'événement de clic du bouton ne revient pas et le deuxième fichier ne sera pas téléchargé.

J'utilise le code suivant sur l'événement de clic du bouton :

protected void btnDownload_Click(object sender, EventArgs e)
{
    string viewXml = exporter.Export();
    Response.Clear();
    Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
    Response.AddHeader("Content-Length", viewXml.Length.ToString());
    Response.ContentType = "text/plain";
    Response.Write(viewXml);
    Response.End();
}

Est-ce que je fais quelque chose de mal ici ?

Le même problème peut être reproduit dans IE6, IE7 et Chrome. Je pense que ce problème est indépendant du navigateur.

0 votes

Si vous êtes sur un formulaire (ou un contrôle) activé par Ajax, il se peut que le javascript Ajax soit mélangé ou bloqué car vous avez renvoyé un document différent au lieu de renvoyer ce que Javascript attendait (quelques informations sur l'état de la vue et le html mis à jour qui va dans le panneau de mise à jour). Voir aussi social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/

61voto

RobbZ Points 311

J'ai eu le même problème avec Sharepoint. J'ai un bouton sur la page qui envoie un fichier et après avoir cliqué sur le bouton, le reste du formulaire ne répondait plus. Il s'avère que c'est un truc de Sharepoint qui met la variable _spFormOnSubmitCalled à true pour empêcher toute autre soumission. Lorsque nous envoyons un fichier, cela ne rafraîchit pas la page, nous devons donc remettre manuellement cette variable à false.

Sur votre bouton dans le webpart, définissez le OnClientClick à une fonction dans votre javascript pour la page.

 <asp:Button ID="generateExcel" runat="server" Text="Export Excel" 
OnClick="generateExcel_Click" CssClass="rptSubmitButton"
OnClientClick="javascript:setFormSubmitToFalse()" />

Ensuite, dans le javascript, j'ai cette fonction.

function setFormSubmitToFalse() {
    setTimeout(function () { _spFormOnSubmitCalled = false; }, 3000);
    return true;
}

La pause de 3 secondes que j'ai trouvée était nécessaire parce que sinon, je définissais la variable avant que Sharepoint ne la définisse. De cette façon, je laisse sharepoint la définir normalement et je la remets à false juste après.

0 votes

Je connaissais cette information dans le passé, mais je l'avais complètement oubliée. Merci de m'avoir fait gagner des heures en me le rappelant.

0 votes

A fonctionné comme un charme pour mon problème de bibliothèque de documents Sharepoint > téléchargement de documents. Trois fois bravo ! !!

0 votes

Merci beaucoup, ça a marché. Mais est-ce maintenant une faille de sécurité permettant aux utilisateurs de soumettre à nouveau le formulaire après avoir cliqué sur le bouton ?

4voto

Randolpho Points 36512

A priori, ce que vous faites devrait fonctionner. J'ai réussi à faire quelque chose de similaire dans le passé, bien que j'aie utilisé un répéteur et des boutons LinkButtons.

La seule chose que je vois qui est différente est que vous utilisez Response.Write() plutôt que Response.OutputStream.Write() et que vous écrivez du texte plutôt que du binaire. ContentType que vous avez spécifié, il ne devrait pas y avoir de problème. De plus, j'appelle Response.ClearHeaders() avant d'envoyer des informations, et Response.Flush() par la suite (avant mon appel à Response.End() ).

Si cela peut vous aider, voici une version aseptisée de ce qui fonctionne bien pour moi :

// called by click handler after obtaining the correct MyFileInfo class.
private void DownloadFile(MyFileInfo file) 
{
    Response.Clear();
    Response.ClearHeaders();
    Response.ContentType = "application/file";
    Response.AddHeader("Content-Disposition", "attachment; filename=\"" + file.FileName + "\"");
    Response.AddHeader("Content-Length", file.FileSize.ToString());
    Response.OutputStream.Write(file.Bytes, 0, file.Bytes.Length);
    Response.Flush();
    Response.End();        
}

Vous pouvez envisager de transférer le fichier d'une manière binaire, peut-être en appelant System.Text.Encoding.ASCII.GetBytes(viewXml); et de transmettre le résultat de cette opération à Response.OutputStream.Write() .

Modifier légèrement votre code :

protected void btnDownload_Click(object sender, EventArgs e)
{
    string viewXml = exporter.Export();
    byte [] bytes = System.Text.Encoding.ASCII.GetBytes(viewXml); 
    // NOTE: you should use whatever encoding your XML file is set for.
    // Alternatives:
    // byte [] bytes = System.Text.Encoding.UTF7.GetBytes(viewXml);
    // byte [] bytes = System.Text.Encoding.UTF8.GetBytes(viewXml);

    Response.Clear();
    Response.ClearHeaders();
    Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
    Response.AddHeader("Content-Length", bytes.Length.ToString());
    Response.ContentType = "application/file";
    Response.OutputStream.Write(bytes, 0, bytes.Length);
    Response.Flush();
    Response.End();
}

0 votes

Merci, Randolpho. Pas de chance non plus avec le code modifié. Il se comporte de la même manière :(

0 votes

Hmm... eh bien, je suis perplexe. Comme je l'ai dit, ce que j'ai fonctionne bien. Est-il possible que ce soit quelque chose que vous faites dans votre code avant que le gestionnaire de clic soit appelé ? Si vous le pouvez, essayez de poster la page entière et le code-behind.

0 votes

El Response.ClearHeaders() semble être critique dans mon cas. Merci Randolpho.

4voto

Digitz Points 303

Un moyen simple de le faire sans supprimer Response.End est d'ajouter des js côté client pour faire le rafraîchissement de la page. Ajoutez le js à la propriété onclientclick de votre bouton.

par exemple

    onclientclick="timedRefresh(2000)"

then in your html..

    <script type="text/JavaScript">
    <!--
    function timedRefresh(timeoutPeriod) {
        setTimeout("location.reload(true);",timeoutPeriod);
    }
    //   -->

3voto

Josh Stodola Points 42410

Retirer Response.End() et laisser la réponse se terminer naturellement dans l'écosystème ASP.NET.

Si cela ne fonctionne pas, je recommanderais de placer le bouton dans un fichier séparé. <form> et envoyer les données requises à un gestionnaire HTTP distinct. Configurez le gestionnaire HTTP pour exporter le XML au lieu d'une page Web.

0 votes

Au départ, je n'avais pas inclus Response.End() . Il ne fonctionnait pas non plus à l'époque !

1 votes

Hmmm. Eh bien, peut-être que vous pouvez essayer de mettre le bouton dans un fichier séparé <form> et envoyer les données requises à un gestionnaire HTTP distinct qui est configuré pour exporter le XML ?

0 votes

De plus, vous devez spécifier un encodage de contenu tel que Response.ContentEncoding = Encoding.UTF8

3voto

AhsanRazaUK Points 11

J'ai eu le même problème. La fonction permettant d'exécuter une simple Response.Writer("") lors de l'événement "Button Click" sur la page aspx ne se déclenche jamais.

Méthode dans la classe :

public test_class()
{
    public test_class() { }

    public static void test_response_write(string test_string) 
    {
        HttpContext context = HttpContext.Current;
        context.Response.Clear();
        context.Response.Write(test_string);
        context.Response.End();                   
    }
}

Page ASPX :

protected void btn_test_Click(object sender, EventArgs e)
{
    test_class.test_response_write("testing....");
}

Pendant que j'essayais de trouver la raison, je viens d'appeler la même fonction sur Page_Load L'événement a fonctionné.

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        test_class.test_response_write("testing....");
    }
}

En enquêtant sur le problème, j'ai découvert que la page principale du corps de la page aspx était sous <asp:UpdatePanel> .

Je l'ai enlevé, et ça a marché sur Button_Click Événement. Je vous recommande de vérifier cela aussi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X