如何在ASP.NET中以编程方式模拟HTTP POST?

问题描述:

我需要以编程方式模拟HTTP POST,即我需要生成带有一些POST变量的请求,然后将其发送到页面。如何在ASP.NET中以编程方式模拟HTTP POST?

为了澄清,我需要模拟常规POST的行为,而不是以编程方式完成整个事情。所以基本上我需要填写一个请求,就像POST表单发生时那样填充Request,然后将浏览器发送到期望POST的页面。

这是一种方法。

您以NameValueCollection的形式发送此方法的URL和名称/值参数。该方法在端点上创建一个Http Post并将响应作为字符串返回。

当然,取决于你为什么要做这个以及调用这个方法的次数,还有其他的选择。但是,除非您提供有关您特定需求的更多信息,否则此方法足够好。

下面的方法使用任务(.NET 4.0)和异步方法,所以它会更快然后如果你正在做的,例如一个循环多次调用,如下面的代码同步方法上市。

static string GetWebResponse(string url, NameValueCollection parameters) 
{ 
    var httpWebRequest = (HttpWebRequest)WebRequest.Create(url); 
    httpWebRequest.ContentType = "application/x-www-form-urlencoded"; 
    httpWebRequest.Method = "POST"; 

    var sb = new StringBuilder(); 
    foreach (var key in parameters.AllKeys) 
    sb.Append(key + "=" + parameters[key] + "&"); 
    sb.Length = sb.Length - 1; 

    byte[] requestBytes = Encoding.UTF8.GetBytes(sb.ToString()); 
    httpWebRequest.ContentLength = requestBytes.Length; 

    using (var requestStream = httpWebRequest.GetRequestStream()) 
    { 
    requestStream.Write(requestBytes, 0, requestBytes.Length); 
    requestStream.Close(); 
    } 

    Task<WebResponse> responseTask = Task.Factory.FromAsync<WebResponse>(httpWebRequest.BeginGetResponse, httpWebRequest.EndGetResponse, null); 
    using (var responseStream = responseTask.Result.GetResponseStream()) 
    { 
    var reader = new StreamReader(responseStream); 
    return reader.ReadToEnd(); 
    } 
} 

你也可以使用WebClient(这有点简单)。所以,如果你用这个方法一定要在你的参数传递这样或修改的实施,像上面的代码此方法需要在形式

name1=value1&name2=value2&name3=value3 

等职参数为字符串。

static string HttpPost(string url, string Parameters) 
{ 
    var req = System.Net.WebRequest.Create(url);  

    req.ContentType = "application/x-www-form-urlencoded"; 
    req.Method = "POST"; 
    byte[] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters); 
    req.ContentLength = bytes.Length; 
    System.IO.Stream os = req.GetRequestStream(); 
    os.Write (bytes, 0, bytes.Length); 
    os.Close(); 
    System.Net.WebResponse resp = req.GetResponse(); 
    if (resp== null) 
    return null; 
    var sr = new StreamReader(resp.GetResponseStream()); 
    return sr.ReadToEnd().Trim(); 
} 
+0

正如我在另一条评论中提到的,我需要能够在用我需要的POST变量“构造”请求之后执行常规的Response.Redirect()。 – Farinha 2011-02-23 14:09:25

+0

@Farina,然后请修改你的问题,并明确说明。你不能指望每个人都阅读你的所有评论,只是为了了解你需要什么。 – 2011-02-23 19:39:51

+0

@Farina,我读了其他评论,我不确定我是否理解你的要求,所以请花时间尽可能清楚地解释你正在尝试做什么(在你的问题中)。当你发出一个http请求(GET或POST)对方时,可能会发送你重定向。在这种情况下,您需要遵循该重定向。你不能自己重定向。 – 2011-02-23 19:42:46

您需要HttpWebRequest类。

像这样的东西?

public string DoFormPost(string Target, string PostData) 
    { 
     //Make a request    
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Target); 
     request.Method = "POST"; 
     request.ContentType = "application/x-www-form-urlencoded"; 
     request.AllowAutoRedirect = false; 

     //Put the post data into the request 
     byte[] data = (new ASCIIEncoding()).GetBytes(PostData); 
     request.ContentLength = data.Length; 
     Stream reqStream = request.GetRequestStream(); 
     reqStream.Write(data, 0, data.Length); 
     reqStream.Close(); 

     //Get response 
     HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

     //Output response to a string    
     String result = ""; 
     using (Stream responseStream = response.GetResponseStream()) 
     { 
      using (StreamReader reader = new StreamReader(responseStream, Encoding.UTF8)) 
      { 
       result = reader.ReadToEnd(); 
       reader.Close(); 
      } 
      return result; 
     } 
    } 

我问这个问题在过去这里:

POST a HTML Form programmatically?

我是针对下面的链接这对我来说真是棒极了!:

WebClient.UploadValues

+0

我看到了一个,但WebClient是做POST的人,我打算在设置POST变量后执行正常的Response.Redirect()。 – Farinha 2011-02-23 14:08:26

我认为做你想做的事并不容易,但可能会有一个接受可行的解决方法。 这里有解决方法的一些想法:

  • 返回JavaScript与您要发布,并有JavaScript的形式沿浏览器做后你。虽然这不安全。
  • 如果目标页面在您的控制之下,请通过HttpContext.Current.Items传递数据,调用Transfer,并让目标页面识别出特殊情况并处理它。使用HttpContext.Current.Items的一个好处是它在请求结束时自动清除,与会话状态不同。
  • 如果要将其他页面的结果嵌入当前页面,HttpServerUtility.Execute会很有用。它不允许您设置表单发布数据或URL请求参数。
  • 按照其他答案中所述运行HttpWebRequest,并使用Response.Write将其作为网页的响应返回。您可能还需要提供用户身份验证凭据和Cookie。请参阅HttpWebRequest.Credentials和HttpWebRequest.CookieContainer。
  • 如果您可以修改目标页面,以便在重新请求时显示相同的信息,则可以执行HttpWebRequest,并按照浏览器的重定向进行操作。
  • 重构代码,以便任一页面都可以生成相同的输出(例如:使用共享UserControl或自定义WebControl)。
  • 如果目标页面位于另一个站点上,则页面抓取可能很有用。提出请求,刮取结果,并在您自己的页面上显示结果。