Source
As an example of how leveraging Soapi.CS 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
// https://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
}
}