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

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

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

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


当前回答

通常,您所需要的只是在这两个请求之间携带一些状态。实际上有一种非常时髦的方法来做到这一点,它不依赖于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;
}

其他回答

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

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

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

ASP中的一些新东西。Net 3.5是ASP按钮的“PostBackUrl”属性。您可以将其设置为您想要直接发布到的页面的地址,当单击该按钮时,它不会像正常情况下那样发布回同一页面,而是会发布到您所指示的页面。方便。确保UseSubmitBehavior也被设置为TRUE。

基于Pavlo Neyman方法的可复制粘贴代码

RedirectPost(string url, T bodyPayload)和GetPostData()是为那些只想在源页面中转储一些强类型数据并在目标页面中取回它的人准备的。 数据必须由NewtonSoft Json序列化。NET,当然你需要引用这个库。

只需复制粘贴到您的页面,或者更好的是您的页面的基类,并在应用程序的任何地方使用它。

我的心与2019年仍然必须使用Web Forms的所有人同在。

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

你可以使用这个方法:

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。