Find SuburbName from latlong or location

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
4
down vote

favorite
2












I have create one class and interface for finding SuburbName based on Location or LatLong coordinates.



My interface



public interface IGeoCodeService

string GetSuburbName(double latitude, double longitude);
string GetSuburbName(string location);
string GetGoogleStaticMapImageUrl(string location);



My Class



public class GeoCodeService : IGeoCodeService

private static readonly string GoogleApiKey = "*****MyAPI KEY*****";
private static readonly string GoogleStaticMapUrl = "http://maps.googleapis.com/maps/api/staticmap";

public string GetSuburbName(string location)

if (!string.IsNullOrEmpty(location))

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("address", location);
param.Add("components", "country:AU");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);
var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);


return string.Empty;


public string GetSuburbName(double latitude, double longitude)

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("latlng", $"latitude,longitude");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);

var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);



private string FindSuburbName(GeoCodeResponse result)
result.results != null && result.results.Count > 0)

var addressObj = result.results.FirstOrDefault();
if (addressObj != null)

var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();
if (component != null)

return component.LongName;



return response;


public string GetGoogleStaticMapImageUrl(string location)

return $"GoogleStaticMapUrl?size=350x200&markers=location";




And lastly the GeoCodeResponse class to store response from the google api call.



public class GeoCodeResponse

[JsonProperty("results")]
public List<Results> results get; set;
[JsonProperty("status")]
public string status get; set;


public class Results

public Results()

AddressComponents = new List<AddressComponent>();

[JsonProperty("address_components")]
public List<AddressComponent> AddressComponents get; set;

public class AddressComponent

[JsonProperty("long_name")]
public string LongName get; set;
[JsonProperty("short_name")]
public string ShortName get; set;
[JsonProperty("types")]
public string Types get; set;



Can you please suggest me if what I have implemented is right or require any change. Your help will improve my code quality.



The HttpClientService class is used for call api










share|improve this question























  • Please include the HttpClientService class even if it's already been reviewed. You never know what someone else can find :)
    – IEatBagels
    Aug 23 at 14:42














up vote
4
down vote

favorite
2












I have create one class and interface for finding SuburbName based on Location or LatLong coordinates.



My interface



public interface IGeoCodeService

string GetSuburbName(double latitude, double longitude);
string GetSuburbName(string location);
string GetGoogleStaticMapImageUrl(string location);



My Class



public class GeoCodeService : IGeoCodeService

private static readonly string GoogleApiKey = "*****MyAPI KEY*****";
private static readonly string GoogleStaticMapUrl = "http://maps.googleapis.com/maps/api/staticmap";

public string GetSuburbName(string location)

if (!string.IsNullOrEmpty(location))

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("address", location);
param.Add("components", "country:AU");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);
var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);


return string.Empty;


public string GetSuburbName(double latitude, double longitude)

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("latlng", $"latitude,longitude");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);

var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);



private string FindSuburbName(GeoCodeResponse result)
result.results != null && result.results.Count > 0)

var addressObj = result.results.FirstOrDefault();
if (addressObj != null)

var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();
if (component != null)

return component.LongName;



return response;


public string GetGoogleStaticMapImageUrl(string location)

return $"GoogleStaticMapUrl?size=350x200&markers=location";




And lastly the GeoCodeResponse class to store response from the google api call.



public class GeoCodeResponse

[JsonProperty("results")]
public List<Results> results get; set;
[JsonProperty("status")]
public string status get; set;


public class Results

public Results()

AddressComponents = new List<AddressComponent>();

[JsonProperty("address_components")]
public List<AddressComponent> AddressComponents get; set;

public class AddressComponent

[JsonProperty("long_name")]
public string LongName get; set;
[JsonProperty("short_name")]
public string ShortName get; set;
[JsonProperty("types")]
public string Types get; set;



Can you please suggest me if what I have implemented is right or require any change. Your help will improve my code quality.



The HttpClientService class is used for call api










share|improve this question























  • Please include the HttpClientService class even if it's already been reviewed. You never know what someone else can find :)
    – IEatBagels
    Aug 23 at 14:42












up vote
4
down vote

favorite
2









up vote
4
down vote

favorite
2






2





I have create one class and interface for finding SuburbName based on Location or LatLong coordinates.



My interface



public interface IGeoCodeService

string GetSuburbName(double latitude, double longitude);
string GetSuburbName(string location);
string GetGoogleStaticMapImageUrl(string location);



My Class



public class GeoCodeService : IGeoCodeService

private static readonly string GoogleApiKey = "*****MyAPI KEY*****";
private static readonly string GoogleStaticMapUrl = "http://maps.googleapis.com/maps/api/staticmap";

public string GetSuburbName(string location)

if (!string.IsNullOrEmpty(location))

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("address", location);
param.Add("components", "country:AU");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);
var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);


return string.Empty;


public string GetSuburbName(double latitude, double longitude)

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("latlng", $"latitude,longitude");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);

var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);



private string FindSuburbName(GeoCodeResponse result)
result.results != null && result.results.Count > 0)

var addressObj = result.results.FirstOrDefault();
if (addressObj != null)

var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();
if (component != null)

return component.LongName;



return response;


public string GetGoogleStaticMapImageUrl(string location)

return $"GoogleStaticMapUrl?size=350x200&markers=location";




And lastly the GeoCodeResponse class to store response from the google api call.



public class GeoCodeResponse

[JsonProperty("results")]
public List<Results> results get; set;
[JsonProperty("status")]
public string status get; set;


public class Results

public Results()

AddressComponents = new List<AddressComponent>();

[JsonProperty("address_components")]
public List<AddressComponent> AddressComponents get; set;

public class AddressComponent

[JsonProperty("long_name")]
public string LongName get; set;
[JsonProperty("short_name")]
public string ShortName get; set;
[JsonProperty("types")]
public string Types get; set;



Can you please suggest me if what I have implemented is right or require any change. Your help will improve my code quality.



The HttpClientService class is used for call api










share|improve this question















I have create one class and interface for finding SuburbName based on Location or LatLong coordinates.



My interface



public interface IGeoCodeService

string GetSuburbName(double latitude, double longitude);
string GetSuburbName(string location);
string GetGoogleStaticMapImageUrl(string location);



My Class



public class GeoCodeService : IGeoCodeService

private static readonly string GoogleApiKey = "*****MyAPI KEY*****";
private static readonly string GoogleStaticMapUrl = "http://maps.googleapis.com/maps/api/staticmap";

public string GetSuburbName(string location)

if (!string.IsNullOrEmpty(location))

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("address", location);
param.Add("components", "country:AU");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);
var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);


return string.Empty;


public string GetSuburbName(double latitude, double longitude)

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("latlng", $"latitude,longitude");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);

var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);



private string FindSuburbName(GeoCodeResponse result)
result.results != null && result.results.Count > 0)

var addressObj = result.results.FirstOrDefault();
if (addressObj != null)

var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();
if (component != null)

return component.LongName;



return response;


public string GetGoogleStaticMapImageUrl(string location)

return $"GoogleStaticMapUrl?size=350x200&markers=location";




And lastly the GeoCodeResponse class to store response from the google api call.



public class GeoCodeResponse

[JsonProperty("results")]
public List<Results> results get; set;
[JsonProperty("status")]
public string status get; set;


public class Results

public Results()

AddressComponents = new List<AddressComponent>();

[JsonProperty("address_components")]
public List<AddressComponent> AddressComponents get; set;

public class AddressComponent

[JsonProperty("long_name")]
public string LongName get; set;
[JsonProperty("short_name")]
public string ShortName get; set;
[JsonProperty("types")]
public string Types get; set;



Can you please suggest me if what I have implemented is right or require any change. Your help will improve my code quality.



The HttpClientService class is used for call api







c# beginner object-oriented geospatial google-maps






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 23 at 16:55









200_success

124k14144401




124k14144401










asked Aug 23 at 11:32









Lalji Dhameliya

1747




1747











  • Please include the HttpClientService class even if it's already been reviewed. You never know what someone else can find :)
    – IEatBagels
    Aug 23 at 14:42
















  • Please include the HttpClientService class even if it's already been reviewed. You never know what someone else can find :)
    – IEatBagels
    Aug 23 at 14:42















Please include the HttpClientService class even if it's already been reviewed. You never know what someone else can find :)
– IEatBagels
Aug 23 at 14:42




Please include the HttpClientService class even if it's already been reviewed. You never know what someone else can find :)
– IEatBagels
Aug 23 at 14:42










2 Answers
2






active

oldest

votes

















up vote
3
down vote













There are lots of nice things in your code for a beginner, congratulations.



Configuration file



Right now, you obfuscated your API key so that we don't have it, that's logical.



But it shouldn't be hardcoded in your code either. This is a bad practice for multiple reasons



  1. What if I want to use your code? I'd be using you API key, this is danngerous. I should be able to set mine without having to recompile

  2. Your API key would be stored in your source control (if you have one) and could be accessible to anyone decompiling your code. If there are costs related to Maps API, things could go wrong very quickly.

An API key should always be in some sort of configuration file. Either an app.config, web.config or some other external configuration manager.



Code repetition



Between the two overrides of GetSuburbName, there are parts of code that are duplicated. You did a good job of extracting FindSuburbName(GeoCodeResponse result) as a private method though.



I would go a little further. The only difference between the two methods is the parameters list so, as an example, I'd change :



if (!string.IsNullOrEmpty(location))

using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

var param = new Dictionary<string, string>();
param.Add("address", location);
param.Add("components", "country:AU");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);
var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
return FindSuburbName(apiResult);


return string.Empty;


To :



if (!string.IsNullOrEmpty(location))

var param = new Dictionary<string, string>();
param.Add("address", location);
param.Add("components", "country:AU");
param.Add("result_type", "locality");
param.Add("key", GoogleApiKey);

return FindSuburbName(param);

return string.Empty;


Then, you could have your API call in the common method.



C# tips



You can use the Dictionary Initializer if you have a recent version of C#.



As an example :



var param = new Dictionary<string, string>();
param.Add("address", location);


becomes :



var param = new Dictionary<string, string>

"address", location,
//etc



Regarding this line :



var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();


There is an override for FirstOrDefaut that takes a Predicate (a condition), which means your code could be :



var component = addressObj.AddressComponents.FirstOrDefault(x => x.Types.Contains("locality"));


@FabienH. @FabianH. already pointed out the other points I wanted to cover regarding C#.






share|improve this answer






















  • Nice Answer and thanks for mentioning my own. I even forgive you writing my name wrong :-)
    – Fabian H.
    Aug 23 at 14:49










  • @FabianH. Oops my bad, fixed :p
    – IEatBagels
    Aug 23 at 14:58

















up vote
2
down vote













I would reccomend using string.IsNullOrWhitespace(..) instead of string.IsNullOrEmpty(..), but this depends on how you call your method and what input is possible.
Also I prefer returning early, instead of having all my actual code in an if-block:



public string GetSuburbName(string location)

if (string.IsNullOrWhitespace(location))

return null; // or String.Empty

// your stuff



Regarding your FindSuburbName-Method: There are a LOT of redundant checks, that could be a lot more simplified. For example you check if Count > 0, then take the FirstOrDefault(), where First() would be enough, because you know there is at leat one, then you check if that result is not null. How could it be null?



One line version (for readability it would probably be best to do this in more lines, but this is just to show what is possible):



private string FindSuburbName(GeoCodeResponse result)

return result?.results?.FirstOrDefault()?.AddressComponents.FirstOrDefault(comp => comp.Types.Contains("locality"))?.LongName;



If you want to return string.Empty instead of null, just do ?? string.Empty at the end of that oneliner.



You could omit the constructor of you Results-class, if you do



public List<AddressComponent> AddressComponents get; set; = new List<AddressComponent>();


instead.






share|improve this answer




















    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f202299%2ffind-suburbname-from-latlong-or-location%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote













    There are lots of nice things in your code for a beginner, congratulations.



    Configuration file



    Right now, you obfuscated your API key so that we don't have it, that's logical.



    But it shouldn't be hardcoded in your code either. This is a bad practice for multiple reasons



    1. What if I want to use your code? I'd be using you API key, this is danngerous. I should be able to set mine without having to recompile

    2. Your API key would be stored in your source control (if you have one) and could be accessible to anyone decompiling your code. If there are costs related to Maps API, things could go wrong very quickly.

    An API key should always be in some sort of configuration file. Either an app.config, web.config or some other external configuration manager.



    Code repetition



    Between the two overrides of GetSuburbName, there are parts of code that are duplicated. You did a good job of extracting FindSuburbName(GeoCodeResponse result) as a private method though.



    I would go a little further. The only difference between the two methods is the parameters list so, as an example, I'd change :



    if (!string.IsNullOrEmpty(location))

    using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

    var param = new Dictionary<string, string>();
    param.Add("address", location);
    param.Add("components", "country:AU");
    param.Add("result_type", "locality");
    param.Add("key", GoogleApiKey);
    var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
    return FindSuburbName(apiResult);


    return string.Empty;


    To :



    if (!string.IsNullOrEmpty(location))

    var param = new Dictionary<string, string>();
    param.Add("address", location);
    param.Add("components", "country:AU");
    param.Add("result_type", "locality");
    param.Add("key", GoogleApiKey);

    return FindSuburbName(param);

    return string.Empty;


    Then, you could have your API call in the common method.



    C# tips



    You can use the Dictionary Initializer if you have a recent version of C#.



    As an example :



    var param = new Dictionary<string, string>();
    param.Add("address", location);


    becomes :



    var param = new Dictionary<string, string>

    "address", location,
    //etc



    Regarding this line :



    var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();


    There is an override for FirstOrDefaut that takes a Predicate (a condition), which means your code could be :



    var component = addressObj.AddressComponents.FirstOrDefault(x => x.Types.Contains("locality"));


    @FabienH. @FabianH. already pointed out the other points I wanted to cover regarding C#.






    share|improve this answer






















    • Nice Answer and thanks for mentioning my own. I even forgive you writing my name wrong :-)
      – Fabian H.
      Aug 23 at 14:49










    • @FabianH. Oops my bad, fixed :p
      – IEatBagels
      Aug 23 at 14:58














    up vote
    3
    down vote













    There are lots of nice things in your code for a beginner, congratulations.



    Configuration file



    Right now, you obfuscated your API key so that we don't have it, that's logical.



    But it shouldn't be hardcoded in your code either. This is a bad practice for multiple reasons



    1. What if I want to use your code? I'd be using you API key, this is danngerous. I should be able to set mine without having to recompile

    2. Your API key would be stored in your source control (if you have one) and could be accessible to anyone decompiling your code. If there are costs related to Maps API, things could go wrong very quickly.

    An API key should always be in some sort of configuration file. Either an app.config, web.config or some other external configuration manager.



    Code repetition



    Between the two overrides of GetSuburbName, there are parts of code that are duplicated. You did a good job of extracting FindSuburbName(GeoCodeResponse result) as a private method though.



    I would go a little further. The only difference between the two methods is the parameters list so, as an example, I'd change :



    if (!string.IsNullOrEmpty(location))

    using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

    var param = new Dictionary<string, string>();
    param.Add("address", location);
    param.Add("components", "country:AU");
    param.Add("result_type", "locality");
    param.Add("key", GoogleApiKey);
    var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
    return FindSuburbName(apiResult);


    return string.Empty;


    To :



    if (!string.IsNullOrEmpty(location))

    var param = new Dictionary<string, string>();
    param.Add("address", location);
    param.Add("components", "country:AU");
    param.Add("result_type", "locality");
    param.Add("key", GoogleApiKey);

    return FindSuburbName(param);

    return string.Empty;


    Then, you could have your API call in the common method.



    C# tips



    You can use the Dictionary Initializer if you have a recent version of C#.



    As an example :



    var param = new Dictionary<string, string>();
    param.Add("address", location);


    becomes :



    var param = new Dictionary<string, string>

    "address", location,
    //etc



    Regarding this line :



    var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();


    There is an override for FirstOrDefaut that takes a Predicate (a condition), which means your code could be :



    var component = addressObj.AddressComponents.FirstOrDefault(x => x.Types.Contains("locality"));


    @FabienH. @FabianH. already pointed out the other points I wanted to cover regarding C#.






    share|improve this answer






















    • Nice Answer and thanks for mentioning my own. I even forgive you writing my name wrong :-)
      – Fabian H.
      Aug 23 at 14:49










    • @FabianH. Oops my bad, fixed :p
      – IEatBagels
      Aug 23 at 14:58












    up vote
    3
    down vote










    up vote
    3
    down vote









    There are lots of nice things in your code for a beginner, congratulations.



    Configuration file



    Right now, you obfuscated your API key so that we don't have it, that's logical.



    But it shouldn't be hardcoded in your code either. This is a bad practice for multiple reasons



    1. What if I want to use your code? I'd be using you API key, this is danngerous. I should be able to set mine without having to recompile

    2. Your API key would be stored in your source control (if you have one) and could be accessible to anyone decompiling your code. If there are costs related to Maps API, things could go wrong very quickly.

    An API key should always be in some sort of configuration file. Either an app.config, web.config or some other external configuration manager.



    Code repetition



    Between the two overrides of GetSuburbName, there are parts of code that are duplicated. You did a good job of extracting FindSuburbName(GeoCodeResponse result) as a private method though.



    I would go a little further. The only difference between the two methods is the parameters list so, as an example, I'd change :



    if (!string.IsNullOrEmpty(location))

    using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

    var param = new Dictionary<string, string>();
    param.Add("address", location);
    param.Add("components", "country:AU");
    param.Add("result_type", "locality");
    param.Add("key", GoogleApiKey);
    var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
    return FindSuburbName(apiResult);


    return string.Empty;


    To :



    if (!string.IsNullOrEmpty(location))

    var param = new Dictionary<string, string>();
    param.Add("address", location);
    param.Add("components", "country:AU");
    param.Add("result_type", "locality");
    param.Add("key", GoogleApiKey);

    return FindSuburbName(param);

    return string.Empty;


    Then, you could have your API call in the common method.



    C# tips



    You can use the Dictionary Initializer if you have a recent version of C#.



    As an example :



    var param = new Dictionary<string, string>();
    param.Add("address", location);


    becomes :



    var param = new Dictionary<string, string>

    "address", location,
    //etc



    Regarding this line :



    var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();


    There is an override for FirstOrDefaut that takes a Predicate (a condition), which means your code could be :



    var component = addressObj.AddressComponents.FirstOrDefault(x => x.Types.Contains("locality"));


    @FabienH. @FabianH. already pointed out the other points I wanted to cover regarding C#.






    share|improve this answer














    There are lots of nice things in your code for a beginner, congratulations.



    Configuration file



    Right now, you obfuscated your API key so that we don't have it, that's logical.



    But it shouldn't be hardcoded in your code either. This is a bad practice for multiple reasons



    1. What if I want to use your code? I'd be using you API key, this is danngerous. I should be able to set mine without having to recompile

    2. Your API key would be stored in your source control (if you have one) and could be accessible to anyone decompiling your code. If there are costs related to Maps API, things could go wrong very quickly.

    An API key should always be in some sort of configuration file. Either an app.config, web.config or some other external configuration manager.



    Code repetition



    Between the two overrides of GetSuburbName, there are parts of code that are duplicated. You did a good job of extracting FindSuburbName(GeoCodeResponse result) as a private method though.



    I would go a little further. The only difference between the two methods is the parameters list so, as an example, I'd change :



    if (!string.IsNullOrEmpty(location))

    using (var clientService = new HttpClientService<GeoCodeResponse>("https://maps.googleapis.com"))

    var param = new Dictionary<string, string>();
    param.Add("address", location);
    param.Add("components", "country:AU");
    param.Add("result_type", "locality");
    param.Add("key", GoogleApiKey);
    var apiResult = clientService.GetAPI("maps/api/geocode/json", param);
    return FindSuburbName(apiResult);


    return string.Empty;


    To :



    if (!string.IsNullOrEmpty(location))

    var param = new Dictionary<string, string>();
    param.Add("address", location);
    param.Add("components", "country:AU");
    param.Add("result_type", "locality");
    param.Add("key", GoogleApiKey);

    return FindSuburbName(param);

    return string.Empty;


    Then, you could have your API call in the common method.



    C# tips



    You can use the Dictionary Initializer if you have a recent version of C#.



    As an example :



    var param = new Dictionary<string, string>();
    param.Add("address", location);


    becomes :



    var param = new Dictionary<string, string>

    "address", location,
    //etc



    Regarding this line :



    var component = addressObj.AddressComponents.Where(x => x.Types.Contains("locality")).FirstOrDefault();


    There is an override for FirstOrDefaut that takes a Predicate (a condition), which means your code could be :



    var component = addressObj.AddressComponents.FirstOrDefault(x => x.Types.Contains("locality"));


    @FabienH. @FabianH. already pointed out the other points I wanted to cover regarding C#.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Aug 23 at 14:57

























    answered Aug 23 at 14:38









    IEatBagels

    8,76623078




    8,76623078











    • Nice Answer and thanks for mentioning my own. I even forgive you writing my name wrong :-)
      – Fabian H.
      Aug 23 at 14:49










    • @FabianH. Oops my bad, fixed :p
      – IEatBagels
      Aug 23 at 14:58
















    • Nice Answer and thanks for mentioning my own. I even forgive you writing my name wrong :-)
      – Fabian H.
      Aug 23 at 14:49










    • @FabianH. Oops my bad, fixed :p
      – IEatBagels
      Aug 23 at 14:58















    Nice Answer and thanks for mentioning my own. I even forgive you writing my name wrong :-)
    – Fabian H.
    Aug 23 at 14:49




    Nice Answer and thanks for mentioning my own. I even forgive you writing my name wrong :-)
    – Fabian H.
    Aug 23 at 14:49












    @FabianH. Oops my bad, fixed :p
    – IEatBagels
    Aug 23 at 14:58




    @FabianH. Oops my bad, fixed :p
    – IEatBagels
    Aug 23 at 14:58












    up vote
    2
    down vote













    I would reccomend using string.IsNullOrWhitespace(..) instead of string.IsNullOrEmpty(..), but this depends on how you call your method and what input is possible.
    Also I prefer returning early, instead of having all my actual code in an if-block:



    public string GetSuburbName(string location)

    if (string.IsNullOrWhitespace(location))

    return null; // or String.Empty

    // your stuff



    Regarding your FindSuburbName-Method: There are a LOT of redundant checks, that could be a lot more simplified. For example you check if Count > 0, then take the FirstOrDefault(), where First() would be enough, because you know there is at leat one, then you check if that result is not null. How could it be null?



    One line version (for readability it would probably be best to do this in more lines, but this is just to show what is possible):



    private string FindSuburbName(GeoCodeResponse result)

    return result?.results?.FirstOrDefault()?.AddressComponents.FirstOrDefault(comp => comp.Types.Contains("locality"))?.LongName;



    If you want to return string.Empty instead of null, just do ?? string.Empty at the end of that oneliner.



    You could omit the constructor of you Results-class, if you do



    public List<AddressComponent> AddressComponents get; set; = new List<AddressComponent>();


    instead.






    share|improve this answer
























      up vote
      2
      down vote













      I would reccomend using string.IsNullOrWhitespace(..) instead of string.IsNullOrEmpty(..), but this depends on how you call your method and what input is possible.
      Also I prefer returning early, instead of having all my actual code in an if-block:



      public string GetSuburbName(string location)

      if (string.IsNullOrWhitespace(location))

      return null; // or String.Empty

      // your stuff



      Regarding your FindSuburbName-Method: There are a LOT of redundant checks, that could be a lot more simplified. For example you check if Count > 0, then take the FirstOrDefault(), where First() would be enough, because you know there is at leat one, then you check if that result is not null. How could it be null?



      One line version (for readability it would probably be best to do this in more lines, but this is just to show what is possible):



      private string FindSuburbName(GeoCodeResponse result)

      return result?.results?.FirstOrDefault()?.AddressComponents.FirstOrDefault(comp => comp.Types.Contains("locality"))?.LongName;



      If you want to return string.Empty instead of null, just do ?? string.Empty at the end of that oneliner.



      You could omit the constructor of you Results-class, if you do



      public List<AddressComponent> AddressComponents get; set; = new List<AddressComponent>();


      instead.






      share|improve this answer






















        up vote
        2
        down vote










        up vote
        2
        down vote









        I would reccomend using string.IsNullOrWhitespace(..) instead of string.IsNullOrEmpty(..), but this depends on how you call your method and what input is possible.
        Also I prefer returning early, instead of having all my actual code in an if-block:



        public string GetSuburbName(string location)

        if (string.IsNullOrWhitespace(location))

        return null; // or String.Empty

        // your stuff



        Regarding your FindSuburbName-Method: There are a LOT of redundant checks, that could be a lot more simplified. For example you check if Count > 0, then take the FirstOrDefault(), where First() would be enough, because you know there is at leat one, then you check if that result is not null. How could it be null?



        One line version (for readability it would probably be best to do this in more lines, but this is just to show what is possible):



        private string FindSuburbName(GeoCodeResponse result)

        return result?.results?.FirstOrDefault()?.AddressComponents.FirstOrDefault(comp => comp.Types.Contains("locality"))?.LongName;



        If you want to return string.Empty instead of null, just do ?? string.Empty at the end of that oneliner.



        You could omit the constructor of you Results-class, if you do



        public List<AddressComponent> AddressComponents get; set; = new List<AddressComponent>();


        instead.






        share|improve this answer












        I would reccomend using string.IsNullOrWhitespace(..) instead of string.IsNullOrEmpty(..), but this depends on how you call your method and what input is possible.
        Also I prefer returning early, instead of having all my actual code in an if-block:



        public string GetSuburbName(string location)

        if (string.IsNullOrWhitespace(location))

        return null; // or String.Empty

        // your stuff



        Regarding your FindSuburbName-Method: There are a LOT of redundant checks, that could be a lot more simplified. For example you check if Count > 0, then take the FirstOrDefault(), where First() would be enough, because you know there is at leat one, then you check if that result is not null. How could it be null?



        One line version (for readability it would probably be best to do this in more lines, but this is just to show what is possible):



        private string FindSuburbName(GeoCodeResponse result)

        return result?.results?.FirstOrDefault()?.AddressComponents.FirstOrDefault(comp => comp.Types.Contains("locality"))?.LongName;



        If you want to return string.Empty instead of null, just do ?? string.Empty at the end of that oneliner.



        You could omit the constructor of you Results-class, if you do



        public List<AddressComponent> AddressComponents get; set; = new List<AddressComponent>();


        instead.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Aug 23 at 14:26









        Fabian H.

        1615




        1615



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f202299%2ffind-suburbname-from-latlong-or-location%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay