2

So I am just trying to create a basic Stack Overflow Client using WebClient. When I run the program as is, I get an empty string result, even if I sleep and wait. However when I open up Fiddler2 the program works... All I have to do is open Fiddler... Here is the relevant code.

public partial class MainWindow : Window
{
    public  ObservableCollection<question>  questions { get; set; }

    public MainWindow() 
    {
        questions = new ObservableCollection<question>();
        this.DataContext = this;

        InitializeComponent();
    }

    void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        MessageBox.Show(e.Result); //Right here is the difference. When 

        <BREAK POINT HERE OR IT BREAKS>

        string data = data = e.Result.Substring(e.Result.IndexOf("class=\"question-summary narrow\"") + 31);
        string content = data.Substring(0, data.IndexOf("class=\"question-summary narrow\""));
        string v, a, t, b, tgs, link;
        questions.Add(new question
            {
                //votes = v,
                //answers = a,
                //title = t.ToUpper(),
                //body = b,
                ////tags = tgs
                //href = link
             });
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        WebClient wc = new WebClient();
        wc.DownloadStringAsync(new Uri(@"http://api.stackoverflow.com/1.1/questions"));
        wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
    }
}
public class question
{
    public string votes { get; set; }
    public string answers { get; set; }
    public string title { get; set; }
    public string body { get; set; }
    public string tags { get; set; }
    public string href { get; set; }
}

Also worth noting is the fidler results When I load http://api.stackoverflow.com/1.1/questions in the browser fiddler shows

GET http://api.stackoverflow.com/1.1/questions 200 OK (application/json)

and

GET http://api.stackoverflow.com/favicon.ico 503 Service Unavailable (text/html)

When I load it in my program though only this shows

GET http://api.stackoverflow.com/1.1/questions 200 OK (application/json)

EricLaw
  • 56,563
  • 7
  • 151
  • 196
DotNetRussell
  • 9,716
  • 10
  • 56
  • 111
  • For the browser vs. app thing, browsers always ask for favicon.ico so they can put their image on the browser tab - that's normal, and errors here are no big deal. – Joe Enos Mar 08 '13 at 19:55
  • Alright well at least we can rule that shenanigans out. – DotNetRussell Mar 08 '13 at 19:56
  • Have you tried running this synchronously instead of asynchronously to see what happens? Is the result complete when you do it that way? What you're describing sounds like even though the complete event is firing, the result isn't truly back yet - but that doesn't really make sense. Also, maybe try throwing a `Thread.Sleep(2000)` or something in that event handler, just in case that might be the issue - if it works with the `Sleep` but doesn't without it, then something really funky is going on. – Joe Enos Mar 08 '13 at 19:57
  • Yeah sync isnt working at all. This is what I tried WebClient wc = new WebClient(); MessageBox.Show(wc.DownloadString(new Uri(@"http://api.stackoverflow.com/1.1/questions"))); – DotNetRussell Mar 08 '13 at 20:05
  • Are you missing the `http://`? – Joe Enos Mar 08 '13 at 20:25
  • What I have is what is listed above. It has the http:// in there minus the messed up one I posted. I tried it with http though – DotNetRussell Mar 08 '13 at 20:27
  • Stack takes out the Http:// when I post – DotNetRussell Mar 08 '13 at 20:28
  • What error are you getting on the synchronous one? That one should be pretty straightforward. – Joe Enos Mar 08 '13 at 20:28
  • Thats the thing. There is no error. When I run this either from executable or in debug mode there is no return value. When I run either while fiddler2 is running it returns the json. – DotNetRussell Mar 08 '13 at 20:29

1 Answers1

4

Looks like the problem is with the API itself. Even though you are not telling it that you accept GZipped content, it's GZipping it anyway, and apparently Fiddler deals with that and unzips it for you. In your app, you have to deal with this by unzipping the content. Here's a simple example of how to do that:

var wc = new WebClient();
var bytes = wc.DownloadData(new Uri(@"http://api.stackoverflow.com/1.1/questions"));
string responseText;
using (var outputStream = new MemoryStream())
{
    using (var memoryStream = new MemoryStream(bytes))
    {
        using (var gzip = new GZipStream(memoryStream, CompressionMode.Decompress))
        {
            byte[] buffer = new byte[1024];
            int numBytes;
            while ((numBytes = gzip.Read(buffer, 0, buffer.Length)) > 0)
            {
                outputStream.Write(buffer, 0, numBytes);
            }
        }
        responseText = Encoding.UTF8.GetString(outputStream.ToArray());
    }
}

Console.WriteLine(responseText);

Whether or not it will always be GZipped, who knows - you can check the Content-Encoding HTTP header to see if it's gzip, and if so, then run this code, and if not, then you can convert the bytes directly into text.

Joe Enos
  • 39,478
  • 11
  • 80
  • 136
  • 1
    Anytime. I actually ran across that same issue a couple months ago with a regular website (not an API) - irritated the crap out of me that a site would do that. You'd have to purposely override your web server settings to make it compress when the client doesn't tell you they can do it. – Joe Enos Mar 08 '13 at 21:14
  • Fiddler only decompresses the content when you tell it to. You likely have the DECODE toggle set on the toolbar. – EricLaw Mar 09 '13 at 14:40
  • 2
    See this answer for a way to automatically decompress the gzipped response by deriving from `WebClient`: http://stackoverflow.com/a/4914874 – Bradley Grainger Mar 09 '13 at 15:18
  • @BradleyGrainger Wow, crazy that they had that in the old-school web client, but not the newer ones. Seems like it would be pretty useful to have that built in. – Joe Enos Mar 10 '13 at 14:45
  • It's not actually legal for the server to compress something if the client didn't ask for compression. For instance, if you configure IE not to send Accept: deflate,gzip, then it won't decompress if the server uses either encoding. – EricLaw Mar 11 '13 at 20:52
  • 1
    @EricLaw I can see where they're coming from - [from their site](http://api.stackoverflow.com/1.1/usage/gzip) - I don't know if I like it, but it's hard to disagree that many devs would probably not think to turn on compression otherwise, and compressing makes an enormous impact on bandwidth. BTW, I love Fiddler - couldn't live without it. Hope things are going well for you at Telerik. – Joe Enos Mar 11 '13 at 21:42