###Source

As an example of how leveraging [Soapi.CS][1] and the reusable controls in Soapi.Contrib.Silverlight can increase productivity when writing code against the API, I include the source code for the Soapi.Explore Silverlight application.


    //  
    //  Project: SOAPI
    //  http://soapics.codeplex.com
    //  http://stackapps.com/questions/386
    //  
    //  Copyright 2010, Sky Sanders
    //  Licensed under the GPL Version 2 license.
    //  http://soapics.codeplex.com/license
    //  
    //  Date: Aug 12 2010 
    //  API ver 1.0 rev 2010.0709.04
    //  
    
    #region
    
    using System;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Windows;
    using System.Windows.Controls;
    using Amp.Controls.MouseWheel;
    using Soapi;
    using Soapi.Contrib.Controls;
    using Soapi.Domain;
    using Soapi.Net;
    using Soapi.Parameters;
    using Soapi.Routes;
    
    #endregion
    
    namespace Explore
    {
        public partial class MainPage
        {
            #region Constants
    
            private const string ApiKey = "qgAq_KfDu0KYzlNG-qaTuw";
    
            #endregion
    
            #region Fields
    
            private TextBlock _busyMessage;
    
            private bool _cancel;
    
            private Button _cancelButton;
    
            private ApiContext _context;
    
            #endregion
    
            #region Constructors
    
            public MainPage()
            {
                InitializeComponent();
                InitializeContext();
            }
    
            private void InitializeContext()
            {
                BusyIndicator.IsBusy = true;
                BusyIndicator.DisplayAfter = new TimeSpan(0, 0, 0, 0, 500);
                ScrollViewerMouseWheelSupport.Initialize(this);
                AccordionScroller.AddMouseWheelSupport();
                JsonOutputScroller.AddMouseWheelSupport();
                RequestCache.Instance.DefaultDuration = new TimeSpan(0, 0, 0, 1);
                _context = new ApiContext(ApiKey);
                _context.Initialized += ContextInitialized;
    
    
                _context.Initialize(true);
            }
    
            void ContextInitialized(object sender, EventArgs e)
            {
                Dispatcher.BeginInvoke(() =>
                    {
                        SitesComboBox.ItemsSource = _context.Sites;
                        SitesComboBox.SelectedIndex = 0;
    
                        // this is a total hack. need to use mvvm light and a command pattern.
    
                        WireUpRouteControl(AnswersById);
                        WireUpRouteControl(AnswersByIdComments);
                        WireUpRouteControl(Badges);
                        WireUpRouteControl(BadgesById);
                        WireUpRouteControl(BadgesName);
                        WireUpRouteControl(BadgesTags);
                        WireUpRouteControl(CommentsById);
                        WireUpRouteControl(PostsByIdComments);
                        WireUpRouteControl(Questions);
                        WireUpRouteControl(QuestionsById);
                        WireUpRouteControl(QuestionsByIdAnswers);
                        WireUpRouteControl(QuestionsByIdComments);
                        WireUpRouteControl(QuestionsByIdTimeline);
                        WireUpRouteControl(QuestionsUnanswered);
                        WireUpRouteControl(RevisionsById);
                        WireUpRouteControl(RevisionsByIdByRevisionGuid);
                        WireUpRouteControl(Search);
                        WireUpRouteControl(Stats);
                        WireUpRouteControl(Tags);
                        WireUpRouteControl(Users);
                        WireUpRouteControl(UsersById);
                        WireUpRouteControl(UsersByIdAnswers);
                        WireUpRouteControl(UsersByIdBadges);
                        WireUpRouteControl(UsersByIdComments);
                        WireUpRouteControl(UsersByIdCommentsTo);
                        WireUpRouteControl(UsersByIdFavorites);
                        WireUpRouteControl(UsersByIdMentioned);
                        WireUpRouteControl(UsersByIdQuestions);
                        WireUpRouteControl(UsersByIdReputation);
                        WireUpRouteControl(UsersByIdTags);
                        WireUpRouteControl(UsersByIdTimeline);
                        WireUpRouteControl(UsersModerators);
                        WireUpRouteControl(Sites);
                        WireUpRouteControl(UsersByIdAssociated);
                        BusyIndicator.IsBusy = false;
                    });
            }
    
            #endregion
    
            #region Private Methods
    
            private void BusyMessageLoaded(object sender, RoutedEventArgs e)
            {
                _busyMessage = (TextBlock)sender;
            }
    
            private void CancelButtonClick(object sender, RoutedEventArgs e)
            {
                _cancel = true;
                _cancelButton.IsEnabled = false;
            }
    
            private void CancelButtonLoaded(object sender, RoutedEventArgs e)
            {
                _cancelButton = (Button)sender;
            }
    
            private void SetJsonText(string value, bool scroll)
            {
                JsonOutput.Text += value;
                if (scroll)
                {
    
                    try
                    {
                        JsonOutput.SelectionStart = JsonOutput.Text.LastIndexOf(Environment.NewLine);
                        JsonOutput.SelectionStart = JsonOutput.Text.LastIndexOf(Environment.NewLine, JsonOutput.SelectionStart);
                        JsonOutput.SelectionLength = 0;
                    }
                    catch
                    {
                    }
                }
    
            }
            private void SetUrl(IRoute route)
            {
                var url = Regex.Replace(route.RequestUri.AbsoluteUri, @"(\?|&)key=" + ApiKey, "");
                QueryUrl.Content = url;
                QueryUrl.NavigateUri = new Uri(url);
            }
    
            private void WireUpRouteControl(ParametersControl ctrl)
            {
    
    
                ctrl.ExecuteQuery += (s, e) =>
                    {
    
                        IParameter parameters = ctrl.Parameters;
                        try
                        {
                            parameters.Validate();
                        }
                        catch (Exception ex)
                        {
                            Dispatcher.BeginInvoke(() =>
                                MessageBox.Show(ex.Message));
    
                            return;
                        }
    
                        var site = ((Site)SitesComboBox.SelectedItem);
                        var route = site.RouteFactory.GetRouteByPath(ctrl.Route);
                        route.Parameters = parameters;
                        var pagedRoute = route as IPagedRoute;
                        if (pagedRoute != null)
                        {
                            
                            var pageParameters = (IPageParameter)parameters;
                            if (pageParameters.PageCount < 1 || pageParameters.PageCount > 9)
                            {
                                var result =
                                    MessageBox.Show(
                                        "Large result sets may be hard for your browser to handle.\r\nAre you sure you want to continue?"
                                        +"\r\n\r\nNote: I am working on a virtualized textbox\r\nthat will relieve this issue."
                                        , "Large Result Warning", MessageBoxButton.OKCancel);
                                if (result == MessageBoxResult.Cancel)
                                {
                                    return;
                                }
                            }
    
                        }
    
    
                        Dispatcher.BeginInvoke(() =>
                            {
                                _cancelButton.IsEnabled = true;
                                BusyIndicator.IsBusy = true;
                                _busyMessage.Text = String.Format("Initializing request");
                                JsonOutput.Text = string.Empty;
                            });
    
    
    
                        ThreadPool.QueueUserWorkItem(ignored =>
                            {
    
                                if (pagedRoute != null)
                                {
                                    pagedRoute.PageRecieved += (ss, ee) =>
                                        {
                                            Dispatcher.BeginInvoke(() =>
                                                {
                                                    _busyMessage.Text = String.Format("Fetched Page {0} of {1}", ee.CurrentPage, ee.TotalPages);
                                                    string value = "\r\n" + ee.Result.ResponseText;
    
                                                    SetJsonText(value, false);
                                                    SetUrl(route);
                                                });
                                            ee.Cancel = _cancel;
                                        };
                                }
                                try
                                {
    #pragma warning disable 168
                                    // need this to build structured response
                                    var response = route.GetResponse();
    #pragma warning restore 168
                                    // todo - structured output of response
                                    if (pagedRoute == null)
                                    {
                                        Dispatcher.BeginInvoke(() =>
                                            {
                                                SetJsonText(route.ResponseText, false);
                                                SetUrl(route);
                                            });
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Dispatcher.BeginInvoke(() =>
                                        {
                                            SetJsonText("\r\n--------------------------------------------------"
                                                + "\r\nERROR:"
                                                + "\r\n--------------------------------------------------\r\n"
                                                + ex.Message
                                                + "\r\n--------------------------------------------------\r\n"
                                                + ex
                                                + "\r\n--------------------------------------------------", true);
                                            SetUrl(route);
                                        });
                                }
                                finally
                                {
                                    Dispatcher.BeginInvoke(() =>
                                        {
                                            _cancel = false;
                                            BusyIndicator.IsBusy = false;
                                        });
                                }
                            });
                    };
            }
    
            #endregion
    
        }
    }


  [1]: http://stackapps.com/questions/386/