0

Targets: - .NET Framework 4.5; - Windows 8; - Windows Phone 8.1; - Portable class library.

Hi all, I need to implement HTTP POST request on C# .NET Portable class library. I have faced with a problem, that parameters are not sent (request body is empty).

UPDATE I've tried this link and this link approaches with HttpClient, and request body is still empty END UPDATE

Here is comparison via fiddler of expected and actual request. enter image description here

I have a code of this request that works fine from common ConsoleApplication, but I did not found a way how to implement such request at Portable class library. Here is code that works from common Console app:

using System;
using System.IO;
using System.Net;

namespace ConsoleApplication3
{
class Program
{
    static void Main(string[] args)
    {
        var p = new Program();
        p.MakeRequests();

    }

    private void MakeRequests()
    {
        HttpWebResponse response;
        string json = String.Empty;

        if (Request_www_example_com(out response))
        {
            using (var sr = new StreamReader(response.GetResponseStream()))
            {
                json = sr.ReadToEnd();
            }
            response.Close();
        }
    }

    private bool Request_www_example_com(out HttpWebResponse response)
    {
        response = null;

        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.example.com/gps/?city=kyiv&ID=3&lang=ru");

            request.Accept = "*/*";
            request.ContentType = "application/x-www-form-urlencoded";
            request.Headers.Add("Accept-Languages", @"ru-RU,ru;q=0.7,en-US;q=0.6,en;q=0.4");
            request.Headers.Add("Contents-Length", @"59");
            request.Headers.Add("X-Requested-With", @"XMLHttpRequest");
            request.Referer = "http://www.example.com/";
            request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.7,ru;q=0.3");
            request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
            request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko";
            request.Headers.Set(HttpRequestHeader.Pragma, "no-cache");

            request.Method = "POST";
            request.ServicePoint.Expect100Continue = false;

            string body = @"city=kyiv&ID=3&lang=ru";
            byte[] postBytes = System.Text.Encoding.UTF8.GetBytes(body);
            request.ContentLength = postBytes.Length;
            Stream stream = request.GetRequestStream();
            stream.Write(postBytes, 0, postBytes.Length);
            stream.Close();

            response = (HttpWebResponse)request.GetResponse();
        }
        catch (WebException e)
        {
            if (e.Status == WebExceptionStatus.ProtocolError) response = (HttpWebResponse)e.Response;
            else return false;
        }
        catch (Exception)
        {
            if (response != null) response.Close();
            return false;
        }

        return true;
    }
}
}

So please help me to translate this code to Portable. Thanks !

Community
  • 1
  • 1
Mykola
  • 56
  • 1
  • 6

3 Answers3

1

So this I've seen some weird issues with the HttpWebRequest, if you really want to continue with the HttpWebRequest just be aware that the App and Phone versions do not work the same (even in a portable project). There were 2 main issues that I found:

  • Content Type not changing
  • Content-Length not changing

To fix these issues, this is what I used:

        HttpWebRequest webRequest = WebRequest.CreateHttp(yourRequest.RequestUri);
        webRequest.Method = yourRequest.Method;

        // HttpWebRequest does not change when assigning, have to assign base class
        ((WebRequest)webRequest).ContentType = client.Headers.ContentType;

        if (yourRequest.RequestString != null)
        {
            // For Windows Phone 8.1 to work
            if (webRequest.Headers.AllKeys.Contains("Content-Length"))
            {
                webRequest.Headers[HttpRequestHeader.ContentLength] = yourRequest.RequestString.Length.ToString();
            }

            // This is for Windows 8.1 to work
            byte[] arrData = Encoding.UTF8.GetBytes(yourRequest.RequestString);
            using (Stream dataStream = await webRequest.GetRequestStreamAsync())
            {
                dataStream.Write(arrData, 0, arrData.Length);
            }
        }

Hope this helps!

Barnstokkr
  • 2,904
  • 1
  • 19
  • 34
  • thank you, Barnstokkr, you helps me to find a problem: for some reason when I run code from unit test - it send request with empty body, but in other case, when i run this method from windows 8 app - it works fine – Mykola Apr 19 '15 at 17:39
0

I believe you need to change the header name from "Contents-Length" to "Content-Length" to fix your problem. But you should also be using Windows.Web.Http.HttpClient as this is recommended by Microsoft going forward.

Jon
  • 2,891
  • 2
  • 17
  • 15
  • I've tried this [link](http://stackoverflow.com/questions/12390511/c-sharp-httpclient-formurlencodedcontent-encoding-vs-2012) and this [link](http://stackoverflow.com/questions/15176538/net-httpclient-how-to-post-string-value) approaches with HttpClient, and request body is still empty – Mykola Apr 15 '15 at 20:43
  • 1
    Why are you putting the parameters (city=kyiv&ID=3&lang=ru) in the URL and also in the body? – Jon Apr 15 '15 at 22:13
0

If it helps someone: it is possible to face with problem when request has been sent without body when you run code from unit test. Here is an example of code that forks fine for windows 8\windows phone app:

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
    public async Task<string> RunHttpPost(string city, string Id)
    {
        var _url = String.Format("http://www.example.com/gps/?city={0}&Id={1}",city,Id);           

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml");
            client.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
            client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
            client.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", "ISO-8859-1");
            client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");

            var values = new Dictionary<string, string>{

            { "city", city },
            { "Id", Id }
            };

            var content = new FormUrlEncodedContent(values);

            var response = await client.PostAsync(_url, content);

           return await response.Content.ReadAsStringAsync();
        }
Mykola
  • 56
  • 1
  • 6