【问题标题】:The same code works using HttpWebRequest but not using HttpRequestMessage相同的代码使用 HttpWebRequest 但不使用 HttpRequestMessage
【发布时间】:2016-02-17 00:31:29
【问题描述】:

我创建了HttpClient 用于发送请求:

public static void Initialize()
{
    handler = new HttpClientHandler() { UseCookies = false, AllowAutoRedirect = true };
    http = new HttpClient(handler) { BaseAddress = new Uri("http://csgolounge.com/mytrades") };
    http.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36");
}

之后,我将创建自定义类的实例,用于存储帐户的 cookie 字符串(类似于 id=xxxxxxxx; tkz=xxxxxxxxxx; token=xxxxxxxxxxx

这就是我发送帖子请求的方式:

public async Task Bump()
{
    //if (Bumpable)
    //{
    var req = new HttpRequestMessage(HttpMethod.Post, "http://www.csgolounge.com/ajax/bumpTrade.php");
    req.Headers.Add("Cookie", cookieString);
    req.Headers.Add("X-Requested-With", "XMLHttpRequest");
    req.Headers.Add("Referer", "http://csgolounge.com/mytrades"); //Not really sure if this does anything but I've run out of smart ideas long time ago

    /*Dictionary<string, string> postData = new Dictionary<string, string>()
    {
        {"trade", offer_id}
    };
    var encoded = new FormUrlEncodedContent(postData);
    */
    req.Content = new StringContent("&trade="+Offer_id, Encoding.UTF8, "application/x-www-form-urlencoded"); //Desperation.. decided to change the encoded dictionary to StringContent
    var res = await SteamAccount.http.SendAsync(req);
    var html = await res.Content.ReadAsStringAsync();
    //}
}

我不明白这段代码有什么问题。这对我来说似乎是正确的。

另外,当我设置 AllowAutoRedirect = false 时,它返回 301: Moved Permanently 错误,而通常它返回 200,没有 HTML,无论我作为内容传递什么。

我做错了什么?

编辑:这是我提出请求的 JavaScript 函数:

function bumpTrade(trade) {
    $.ajax({
        type: "POST",
        url: "ajax/bumpTrade.php",
        data: "trade=" + trade
    });
}

我以前使用过更复杂的 AJAX,但无论我做什么,这似乎都不起作用。

编辑:我失去了耐心,转而使用HttpWebRequest

现在方法如下所示:

public async Task BumpLegacy()
{
    while (true)
    {
        try
        {
            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://csgolounge.com/ajax/bumpTrade.php");
            var cc = new CookieContainer();
            MatchCollection mc = Regex.Matches(Account.CookieString, @"\s?([^=]+)=([^;]+);");
            foreach (Match m in mc)
                cc.Add(new Cookie(m.Groups[1].Value, m.Groups[2].Value, "/", "csgolounge.com"));
            httpWebRequest.CookieContainer = cc;
            byte[] bytes = Encoding.ASCII.GetBytes("trade=" + Offer_id);
            httpWebRequest.Referer = "http://csgolounge.com/mytrades";
            httpWebRequest.Headers.Add("X-Requested-With", "XMLHttpRequest");
            httpWebRequest.Method = "POST";
            httpWebRequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
            httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36";
            httpWebRequest.ContentLength = (long)bytes.Length;
            var g = await httpWebRequest.GetRequestStreamAsync();
            await g.WriteAsync(bytes, 0, bytes.Count());
            g.Close();
            var res = await httpWebRequest.GetResponseAsync();
            res.Close();
            break;
        }
        catch
        {
        }
    }
}

也许我只是笨,但对我来说似乎并没有什么不同。是否存在一些可能是原因的关键差异?

【问题讨论】:

  • 没注意到,谢谢陛下指出。
  • 您遇到的具体问题是什么?
  • 即使我得到状态码 200 也没有任何反应。此外,没有消息表明我的请求缺少某些参数或类似的东西。理论上一切似乎都行得通,但事实并非如此。
  • 您是否能够通过代码外部的 HTTP 代理确认对已识别资源的 /POST 将产生您想要的结果?去 Fiddler 写一个/POST 看看资源系统是否正确集成了你的请求;否则,您同时要测试的变量太多。
  • 我已经改用HttpWebRequest,因为我知道它确实可以解决这个问题,但我仍然不明白为什么。我在这里到底做了什么不同的事情?

标签: c# httprequest httpclient


【解决方案1】:

这是来自我的一个工作系统的代码,它通过HTTPClient 提交 POST 请求。

[Route("resource")]
public async Task<dynamic> CreateResource([FromBody]Resource resource)
{
    if (resource == null) return BadRequest();
    dynamic response = null;
    resource.Topic = GetDataFromSomewhereElse();
    var message = new PostMessage(resource).BodyContent;

    dynamic postRequest = new
    {
        Message = message
    };
    var post = JsonConvert.SerializeObject(postRequest);

    HttpContent content = new StringContent(post, Encoding.UTF8, "application/json");

    using (var client = new HttpClient())
    {
        client.Timeout = TimeSpan.FromMinutes(1);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

        try
        {
            client.BaseAddress = @"http://localhost:51145/"; 

            HttpResponseMessage postResponse = await client.PostAsync("Resource", content); //"Resource" is a route exposed on the remote host

            string json = await postResponse.Content.ReadAsStringAsync();

            if (postResponse.StatusCode == HttpStatusCode.BadRequest) return BadRequest();
            if (postResponse.StatusCode == HttpStatusCode.InternalServerError) return InternalServerError();
            if (postResponse.StatusCode == HttpStatusCode.NotFound) return NotFound();

            return json;
        }
        catch(Exception ex)
        {
            return InternalServerError(ex);
        }
    }
}

[编辑] 修改了“PostMessage”以删除特定于域的详细信息。以下是我的解决方案中真正的“PostMessage”中如何定义BodyContent,以便为您提供足够的上下文来了解该“消息”实际上是什么以及它如何在示例中起作用。

public string BodyContent
    {
        get
        {
            string content = "";

            Type type = this.GetType();
            Assembly assembly = Assembly.GetExecutingAssembly();
            string resource = String.Format("{0}.{1}", type.Namespace, this.EmbeddedResourceName);
            Stream stream = assembly.GetManifestResourceStream(resource);
            StreamReader reader = new StreamReader(stream);
            content = reader.ReadToEnd();

            return content;
        }
    }

...这里是PostRequest(同样,修剪了特定领域的细节)

public class PostRequest
{
   public string Message { get;set; }
}

【讨论】:

  • 我不认为这种方法的结果有什么不同
  • @Reynevan 那么问题在于远程服务主机或您的调用约定。如果您需要以某种方式构建您的 POST 正文,那么他们的服务端点可能会拒绝它但响应 200 OK(愚蠢)我的建议是首先从等式中删除 C# http 客户端库。进入 Fiddler 或 POSTman 并向该服务器发送 POST 请求。然后去确认您的 POST 已处理(但是您是使用远程服务器执行此操作的)。然后添加自动化客户端代码。
  • 我几乎和你说的完全一样,结果无论请求失败还是成功,响应看起来都是一样的。我检查了 Fiddler 的外观并分配了缺失的标题。似乎有所帮助。感谢您提供信息。
猜你喜欢
  • 2015-11-07
  • 1970-01-01
  • 2016-02-19
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多