了解你的代表
此应用程序提供了一种系统化的方法,
介绍
这个应用程序为公众和民选官员提供了一个系统化的方法,以便他们互动并解决公众提出的重要公共问题。
类别:平板电脑平台上的教育(公众意识)。
背景
有多少人知道他们所在议会/州/国会的代表?有多少地方问题能够传达给最相关的民选官员?
您如何了解已提出问题的最新进展?
为了回答这些问题,正在开发“了解您的代表”应用程序,旨在将您的民选官员介绍给每一个人。这是一个多设备应用程序,旨在提高民选官员的责任感,从而促进选民参与。
应用程序功能
用户可以根据地理位置查看并联系他们的官员,并提出他们的问题。
- 用户可以查看民选官员的联系信息,基于地理位置。
- 用户可以向相应的民选官员提出问题,并支持最重要的议题。
- 官员可以回复用户,解决问题,并在应用程序上更新状态。
- 其他公众用户可以通过投票按钮表达他们对优先事项的支持,从而优先考虑高优先级事项。
- 每个问题可以在多个回复中进行讨论。
开发方法
将使用 Visual Studio 2012 对应用程序页面进行编码(C#)和设计(XAML)。Windows Azure 将用作后端,以存储用户注册、问题、回复和投票。Azavea-Cicero GIS API 将用于使用地理位置获取民选官员的信息。应用程序的最终版本将同时在平板电脑和 Windows Phone 8 上可用。可移植类库将用于在平板电脑和 Windows Phone 8 应用程序之间共享对象。
将使用 Restful 客户端获取立法官员的详细信息。
当问题提出/更新/解决时,将发送通知(推送) - 仍在研究更便宜的服务。
技术
- Visual Studio 2012、C#、XAML 将用于设计应用程序页面和 UI 编码。
- Windows SQL Azure 和 Mobile Services 将用于存储论坛数据。
关注点
GPS 将用于检测地理位置,以加载当地民选官员。
屏幕截图
一些正在进行中的 Windows Phone 版本截图。
官员类图
使用代码
下面的通用 AzureHelper
类连接到远程数据库以保存和获取数据
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;
}
}
}
下面的代码使用 Azevia API 发出 Rest 调用以获取官员信息
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;
//+"&district_type=NATIONAL_EXEC";
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;
}
}
}
历史
版本 1.0 - 草稿。
版本 1.1 - 更新了平台和类别以及开发方法。