Using Google map API with Umbraco

Create a web service to expose location data

So far in this series we’ve used Razor code in templates to retrieve location data from Umbraco. In part 3 we retrieved the location data with Razor code, formatted it as a JSON string and embedded it in the page markup where it could be read by the Google map javascript code to create the markers. Whilst effective, its perhaps not an ideal solution as the more locations you have the more JSON will be embedded in the markup which could bloat the size of the page significantly. Also, what if you wanted the data to be consumed by some other remote systems? A better solution would be to create a web service that exposes the data which could then be consumed locally and remotely. In this article we create an Umbraco API Controller web service that that exposes the data.

Set up

Umbraco API Controllers are created using server side code. There are two ways server side code can be used in an Umbraco instance, both of which require access to the sites folder structure on the server. One way would be to compile the code into a dll file and drop the file into the sites bin folder. The second is to create a code file in the sites App_Code folder where it will be compiled at run time, removing the need to create a compiled dll file. For this article I will use the second method to create the controller.

Create the model

First off to create a new C# file in the App_Code folder called LocationApiController.cs. If there isn't an App_Code folder then create one in the root folder of your site. Add the following using statements to the top of the file:

using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Web.WebApi;
using Umbraco.Core.Models;
using Newtonsoft.Json;

Add a struct called Geolocation with two properties, one for longitude and another for latitude:

public struct Geolocation
{
    public Double Longitude { get; set; }
    public Double Latitude { get; set; }
}

Next, add a class called Location, with properties for Id, Name and Geolocation:

public class Location
{
    public int Id { get; set; }
    public string Name { get; set; }
public Geolocation Geolocation { get; set; } }

Create the controller

Next you need to create a controller that can access content data in Umbraco and return it to a client as JSON or XML.

Start by adding a class that inherits from UmbracoApiController:

public class LocationController : UmbracoApiController
{
}

Because the controller inherits from UmbracoApiController there are some services available that allow interaction with Umbraco via the Services property of the base class. We use a couple off these services to get the location content from Umbraco.

Get location content from Umbraco

At the top of the class add a field that will store the location content from the location repository, this will be used later on in the code.

private readonly IEnumerable<IContent> _locationContent;

Next, add the following constructor to the class

public LocationController()
{ var contentType = Services.ContentTypeService.GetContentType("location");
_locationContent = Services.ContentService.GetContentOfContentType(contentType.Id).Where(c => c.Published); }

In the first line of the constructor the ContentTypeService.GetContentType() method is used to retrieve data for the location content type:

var contentType = Services.ContentTypeService.GetContentType("location");

The second line uses the content type id of the location content type to retrieve all the published location content using the ContentService.GetContentOfContentType() method. This is then assigned to the _locationContent field.

var _locationContent = Services.ContentService.GetContentOfContentType(contentType.Id).Where(c => c.Published);

Return location data to the client

Now we need a method that returns location data to the calling client as JSON or XML (whichever the client requests).

What we will do is create a method that returns an IEnumerable of our model class Location, we’ll call it GetAllLocations.

public IEnumerable<Location> GetAllLocations()
{
    return;
}

What this method needs to do is to map each location content item to a Location model and add each Location model to a list. This can be achieved by using a simple Linq query:

var locations = (from c in _locationContent
                 select new Location()
                 {
                     Name = c.Name,
                     Id = c.Id,
                     Geolocation = JsonConvert.DeserializeObject<Geolocation>(c.GetValue("geocoder").ToString())
                 }).ToList();

Because Umbraco Api Controllers extend the .Net Web API framework there is no need to to convert the list to JSON or XML as this is done automatically by the Web API native JSON/XML parsers. Note that the location data that is stored as JSON in the geocoder field is deserialized into a Geolocation object that is assigned to the Geolocation property of the Location.

The completed method should look like the following:

public IEnumerable<Location> GetAllLocations()
{
    var locations = (from c in_locationContent
                     select new Location()
                     {
                         Name = c.Name,
                         Id = c.Id,
                         Geolocation = JsonConvert.DeserializeObject<Geolocation>(c.GetValue("geocoder").ToString())
                     }).ToList();
    
    return locations;
}

The full LocationApiController.cs code

using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Web.WebApi;
using Umbraco.Core.Models;
using Newtonsoft.Json;

public struct Geolocation
{
    public Double Longitude { get; set; }
    public Double Latitude { get; set; }
}

public class Location
{
    public int Id { get; set; }
    public string Name { get; set; }
public Geolocation Geolocation { get; set; } } public class LocationController : UmbracoApiController { private readonly IEnumerable<IContent> _locationContent;
public
LocationController()
{ var contentType = Services.ContentTypeService.GetContentType("location");
_locationContent = Services.ContentService.GetContentOfContentType(contentType.Id).Where(c => c.Published); }
public IEnumerable<Location> GetAllLocations() { var locations = (from c in _locationContent select new Location() { Name = c.Name, Id = c.Id, Geolocation = JsonConvert.DeserializeObject<Geolocation>(c.GetValue("geocoder").ToString()) }).ToList(); return locations; } }

Try it out

Once you have saved it and restarted your site you should be able to access the web service by appending /Umbraco/Api/location/GetAllLocations after the sites domain name e.g.

http://yoursitename/Umbraco/Api/location/GetAllLocations

If you use Google chrome to view the URI the output will default to XML format. So if you had three locations saved in your site, one for Bristol, Manchester and London you should see some XML like the following:

<ArrayOfLocation xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Umbraco.Models">
    <Location>
        <Geolocation>
            <Latitude>51.454513</Latitude>
            <Longitude>-2.5879099</Longitude>
        </Geolocation>
        <Id>1083</Id>
        <Name>Bristol</Name>
    </Location>
    <Location>
        <Geolocation>
            <Latitude>53.4807593</Latitude>
            <Longitude>-2.2426305</Longitude>
        </Geolocation>
        <Id>1104</Id>
        <Name>Manchester</Name>
    </Location>
    <Location>
        <Geolocation>
            <Latitude>51.5073509</Latitude>
            <Longitude>-0.1277582</Longitude>
        </Geolocation>
        <Id>1060</Id>
        <Name>London</Name>
    </Location>
</ArrayOfLocation>

Next article: Consume data from web service using JQuery 

Comments

To be able to comment you need to login using a Google or Facebook account.