Introduction
This app provides a systematic approach to both public and elected officials to interact and work on top public issues which is raised by public.
Category : Education(Public Awareness) on Tablet Platform.
Background
How many people know their representative for council/state/congress? How many local issues get their way to the most relevant elected official?
How do you know the status of the most relevant issues raised?
To answer this "Know your representative" app is being created to introduce your elected official to every one. It is a multi-device app geared to increase accountability of elected officials which in turn will promote voter engagement.
App Features
Users can view and contact their official based on geo location and raise their issues
- Users can view the contact information of elected officials based on GEO location.
- Users can raise their issues to the respective elected official and support the most significant issues.
- Official can respond to users and resolve the issues and update the status on the app.
- Other public users can add their support to prioritize the high priority items by raising their support using the voting button.
- Each issue can be discussed in multiple responses.
Development Approach
Visual Studio 2012 will be used to code (C#) and design(XAML) the app pages. Windows Azure will be used as back-end to store User registration,
issues and responses and votings, Azavea-Cicero GIS API will used to bring the elected officials information using the Geo Location. The final version of app will be available in both Tablet and Windows Phone 8. Portable class libraries will be used to share the objects between Tablet and windows phone 8 app.
Restful client will be used to fetch legislative official details.
Notification(Push) will be send whenever issue raised/updated/addressed - Still doing research for cheaper service.
Technologies
- Visual Studio 2012, C#, XAML will be developed to design app pages and UI coding.
- Windows SQL Azure and Mobile Services will be used to store forum data.
Points of Interest
GPS will be used to detect GeoLocation to load local elected officials.
Screenshot
Some of the work in progress screenshots of Windows phone version.
Officials Class Diagram
Using the code
The below Generic
AzureHelper
class connects with remote database to save and fetch data
public class AzureHelper<T>
where T : class
{
internal static MobileServiceClient MobileService =
new MobileServiceClient("AZURE DB URL", "AZUREKEY");
private MobileServiceCollection<T, T> items;
private IMobileServiceTable<T> currentTable = MobileService.GetTable<T>();
public async Task<T> Save(T instance)
{
await currentTable.InsertAsync(instance);
return instance;
}
public async Task<T> Update(T instance)
{
await currentTable.UpdateAsync(instance);
return instance;
}
public async void Delete(T instance)
{
await currentTable.DeleteAsync(instance);
}
public async void GetList()
{
items = await currentTable
.ToCollectionAsync();
}
public async void GetList(Expression<Func<T, bool>> predicate)
{
items = await currentTable
.Where(predicate)
.ToCollectionAsync();
}
public MobileServiceCollection<T, T> ListItems
{
get
{
return items;
}
}
}
The below code makes Rest calls to get official information using Azevia API
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using RestSharp;
using KnowYourCouncil;
namespace KnowYourCouncil
{
public class RestHelper
{
private string _username;
private string _password;
string base_url = "http://cicero.azavea.com/v3.1/";
string ApiKey = "";
public RestHelper()
{
_username = "";
_password = "";
_client = new RestClient(base_url);
}
public RestHelper(string username, string password)
{
_username = username;
_password = password;
_client = new RestClient(base_url);
}
private TimeSpan _opTimeOut = TimeSpan.FromSeconds(30);
private RestClient _client;
private class RestAsyncResult<T> : IAsyncResult where T : class
{
public object AsyncState
{
get;
set;
}
public WaitHandle AsyncWaitHandle
{
get;
set;
}
public bool CompletedSynchronously
{
get;
set;
}
public bool IsCompleted
{
get;
set;
}
public T Value { get; set; }
}
private async Task<T> ExecuteAsync<T>(RestRequest request, IObserver<string> progress) where T : class
{
var tcs = new TaskCompletionSource<T>();
_client.ExecuteAsync(request, resp =>
{
if (resp.StatusCode != System.Net.HttpStatusCode.OK)
{
var ex = new RestInvokeException((int)resp.StatusCode, resp.StatusDescription);
if (progress != null)
progress.OnError(ex);
tcs.SetException(ex);
}
var value = JsonConvert.DeserializeObject<T>(resp.Content);
if (value == null)
{
var ex = new RestInvokeException(100, "value.ErrorDesc");
if (progress != null)
progress.OnError(ex);
tcs.SetException(ex);
}
else
tcs.SetResult(value);
});
return await tcs.Task;
}
public async Task<Token> getToken(string userId, IObserver<string> progress)
{
var url = "token/new.json";
var request = new RestRequest(url, Method.POST);
progress.OnNext("Getting token");
return (await ExecuteAsync<Token>(request, progress));
}
public async Task<RootObject> getofficials(Token token, string location, IObserver<string> progress)
{
var url = "official?order=district&sort=asc&f=JSON&search_loc=" +
location + "&user=" + token.user + "&token=" + token.token;
url = Uri.EscapeUriString(url);
var request = new RestRequest(url, Method.GET);
progress.OnNext("Getting token");
return (await ExecuteAsync<RootObject>(request, progress));
}
}
public class RestInvokeException : Exception
{
private int _errorMsg;
private string _desc;
public RestInvokeException(int errorCode, string desc)
: base(desc)
{
_errorMsg = errorCode;
_desc = desc;
}
}
}
History
Version 1.0 - Draft.
Version 1.1 - Updated with platform and category along with development approach.