我们需要进行表单提交并保存一些数据,然后将用户重定向到站点外的页面,但是在重定向过程中,我们需要使用POST而不是GET“提交”表单。

我希望有一个简单的方法来完成这一点,但我开始觉得没有。我想我现在必须创建一个简单的另一个页面,只有我想要的表单,重定向到它,填充表单变量,然后做一个主体。Onload调用脚本,只调用document.forms[0].submit();

谁能告诉我还有别的选择吗?我们可能需要在项目后期进行调整,它可能会变得有点复杂,所以如果有一个简单的方法,我们可以做所有不依赖于其他页面的事情,那就太棒了。

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


当前回答

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

其他回答

@Matt,

您仍然可以使用HttpWebRequest,然后将您接收到的响应定向到实际的输出流响应,这将为用户提供响应。唯一的问题是任何相对url都会被破坏。

不过,这可能奏效。

PostbackUrl可以在asp按钮上设置,以便发布到不同的页面。

如果你需要在代码背后,尝试Server.Transfer。

我会这么做:

将数据放入标准表单(不带runat="server"属性),并将表单的动作设置为发布到目标场外页面。 在提交之前,我将使用XmlHttpRequest将数据提交到服务器并分析响应。如果响应意味着你应该继续与场外张贴然后我(JavaScript)将继续与张贴,否则我会重定向到我的网站上的一个页面

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

通常,您所需要的只是在这两个请求之间携带一些状态。实际上有一种非常时髦的方法来做到这一点,它不依赖于JavaScript(想想<noscript/>)。

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

有了这个cookie,你可以在下面的请求/redirect.html中检索name=value信息,你可以在这个名称/值对字符串中存储任何类型的信息,最多4K的数据(典型的cookie限制)。当然,您应该避免这种情况,而是存储状态代码和标记位。

在收到此请求后,您将返回响应状态码的删除请求。

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

我的HTTP有点生锈了,我一直在通过RFC2109和RFC2965来弄清楚这有多可靠,最好我想让cookie精确地往返一次,但这似乎不可能,而且,如果你迁移到另一个域,第三方cookie可能对你来说是一个问题。这仍然是可能的,但并不像你在自己的领域内做事情那样轻松。

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

这是<noscript/>的HTTP往返方式,没有无意义的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;
}