Question

Nous avons l'obligation de prendre une forme de soumission et d'enregistrer certaines données, puis de rediriger l'utilisateur vers une page hors site, mais dans la redirection, nous avons besoin de le "soumettre" une forme de POST, pas.

J'espérais qu'il y a un moyen facile de ce faire, mais je commence à penser que il n'y en a pas.Je pense que je dois maintenant créer une autre page, avec juste la forme que je veux, rediriger vers elle, remplir le formulaire de variables, puis faire un corps.onload appel à un script qui appelle simplement le document.forms[0].submit();

Quelqu'un peut me dire si il y a une alternative?Nous pourrions avoir besoin d'ajuster cette plus tard dans le projet, et il peut être sorte de compliqué, donc si il a été facile que nous pourrions le faire tous les non-autres page dépendante, ce serait merveilleux.

De toute façon, merci pour tout et à toutes les réponses.

Était-ce utile?

La solution

Ce faisant, il faut comprendre comment les redirections HTTP travail.Lorsque vous utilisez Response.Redirect(), permet d'envoyer une réponse (pour le navigateur qui fait la demande) Le Code d'État HTTP 302, qui indique au navigateur où aller.Par définition, le navigateur va faire que par l'intermédiaire d'un GET la demande, même si la demande originale a été un POST.

Une autre option est d'utiliser Le Code d'État HTTP 307, qui précise que le navigateur doit faire la demande de redirection de la même façon que l'original de la demande, mais pour demander à l'utilisateur un avertissement de sécurité.Pour ce faire, vous devez écrire quelque chose comme ceci:

public void PageLoad(object sender, EventArgs e)
{
    // Process the post on your side   

    Response.Status = "307 Temporary Redirect";
    Response.AddHeader("Location", "http://example.com/page/to/post.to");
}

Malheureusement, cela ne fonctionne pas toujours. Les différents navigateurs procéder différemment, car il n'est pas un code d'état.

Hélas, à la différence de l'Opéra et des développeurs de FireFox, IE les développeurs n'ont jamais lu la spec, et même la dernière, la plus sécurisée IE7 va rediriger la requête POST de domaine A domaine B, sans que les avertissements ou les boîtes de dialogue de confirmation!Safari agit également de façon intéressante, bien qu'elle ne suscite pas une boîte de dialogue de confirmation et effectue la redirection, il jette les données POST, effectivement changer 307 rediriger dans le plus commun 302.

Donc, autant que je sache, la seule façon de mettre en œuvre quelque chose qui serait à l'utilisation de Javascript.Il y a deux options que je peux penser à du haut de ma tête:

  1. Créer le formulaire et ses action l'attribut pointer vers le serveur tiers.Ensuite, ajoutez un événement click pour le bouton submit qui exécute pour la première fois une requête AJAX à votre serveur avec les données, et permet ensuite le formulaire pour être soumis au serveur tiers.
  2. Créer le formulaire à poster sur votre serveur.Lorsque le formulaire est soumis, montrer à l'utilisateur une page qui contient un formulaire avec toutes les données que vous souhaitez passer, toutes cachées dans les entrées.Juste afficher un message du genre "Redirection...".Ensuite, ajoutez un événement javascript de la page qui envoie le formulaire au serveur tiers.

De deux, je choisirais la deuxième, pour deux raisons.Tout d'abord, il est plus fiable que la première parce que le Javascript n'est pas nécessaire pour qu'il fonctionne;pour ceux qui ne l'ont pas activé, vous pouvez toujours vous rendre sur le bouton soumettre pour la forme cachée visible, et de lui demander de presse si cela prend plus de 5 secondes.Ensuite, vous pouvez décider quelles données est transmis au serveur tiers;si vous utilisez seulement le processus de la forme qu'il se passe, vous serez en passant le long de toutes les données post, qui n'est pas toujours ce que vous voulez.De même pour la 307 solution, en supposant qu'il a travaillé pour tous vos utilisateurs.

Espérons que cette aide!

Autres conseils

Vous pouvez utiliser cette approche:

Response.Clear();

StringBuilder sb = new StringBuilder();
sb.Append("<html>");
sb.AppendFormat(@"<body onload='document.forms[""form""].submit()'>");
sb.AppendFormat("<form name='form' action='{0}' method='post'>",postbackUrl);
sb.AppendFormat("<input type='hidden' name='id' value='{0}'>", id);
// Other params go here
sb.Append("</form>");
sb.Append("</body>");
sb.Append("</html>");

Response.Write(sb.ToString());

Response.End();

Comme résultat une fois que le client pourra obtenir tous html à partir du serveur de l'événement onload prendre place qui déclenche soumettre le formulaire et de valider toutes les données définies postbackUrl.

HttpWebRequest est utilisé pour cela.

Sur la publication, créer un HttpWebRequest à votre troisième partie et après les données du formulaire, puis une fois que c'est fait, vous pouvez la Réponse.Rediriger où vous le souhaitez.

Vous obtenez l'avantage supplémentaire que vous n'avez pas de nom de toutes vos commandes de serveur pour faire de la 3e parties du formulaire, vous pouvez le faire de la traduction lors de la construction de la POST-chaîne.

string url = "3rd Party Url";

StringBuilder postData = new StringBuilder();

postData.Append("first_name=" + HttpUtility.UrlEncode(txtFirstName.Text) + "&");
postData.Append("last_name=" + HttpUtility.UrlEncode(txtLastName.Text));

//ETC for all Form Elements

// Now to Send Data.
StreamWriter writer = null;

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";                        
request.ContentLength = postData.ToString().Length;
try
{
    writer = new StreamWriter(request.GetRequestStream());
    writer.Write(postData.ToString());
}
finally
{
    if (writer != null)
        writer.Close();
}

Response.Redirect("NewPage");

Toutefois, si vous avez besoin de l'utilisateur pour voir la page de réponse à partir de ce formulaire, votre seule option est d'utiliser le Serveur.De transfert, et qui peuvent ou peuvent ne pas fonctionner.

Cela devrait rendre la vie beaucoup plus facile.Vous pouvez simplement utiliser la Réponse.RedirectWithData(...) la méthode dans votre application web facilement.

Imports System.Web
Imports System.Runtime.CompilerServices

Module WebExtensions

    <Extension()> _
    Public Sub RedirectWithData(ByRef aThis As HttpResponse, ByVal aDestination As String, _
                                ByVal aData As NameValueCollection)
        aThis.Clear()
        Dim sb As StringBuilder = New StringBuilder()

        sb.Append("<html>")
        sb.AppendFormat("<body onload='document.forms[""form""].submit()'>")
        sb.AppendFormat("<form name='form' action='{0}' method='post'>", aDestination)

        For Each key As String In aData
            sb.AppendFormat("<input type='hidden' name='{0}' value='{1}' />", key, aData(key))
        Next

        sb.Append("</form>")
        sb.Append("</body>")
        sb.Append("</html>")

        aThis.Write(sb.ToString())

        aThis.End()
    End Sub

End Module

Quelque chose de nouveau dans ASP.Net 3.5 est-ce que "PostBackUrl" propriété de l'ASP boutons.Vous pouvez définir l'adresse de la page que vous souhaitez poster directement, et lorsque ce bouton est cliqué, au lieu de publier à la même page comme d'habitude, plutôt que de postes à la page que vous avez indiqué.À portée de main.Assurez-vous UseSubmitBehavior est également définie sur TRUE.

Pensé qu'il serait intéressant de partager cette heroku fait avec elle SSO pour Ajouter-sur les fournisseurs de

Un exemple de comment cela fonctionne peuvent être vus dans la source de la "kensa" de l'outil:

https://github.com/heroku/kensa/blob/d4a56d50dcbebc2d26a4950081acda988937ee10/lib/heroku/kensa/post_proxy.rb

Et peut être vu dans la pratique, si vous mettez de javascript.Exemple de source de la page:

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Heroku Add-ons SSO</title>
  </head>

  <body>
    <form method="POST" action="https://XXXXXXXX/sso/login">

        <input type="hidden" name="email" value="XXXXXXXX" />

        <input type="hidden" name="app" value="XXXXXXXXXX" />

        <input type="hidden" name="id" value="XXXXXXXX" />

        <input type="hidden" name="timestamp" value="1382728968" />

        <input type="hidden" name="token" value="XXXXXXX" />

        <input type="hidden" name="nav-data" value="XXXXXXXXX" />

    </form>

    <script type="text/javascript">
      document.forms[0].submit();
    </script>
  </body>
</html>

PostbackUrl peut être mis sur votre asp bouton poster sur une autre page.

si vous avez besoin de le faire dans le code-behind, essayez de Serveur.De transfert.

@Matt,

Vous pouvez toujours utiliser la HttpWebRequest, puis orienter la réponse que vous recevez de la réelle outputstream réponse, ce serait la réponse à l'utilisateur.Le seul problème est que toutes les url relatives serait rompu.

Encore, cela peut fonctionner.

Voici ce que je ferais :

Mettre les données dans un formulaire standard (sans runat="server" attribut) et de définir l'action de la forme de poster à la cible en dehors de la page du site.Avant de soumettre je voudrais soumettre les données de mon serveur à l'aide d'un XmlHttpRequest et d'analyser la réponse.Si la réponse signifie que vous devriez aller de l'avant avec le hors site, de Poster alors j' (JavaScript), de procéder avec le post sinon, je voudrais rediriger vers une page sur mon site

En PHP, vous pouvez envoyer des données POST avec cURL.Est-il quelque chose de comparable pour .NET?

Oui, HttpWebRequest, voir mon post ci-dessous.

L'OBTENIR (et la TÊTE) de la méthode ne devrait jamais être utilisé pour faire de tout ce qui a des effets secondaires.Un effet secondaire peut être la mise à jour de l'état d'une application web, ou il peut être recharge de votre carte de crédit.Si une action a des effets secondaires d'une autre méthode POST () doit être utilisé à la place.

Ainsi, un utilisateur (ou un navigateur) ne devraient pas être tenus responsables pour quelque chose fait par un GET.Si certains nuisibles ou cher effet secondaire est due à une, ce serait la faute de l'application web, pas l'utilisateur.Selon la spécification, un agent utilisateur ne doit pas suivre automatiquement une redirection, sauf si elle est une réponse à une requête GET ou HEAD.

Bien sûr, beaucoup de demandes ont quelques effets secondaires, même si c'est juste l'ajout à un fichier journal.La chose importante est que l'application, pas l'utilisateur, doit être tenue pour responsable de ces effets.

Les sections pertinentes de la spécification HTTP sont 9.1.1 et 9.1.2, et 10.3.

Je suggère la construction d'un HttpWebRequest de programmation pour l'exécution de votre POST, et ensuite rediriger après la lecture de la Réponse, le cas échéant.

Copier-pasteable code sur la base de Pavlo la méthode de Neyman

RedirectPost(string url, T bodyPayload) et GetPostData() sont pour ceux qui veulent juste dump certaines données fortement typées dans le source de la page et ensuite le récupérer dans la cible de l'un.Les données doivent être serializeable par NewtonSoft Json.NET et vous avez besoin de faire référence à la bibliothèque de cours.

Il suffit de copier-coller dans votre page(s) ou, mieux encore, de la classe de base pour vos pages et de les utiliser n'importe où dans votre application.

Mon coeur va à vous tous qui ont encore à utiliser des Formulaires Web en 2019, pour quelque raison que ce soit.

        protected void RedirectPost(string url, IEnumerable<KeyValuePair<string,string>> fields)
        {
            Response.Clear();

            const string template =
@"<html>
<body onload='document.forms[""form""].submit()'>
<form name='form' action='{0}' method='post'>
{1}
</form>
</body>
</html>";

            var fieldsSection = string.Join(
                    Environment.NewLine,
                    fields.Select(x => $"<input type='hidden' name='{HttpUtility.UrlEncode(x.Key)}' value='{HttpUtility.UrlEncode(x.Value)}'>")
                );

            var html = string.Format(template, HttpUtility.UrlEncode(url), fieldsSection);

            Response.Write(html);

            Response.End();
        }

        private const string JsonDataFieldName = "_jsonData";

        protected void RedirectPost<T>(string url, T bodyPayload)
        {
            var json = JsonConvert.SerializeObject(bodyPayload, Formatting.Indented);
            //explicit type declaration to prevent recursion
            IEnumerable<KeyValuePair<string, string>> postFields = new List<KeyValuePair<string, string>>()
                {new KeyValuePair<string, string>(JsonDataFieldName, json)};

            RedirectPost(url, postFields);

        }

        protected T GetPostData<T>() where T: class 
        {
            var urlEncodedFieldData = Request.Params[JsonDataFieldName];
            if (string.IsNullOrEmpty(urlEncodedFieldData))
            {
                return null;// default(T);
            }

            var fieldData = HttpUtility.UrlDecode(urlEncodedFieldData);

            var result = JsonConvert.DeserializeObject<T>(fieldData);
            return result;
        }

Généralement, tout ce dont vous aurez besoin est d'avoir un état entre ces deux demandes.Il y a effectivement une très funky façon de le faire qui ne repose pas sur du JavaScript (pense <noscript />).

Set-Cookie: name=value; Max-Age=120; Path=/redirect.html

Avec ce cookie, vous pouvez dans la demande suivante à /redirect.html récupérer le nom=valeur d'infos, vous pouvez stocker tout type d'information dans cette paire nom/valeur chaîne, jusqu'à dire 4K de données (typique cookie limite).Bien sûr, vous devriez éviter cela et de stocker des codes d'état et drapeau bits à la place.

Lors de la réception de cette requête, vous en retour répondre à une demande de supprimer ce code d'état.

Set-Cookie: name=value; Max-Age=0; Path=/redirect.html

Mon HTTP est un peu rouillé, j'ai été en passant par RFC2109 et RFC2965 de comprendre comment fiable c'est vraiment de préférence, je voudrais que le cookie aller-retour exactement une fois, mais qui ne semble pas être possible, aussi, les cookies tiers pourrait être un problème pour vous si vous êtes de déménager à un autre domaine.C'est encore possible, mais pas aussi facile que lorsque vous êtes en train de faire des choses au sein de votre propre nom de domaine.

Le problème ici, c'est la simultanéité, si un utilisateur de puissance est l'utilisation de plusieurs onglets et parvient à intercaler un couple de requêtes appartenant à la même session (ce qui est très improbable, mais pas impossible), cela peut conduire à des incohérences dans votre application.

C'est la <noscript /> façon de faire de HTTP allers-retours sans aucun sens Url et JavaScript

- Je fournir ce code en tant que prof de concept:Si ce code est exécuté dans un contexte que vous n'êtes pas familier avec, je pense que vous pouvez travailler hors de ce cadre est quoi.

L'idée est que vous appelez Déménager avec un certain état quand vous rediriger, et l'URL que vous déménagé appels GetState pour obtenir les données (le cas échéant).

const string StateCookieName = "state";

static int StateCookieID;

protected void Relocate(string url, object state)
{
    var key = "__" + StateCookieName + Interlocked
        .Add(ref StateCookieID, 1).ToInvariantString();

    var absoluteExpiration = DateTime.Now
        .Add(new TimeSpan(120 * TimeSpan.TicksPerSecond));

    Context.Cache.Insert(key, state, null, absoluteExpiration,
        Cache.NoSlidingExpiration);

    var path = Context.Response.ApplyAppPathModifier(url);

    Context.Response.Cookies
        .Add(new HttpCookie(StateCookieName, key)
        {
            Path = path,
            Expires = absoluteExpiration
        });

    Context.Response.Redirect(path, false);
}

protected TData GetState<TData>()
    where TData : class
{
    var cookie = Context.Request.Cookies[StateCookieName];
    if (cookie != null)
    {
        var key = cookie.Value;
        if (key.IsNonEmpty())
        {
            var obj = Context.Cache.Remove(key);

            Context.Response.Cookies
                .Add(new HttpCookie(StateCookieName)
                { 
                    Path = cookie.Path, 
                    Expires = new DateTime(1970, 1, 1) 
                });

            return obj as TData;
        }
    }
    return null;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top