Response.Redirect用POST代替Get?

时间:2020-03-05 18:48:27  来源:igfitidea点击:

我们需要进行表单提交并保存一些数据,然后将用户重定向到非现场页面,但是在重定向中,我们需要使用POST(而不是GET)"提交"表单。

我希望有一个简单的方法来完成此任务,但我开始认为没有。我想我现在必须创建一个简单的其他页面,仅包含我想要的表单,重定向到该页面,填充表单变量,然后对仅调用document.forms [0] .submit()的脚本执行body.onload调用);

谁能告诉我是否有其他选择?我们可能稍后在项目中需要对此进行调整,这可能会变得有些复杂,因此,如果有一个简单的方法,我们可以执行所有非其他页面相关的操作,这将非常棒。

无论如何,感谢所有回复。

解决方案

回答

可以在asp按钮上设置PostbackUrl以发布到其他页面。

如果我们需要在代码隐藏中进行操作,请尝试Server.Transfer。

回答

我建议构建一个HttpWebRequest以编程方式执行POST,然后在阅读了Response(如果适用)之后重定向。

回答

HttpWebRequest用于此目的。

在回发时,向第三方创建一个HttpWebRequest并发布表单数据,然后完成该操作,我们可以在任何需要的地方进行Response.Redirect。

我们获得的另一个好处是,不必命名所有服务器控件即可构成第三方表单,我们可以在构建POST字符串时进行此转换。

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

但是,如果我们需要用户从此表单中查看响应页面,则唯一的选择是利用Server.Transfer,这可能会或者可能不会起作用。

回答

@Matt,

我们仍然可以使用HttpWebRequest,然后将收到的响应定向到实际的outputstream响应,这会将响应提供给用户。唯一的问题是任何相对URL都将被破坏。

不过,这可能会起作用。

回答

这是我要做的:

将数据放入标准表单中(没有runat =" server"属性),并将表单的操作设置为发布到目标异地页面。
在提交之前,我将使用XmlHttpRequest将数据提交到我的服务器并分析响应。如果响应表示我们应该继续进行异地发布,那么我(JavaScript)将继续该发布,否则我将重定向到我网站上的页面

回答

为此,需要了解HTTP重定向的工作方式。当我们使用Response.Redirect()时,我们将使用HTTP状态代码302发送响应(发送给发出请求的浏览器),该状态码告诉浏览器下一步该去哪里。根据定义,即使原始请求是POST,浏览器也会通过GET请求来实现。

另一种选择是使用HTTP状态代码307,该状态代码指定浏览器应以与原始请求相同的方式发出重定向请求,但以安全警告提示用户。为此,我们将编写如下内容:

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

不幸的是,这并不总是可行的。不同的浏览器以不同的方式实现此功能,因为它不是通用的状态码。

Alas, unlike the Opera and FireFox developers, the IE developers have never read the spec, and even the latest, most secure IE7 will redirect the POST request from domain A to domain B without any warnings or confirmation dialogs! Safari also acts in an interesting manner, while it does not raise a confirmation dialog and performs the redirect, it throws away the POST data, effectively changing 307 redirect into the more common 302.

因此,据我所知,实现这种功能的唯一方法是使用Javascript。我可以想到两种选择:

  • 创建表单并将其" action"属性指向第三方服务器。然后,在"提交"按钮上添加一个click事件,该事件首先对数据执行对服务器的AJAX请求,然后允许将表单提交给第三方服务器。
  • 创建表单以发布到服务器。提交表单后,向用户显示一个包含表单的页面,其中包含我们要传递的所有数据,所有数据都在隐藏的输入中。只需显示诸如"正在重定向..."之类的消息即可。然后,将一个javascript事件添加到将表单提交到第三方服务器的页面。

出于两个原因,我将选择第二个。首先,它比第一种更可靠,因为它不需要Java脚本才能起作用。对于未启用该功能的用户,我们始终可以使隐藏表单的"提交"按钮可见,并指示他们在5秒钟以上的时间内按下该按钮。其次,我们可以决定将哪些数据传输到第三方服务器。如果仅使用处理表单的方式,则将传递所有发布数据,而这并非总是我们想要的。假定307解决方案适用于所有用户,则与307解决方案相同。

希望这可以帮助!

回答

In PHP, you can send POST data with cURL. Is there something comparable for .NET?

是的,HttpWebRequest,请参阅下面的我的帖子。

回答

绝对不要使用GET(和HEAD)方法来做任何有副作用的事情。一个副作用可能是更新Web应用程序的状态,或者它可能是信用卡收费。如果操作具有副作用,而应使用的另一种方法(POST)。

因此,用户(或者其浏览器)不应对GET所做的事情负责。如果由于GET产生了一些有害或者昂贵的副作用,那将是Web应用程序的错误,而不是用户的错误。根据规范,除非是对GET或者HEAD请求的响应,否则用户代理不得自动遵循重定向。

当然,即使只是将其添加到日志文件中,许多GET请求也确实有一些副作用。重要的是应由应用程序(而不是用户)对这些后果负责。

HTTP规范的相关部分是9.1.1和9.1.2,以及10.3.

回答

通常,我们只需要在这两个请求之间携带某种状态即可。实际上,有一种非常时髦的方式可以做到这一点,它不依赖JavaScript(请考虑<noscript />)。

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

使用该cookie,我们可以在以下请求中通过/redirect.html检索name = value信息,可以在此name / value对字符串中存储任何类型的信息,最多可存储4K数据(典型cookie限制)。当然,我们应该避免这种情况,而应存储状态代码和标志位。

收到此请求后,我们会返回一个针对该状态码的删除请求。

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

我的HTTP有点生锈,我一直在通过RFC2109和RFC2965来弄清楚这到底有多可靠,我最好让Cookie来回往返一次,但是第三方cookie似乎也不可能如果我们要移至另一个域,可能对我们来说是个问题。这仍然是可能的,但没有我们在自己的域中从事工作时那样轻松。

这里的问题是并发性,如果高级用户正在使用多个选项卡并设法交织属于同一会话的几个请求(这不太可能,但并非不可能),这可能导致应用程序不一致。

这是进行HTTP往返旅行的<noscript />方式,没有无意义的URL和JavaScript

我提供此代码作为概念证明:如果此代码在我们不熟悉的上下文中运行,我认为我们可以算出哪一部分是什么。

这个想法是,当我们重定向时,我们以某种状态调用Relocate,而我们重定位的URL则调用GetState以获取数据(如果有)。

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

回答

我们可以使用以下方法:

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

结果,客户端将在从服务器获取所有html之后立即发生事件onload,该事件触发表单提交并将所有数据发布到定义的postbackUrl。

回答

ASP.Net 3.5中的新功能是ASP按钮的" PostBackUrl"属性。我们可以将其设置为要直接发布到的页面的地址,然后单击该按钮,而不是像通常那样发布回到同一页面,而是将其发布到我们指示的页面。便利。确保UseSubmitBehavior也设置为TRUE。