Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
namespace MyNamespace
{
[ServiceConfiguration(typeof(ISelectionQuery))]
public class GoogleMapsGeocoding : ISelectionQuery
{
private readonly string _googleApiKey;
public GoogleMapsGeocoding()
{
//get key from config
_googleApiKey = ConfigurationManager.AppSettings["GoogleGeocodingApiKey"];
}
//Will be called when the editor types something in the selection editor.
public IEnumerable<ISelectItem> GetItems(string query)
{
if (IsCoordinate(query))
{
//return value if it is coordinates
var list = new List<ISelectItem> { new SelectItem() { Text = query, Value = query } };
return list;
}
if (query.Length < 5) //don't waste API quota on short query
{
return null;
}
var items = GetResultFromGoogle(query);
return EditorFriendlyItems(items, query);
}
//Will be called when initializing an editor with an existing value.
public ISelectItem GetItemByValue(string value)
{
//just return the saved value
return new SelectItem { Text = value, Value = value };
}
private IEnumerable<ISelectItem> GetResultFromGoogle(string query)
{
if (_googleApiKey.IsNullOrEmpty())
{
var list = new List<ISelectItem>();
list.Add(new SelectItem() { Text = "Error: missing Google API key", Value = null });
return list;
}
var apiUrl = $"https://maps.googleapis.com/maps/api/geocode/json?address={query}&key={_googleApiKey}";
var webClient = new WebClient { Encoding = Encoding.UTF8 };
var json = (JObject)JsonConvert.DeserializeObject(webClient.DownloadString(apiUrl));
var results = json["results"].Select(r => new SelectItem()
{
Text = $"{r["formatted_address"].ToString()} ({r["geometry"]["location"]["lat"].ToString()} {r["geometry"]["location"]["lng"].ToString()})",
Value = $"{r["geometry"]["location"]["lat"].ToString()} {r["geometry"]["location"]["lng"].ToString()}"
});
return results;
}
//If items returned by Google doesn't start with the query, add a dummy item to make a better experience for the editor.
private IEnumerable<ISelectItem> EditorFriendlyItems(IEnumerable<ISelectItem> items, string query)
{
var itemsList = items.ToList();
if (itemsList.Any())
{
if (!itemsList.Any(i => i.Text.StartsWith(query, StringComparison.OrdinalIgnoreCase)))
{
itemsList.Insert(0, new SelectItem() { Text = query, Value = null });
}
}
return itemsList;
}
//Check if query is coordinates
private bool IsCoordinate(string query)
{
const string pattern = @"^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?)\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$";
var r = new Regex(pattern);
return r.Match(query).Success;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.