次の方法で共有


HttpWebRequest Fundamentals - Windows Phone Services Consumption - Part 2

wp7services-httpwebrequest

This is the second part of our "Consuming Services with Windows Phone" series. Previously we covered using WebClient to pull raw HTML from the web. WebClient isn't the most optimal solution for all things webbie, so let's explore the daddy of WebClient, HttpWebRequest.

HttpWebRequest is a lower-level abstraction of the http protocol than WebClient. WebClient actually wraps HttpWebRequest.  HttpWebRequest allows for more direct access of HTTP aspects which WebClient does not.  Things such as the Accept header, Content Length and Type, direct access to Cookies and the User Agent.

WebRequest also returns on a background thread, allowing a program to parse and process results as they are returned without crunching down the main UI. When a program wishes to update the main UI  in a callback from a HttpWebRequest, the program must use the Dispatcher to process user interface updates, since the WebRequest callback is on the background thread.

If you wish to explore the basics of a HttpWebRequest for scraping a website, walk through the steps below.

Step1: Create a new Windows Phone Portrait Project
Step2: Modify MainPage.xaml, change the ContentPanel from a Grid to StackPanel, and make it match what's below.

         <StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Button Content="Call HttpWebRequest" Width="250" Click="Button_Click" />
            <TextBlock Text="HttpWebRequest Target:" Style="{StaticResource PhoneTextNormalStyle}" Foreground="{StaticResource PhoneAccentBrush}" />
            <TextBlock Text="https://msdn.microsoft.com" TextWrapping="Wrap" Margin="20,0,0,0" x:Name="TextBlockTargetUri" />

            <TextBlock Text="Elapsed Time:" Style="{StaticResource PhoneTextNormalStyle}" Foreground="{StaticResource PhoneAccentBrush}" />
            <TextBlock Text="tbd" TextWrapping="Wrap" Margin="20,0,0,0" x:Name="TextBlockElapsedTime" />

            <TextBlock Text="HttpWebRequest Call Results:" Style="{StaticResource PhoneTextNormalStyle}" Foreground="{StaticResource PhoneAccentBrush}" />
            <TextBlock x:Name="TextBlockResults" Text="results go here" Margin="20,0,0,0" TextWrapping="Wrap"/>
        </StackPanel>

Next the code. Match up the steps given to the code block below.

Step3: Wire up the Button_Click handler.  In the handler we setup a HttpWebRequest against our target Uri, then initiate the request with a callback targeted towards our "ReadRequestCallback" handler.
Step4:  Code up our handler for the WebRequestCallback. First we'll create a new request instance. Then initialize an HttpWebResponse we can use to pull the results down from the web. After that we'll use a StreamReader to read the data. Once the data is down, since HttpWebRequest returns on a non-UI thread, we just use Dispatcher.Update to show the data in the UI.  Run the program and you should see results similar to what's above.

     public partial class HttpWebRequestPage : PhoneApplicationPage
    {
        public HttpWebRequestPage()
        {
            InitializeComponent();
        }
  // STEP3 STEP3 STEP3
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            System.Uri targetUri = new System.Uri(TextBlockTargetUri.Text);
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(targetUri);
            request.BeginGetResponse(new AsyncCallback(ReadWebRequestCallback), request); 
        }

    // STEP4 STEP4 STEP4
        private void ReadWebRequestCallback(IAsyncResult callbackResult)
        {
            HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.EndGetResponse(callbackResult);

            using (StreamReader httpwebStreamReader = new StreamReader(myResponse.GetResponseStream()))
            {
                string results = httpwebStreamReader.ReadToEnd();
                //TextBlockResults.Text = results; //-- on another thread!
                Dispatcher.BeginInvoke(() => TextBlockResults.Text = results);
            }
            myResponse.Close();
        }
    }

Try this. Comment out the Dispatcher.BeginInvoke line and uncomment the TextBlockResults.Text line. Run the program. Now the background thread the callback is running on is trying to update the UI directly. Directly hitting the UI from a background thread results in an System.UnauthorizedAccessException: Invalid cross-thread access. Something to watch out for, definitely!

All in all, HttpWebRequest provides a greater flexibility than WebClient by being able to address http headers more directly. Since the thread returns on a non-UI thread, there's also a greater opportunity to boost performance and give a better user experience. The pattern isn't as simple as WebClient, but its not too onerous either.

I'll have another post up soon with some service consumption examples against some real world endpoints. See you then.

Consuming Windows Phone Services Series
Part 1 - Web Client Basics - https://blogs.msdn.com/b/devfish/archive/2011/04/06/webclient-windows-phone-services-consumption-part-1.aspx
Part 2 - HttpWebRequest Fundamentals - https://blogs.msdn.com/b/devfish/archive/2011/04/07/httpwebrequest-fundamentals-windows-phone-services-consumption-part-2.aspx
Part 3 - Parsing REST based XML Data - Part A - Single Result - https://blogs.msdn.com/b/devfish/archive/2011/05/05/consuming-geocode-yhoo-api-via-rest-windows-phone-services-consumption-part-3.aspx
Part 4 - Parsing REST based XML Data - Part B - Multiple Results - https://blogs.msdn.com/b/devfish/archive/2011/05/10/consuming-geocode-yhoo-api-via-rest-dealing-with-multiple-results-part-4.aspx

Comments

  • Anonymous
    April 10, 2011
    good stuff Joe.  keep them coming.

  • Anonymous
    January 01, 2012
    Hi Joe, thank you for an excellent article. All the example in HttpWebRequest article on msdn are wrong. Finally I saw a simple and working example on yours.

  • Anonymous
    January 31, 2013
    Hi nice tutorial it worked for me when I am using get request. When I tried to do http post method it throws an error "The remote server returned an error : Not found" Can you help me in this regards can you post the code for http post method. By the way I am working on Windows phone 8 simulator.

  • Anonymous
    February 01, 2013
    @bhanushali - send me an email at jhealy@microsoft.com - lets touch base on this....

  • Anonymous
    October 03, 2013
    to: Bhanushali Ashwin N. "The remote server returned an error : Not found" Make sure that there is a internet connection in your emulator.