Question

I have been stuck on this all weekend and failed miserably!
Please help me to claw back my sanity!!

Your challenge

For my first Silverlight application I thought it would be fun to use the World of Warcraft armoury to list the characters in my guild. This involves making an asyncronous from Silverlight (duh!) to the WoW armoury which is XML based. SIMPLE EH?

Take a look at this link and open the source. You'll see what I mean: http://eu.wowarmory.com/guild-info.xml?r=Eonar&n=Gifted and Talented

Below is code for getting the XML (the call to ShowGuildies will cope with the returned XML - I have tested this locally and I know it works).

I have not managed to get the expected returned XML at all.

Notes:

  • If the browser is capable of transforming the XML it will do so, otherwise HTML will be provided. I think it examines the UserAgent
  • I am a seasoned asp.net web developer C# so go easy if you start talking about native to Windows Forms / WPF
  • I can't seem to set the UserAgent setting in .net 4.0 - doesn't seem to be a property off the HttpWebRequest object for some reason - i think it used to be available.
  • Silverlight 4.0 (created as 3.0 originally before I updated my installation of Silverlight to 4.0)
  • Created using C# 4.0
  • Please explain as if you talking to a web developer and not a proper programming lol!

Below is the code - it should return the XML from the wow armoury.

private void button7_Click(object sender, RoutedEventArgs e)
{
   // URL for armoury lookup
                string url = @"http://eu.wowarmory.com/guild-info.xml?r=Eonar&n=Gifted and Talented";

                // Create the web request
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);

                // Set the user agent so we are returned XML and not HTML
                //httpWebRequest.Headers["User-Agent"] = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)";

                // Not sure about this dispatcher thing - it's late so i have started to guess.
                Dispatcher.BeginInvoke(delegate()
                {
                    // Call asyncronously
                    IAsyncResult asyncResult = httpWebRequest.BeginGetResponse(ReqCallback, httpWebRequest);

                    // End the response and use the result
                    using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.EndGetResponse(asyncResult))
                    {
                        // Load an XML document from a stream
                        XDocument x = XDocument.Load(httpWebResponse.GetResponseStream());

                        // Basic function that will use LINQ to XML to get the list of characters.
                        ShowGuildies(x);
                    }
                });
            }

            private void ReqCallback(IAsyncResult asynchronousResult)
            {
                // Not sure what to do here - maybe update the interface?
            }

Really hope someone out there can help me!

Thanks mucho! Dan.

PS Yes, I have noticed the irony in the name of the guild :)

Was it helpful?

Solution

First, Dispatcher.BeginInvoke is only needed when you're on another thread than the UI thread (where everything silverlight/WPF related happens). On a click event, you're already in the UI thread so there's no need to call it.

Second, BeginGetResponse is an asynchronous operation so when it has finished, it will call a callback function on another thread, here ReqCallback. It's in this method that you can call EndGetResponse. This pattern applies to every BeginX/EndX you'll find in the framework.

However, since you're in another thread, you'll need to use BeginInvoke to dispatch a method back to the UI thread.

The code will look like this:

private void button7_Click(object sender, RoutedEventArgs e) {
    string url = @"http://eu.wowarmory.com/guild-info.xml?r=Eonar&n=Gifted and Talented";
    HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create(url);
    httpWebRequest.BeginGetResponse(ReqCallback, httpWebRequest);
}

private void ReqCallback(IAsyncResult asyncResult)
{
    HttpWebRequest httpWebRequest = (HttpWebRequest) asyncResult.AsyncState;
    using (HttpWebResponse httpWebResponse = (HttpWebResponse) httpWebRequest.EndGetResponse(asyncResult))
    {
        XDocument x = XDocument.Load(httpWebResponse.GetResponseStream());
        Dispatcher.BeginInvoke((Action) (() => ShowGuildies(x)));
    }
}

Note that you can also process the XML in the thread and use the dispatcher only to send back guildies to the UI, to avoid freezing the UI if the XML is very long to parse (shouldn't be the case).

Edit: Corrected the code. You only have to implement ShowGuildies. Regarding the internet connectivity and delays, since the operation occurs in another thread the UI won't freeze. You might consider showing a loading animation or something though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top