简体   繁体   中英

The same code works using HttpWebRequest but not using HttpRequestMessage

I've created HttpClient that I'm using for sending requests:

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

After that I'm creating instance of custom class that stores the cookies string for an account (something like id=xxxxxxxx; tkz=xxxxxxxxxx; token=xxxxxxxxxxx .

That's how I'm sending a post request:

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

I don't get what's wrong with this code. It seems correct to me.

Also, when I set AllowAutoRedirect = false it returns 301: Moved Permanently error, while normally it returns 200 with no HTML no matter what I pass as content.

What am I doing wrong?

Edit: Here's the JavaScript function I'm basing my request on:

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

I've worked with more complex AJAX before, but this just doesn't seem to work no matter what I do.

Edit: I've lost my patience and switched to HttpWebRequest instead.

Now the method looks like this:

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

Maybe I'm just dumb but for me it doesn't seem all that different. Are there some key differences that can be the cause?

Here is code from one of my working systems that submits a POST request through an HTTPClient .

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

[Edit] The "PostMessage" was modified to remove domain-specific details. Here is how BodyContent is defined inside the real "PostMessage" from my solution, to provide you enough context to understand what that "message" actually is and how it works into the sample.

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

...and here is PostRequest (again, with domain-specific details trimmed)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM