10

I am new to both C# and Windows phone and am trying to make a small app that performs a JSON request. I am following the example in this post https://stackoverflow.com/a/4988809/702638

My current code is this:

public string login()
{
    var httpWebRequest = (HttpWebRequest)WebRequest.Create(MY_URL);
    httpWebRequest.ContentType = "text/plain"; 
    httpWebRequest.Method      = "POST";

    using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
    {
       string text = MY_JSON_STRING;
       streamWriter.Write(text);
    }
}

but for some reason Visual Studio is flagging GetRequestStream() with an error message:

error CS1061: 'System.Net.HttpWebRequest' does not contain a definition for 'GetRequestStream' and no extension method 'GetRequestStream' accepting a first argument of type 'System.Net.HttpWebRequest' could be found (are you missing a using directive or an assembly reference?)

Any thoughts on why this would be happening? I have already imported the System.Net package.

Community
  • 1
  • 1
Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170
  • You should use the `HttpClient` class instead; it's more modern and much easier to use. – SLaks Jan 15 '13 at 18:10
  • @SLaks Like I mentioned above I am extremely new to C#, thank you for your suggestion though. – Hunter McMillen Jan 15 '13 at 18:12
  • @SLaks: HttpClient doesn't exist in Windows Phone 8, unfortunately. – Peter Huene Jan 15 '13 at 18:18
  • @PeterHuene: AFAIK, it's available on NuGet. (I'm not sure whether it's still Pre-release) – SLaks Jan 15 '13 at 20:53
  • @Slaks: oooh, what's the package name? A proper HttpClient implementation would make porting between W8 and WP8 easier. – Peter Huene Jan 15 '13 at 21:14
  • @PeterHuene: Try http://nuget.org/packages/Microsoft.Net.Http – SLaks Jan 16 '13 at 03:46
  • @SLaks I tried installing this package into my application and it failed because my target was Windows Phone 8. "Install-Package : Could not install package 'Microsoft.Net.Http 2.0.20710.0'. You are trying to install this package into a project that targets 'WindowsPhone,Version=v8.0', but the package does not contain any assembly references that are compatible with that framework. For more information, contact the package author." – Hunter McMillen Jan 16 '13 at 04:54

1 Answers1

16

HttpWebRequest doesn't have a GetRequestStream or GetRequestStreamAsync in WP8. Your best bet is to create a Task and await on it, like so:

using (var stream = await Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null))
{
    // ...
}

Edit: as you've mentioned that you're new to C#, you would need to have your login method be async to use the await keyword:

public async Task<string> LoginAsync()
{
    // ...
}

Callers to login would need to use the await keyword when calling:

string result = await foo.LoginAsync();

Here's a good primer on the subject: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

Peter Huene
  • 5,758
  • 2
  • 34
  • 35
  • How can I write my json string to the stream inside the Task? – Hunter McMillen Jan 15 '13 at 18:54
  • byte[] content = Encoding.UTF8.GetBytes(text); await stream.WriteAsync(content, 0, content.Length); Note: you'll probably want to specify a utf-8 encoding in the content type. – Peter Huene Jan 15 '13 at 19:10
  • How could I read data back from the Write? I am using the WriteAsync call to POST to a URL, but would like to read the response. Also I was hoping to call this method from a Constructor, but received an error because constructors' cannot be async. Do I really need async here? This is for logging into a service ? There is nothing else to be done until the user authenticates. – Hunter McMillen Jan 16 '13 at 00:54
  • The request stream is only for writing to. To get the response, you'll want to do something like this: var response = (HttpWebResponse)await Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null); The HttpWebResponse class, surprisingly, has GetResponseStream which will directly give you back a stream you can read the response from. As for calling it in a constructor, you would have to synchronously wait on the task to complete (if you omit the await keyword, you can call Wait on the returned Task object or access the Result property). continued... – Peter Huene Jan 16 '13 at 01:02
  • ... continued. This would eliminate the benefits of the async paradigm: namely you can have the user interface "do something" and be responsive while the login is taking place. If you have something like a "login" button, you could asynchronously wait on the login to take place in the clicked event handler and this would allow you to display a busy spinner, for example, all without having to do any background multithreading yourself. – Peter Huene Jan 16 '13 at 01:03