Friday, May 31, 2013

How to get coordinates for geolocation field (No code solution)

Geolocation field is a great addition to SharePoint that enables us to easily give some location meaning to our data.

When we add a geolocation field to our list and want to set our location data we will see that we have two options for doing this. If our environment allows it we can use "Use my location" option or we can go with the "Specify location" option.


When we select that we want to specify location, we will get this dialog:


In order to add a specific location to our list we need to know its exact coordinates and to get them we will probably have to go to Bing Maps and search for them. It would be great if we could simple enter some search values for our location and store coordinates from search results automatically, but there is nothing like that out of the box.

So it may seem that our only option is custom development but there is a nice workaround. I will show you how you can achieve this using a SharePoint list, a new workflow feature for calling web services and Bing Maps. I will not go into details so it would be good if you would have some understanding of REST services and the new Call HTTP service action in SharePoint workflows.

First we will need a SharePoint list with a geolocation field (if you need help adding a geolocation field to your list, check out my Adding geolocation field to SharePoint Online post), I will call mine Geolocation. Also we will add one additional column to store information about our locations, I have added a text column named Place.

The idea is that when user enters location information into the Place column, Geolocation field is automatically populated with coordinates.

To achieve this we will need to create a workflow. This workflow will use Call HTTP service action to call Bing Maps Rest services to get coordinates.

This is how the workflow looks like in the end:



I will go through each step to show you how it works.

As we can see, it has two stages. In the first stage we use Bing Maps services in order to get coordinates and in second part we use them to set values in our location field.

Here is how we get our location coordinates:

1. First we need to build up the request header. For this we need to create a dictionary with two properties Accept and Content-Type, both with values application/json; odata=verbose



Save the dictionary as BingRequestHeader.

2. Bing Maps provide us with REST services we can leverage to get geolocation data. You can read more about it here Bing Maps REST Services. We will use one of this services to get coordinates based on values user inputs into the Place column.
Add the Call HTTP service action to your workflow. For the web address of the service we will use URL that looks like this:

http://dev.virtualearth.net/REST/v1/Locations?q= <lookup to your place column>&o=json&key=<Your BING Maps key>

We will set the HTTP method of the call to HTTP GET.




Next we need to set the request header of our call to the previously created BingRequestHeader dictionary. To do this, right click on the action and select properties. In the properties window you will find a place where you can add your dictionary to request headers.

Create another dictionary called GeolocationResponse. We will use this dictionary to store the response content from our call, so in the Call HTTP service method set the ResponseContent to this new variable.

3. In the response from Bing Maps service we will get a json object that contains our coordinates. We have stored this data into our GeolocationResponse dictionary. In order to get longitude and latitude we need to search this dictionary and get values from it. For this we will use Get an Item from a Dictionary action. For the path of the item  enter :
resourceSets(0)/resources(0)/point/coordinates(0)



This will give you latitude. Set the output to a new variable that we will call Latitude

4. We will get longitude the similar way like we did latitude, we will just change the path of the item  to:
resourceSets(0)/resources(0)/point/coordinates(1)
Set the output to a new variable that we will call Longitude.


With these steps we will get our coordinates from the Bing Maps. Unfortunately, there is no action that allows us to simply set our geolocation field to those coordinates from the workflow. This is what the second stage of the workflow is for. In the second stage we will also use Call HTTP service action, but in this case we will use it to post data to our geolocation field using SharePoint REST Services.

5. First we need to set up our request header as we did when we were calling Bing Maps service. Create a new dictionary SharepointRequestHeader with the same values as BingRequestHeader.

6. To be able to post data into SharePoint list we will have to create a valid object that SharePoint can process. To create this object we will need to build several dictionaries.
Since we will need to create several dictionaries I will specify its properties in this form (name| type | value). First we will build a dictionary called metadata. It contains this property :
type | String | SP.Data.LocationsListItem (note that this will depend on the title of your list)



7. Build a dictionary called GeolocationFieldMetadata with
type | String | SP.FieldGeolocationValue



8. Build a dictionary called GeolocationFieldData. It should contain following properties:

__metadata | Dictionary | (Lookup to previuosly created GeolocationFieldMetadata dictionary)
Altitude       | Number     | 0
Latitude      | Number     | (Lookup to variable Latitude)
Longitude   Number     | (Lookup to variable Longitude)
Measure      | Number     | 0



9.  Build a dictionary named body with following properties:

__metadata | Dictionary  | (Lookup to previuosly created metadata dictionary)
Geolocation | Dictionary  | (Lookup to previuosly created GeolocationFieldData dictionary)



10.  We are now ready to update our field through Call HTTP service action. To update current item we will call service from a URL that looks like this:

https://<your site>/_api/web/lists/getbytitle('Locations')/items([%Current Item:ID%])
We will use our call with POST method.



In  Call HTTP service action we need to set the request of the call to the body dictionary we created and the request header to SharepointRequestHeader dictionary


11. This step is optional. I used it to log errors and similar information from the workflow into a field I have added to the list.

You can set the workflow to start when a new item is added so you can still manually update field if you are not satisfied with the coordinates Bing Maps gave you. And thats all, just publish your workflow, insert location information in your Place column (for example : Zagreb,Croatia), wait for the workflow to finish and your geolocation field should fill up automatically.

(I plan to make a short video demo of this workflow so if I didn't explain it too good in this post check back to see if  I was able to make a video available)

Tuesday, May 14, 2013

Using SharePoint REST services from workflow with POST method

SharePoint 2013 has a completely new workflow engine. With that engine we got some new actions and options that help us in creating our bussiness process using workflows. One of them is Call HTTP service action that enables us to leverage an external web service from our workflow.
On the other hand Sharepoint 2013 comes with a new REST interface that enables us to access and use its resources.When we combine these two new features we get powerful new ways for using our SharePoint workflows.

In this post I will show you how you can use this new action to POST new data to your SharePoint site.

I have created a SharePoint list  named WorkflowItems to use for example. We will create items in this list from a workflow using SharePoint REST services. To keep it simple I will leave it with only one column (Title).

Now we can open our SharePoint Designer and create a new site workflow and call it WorkflowItemWizard.

In our new workflow first we will create couple of dictionaries. Dictionary is a new variable type in SharePoint workflows that is used for defining collections of key/pair values and is very important for the Call HTTP service action.

To create a dictionary add Build Dictionary action to you workflow. Using that action specify two new keys Accept and Content-Type and set the values for both of them to application/json; odata=verbose like in the image below


Set the output to a dictionary with a more meaningful name, call it "header". This dictionary will be used as a header for our request.

Next create another dictionary that you will call metadata and in it add a key called type with value SP.Data.WorkflowItemsListItem.

And finally you will need one more dictionary that will contain your request data. Call it parameters, add key __metadata and set its value to the previously created dictionary metadata


Add one more key, call it Title and set its value to New item created from workflow.
Now you are ready to call the web service. Insert action Call HTTP service.
The URL you will require will look like this:
https://<site>/<web>/_api/web/lists/getbytitle('WorkflowItems')/items
and the HTTP method is POST.

Set the request to your parameters dictionary. To set the header of your request go to :
right click on the Call HTTP service -> properties -> RequestHeaders and set it to your header dictionary.


This is how the complete workflow looks like:



Now you can deploy your workflow and run it. Once it is over you should have a new item created in your list.
From this example you can continue building your solutions, you can add more fields, or use other available REST services for updating list items or deleting them.

One of the biggest advantages using this method to create or update list items is it is not limited to the site in which you workflow runs. Using REST services you can now access and create items in lists on other sites.

If you want to know more about SharePoint 2013 REST you should check this out :
Programming using the SharePoint 2013 REST service

Also check this excellent post on getting data into your workflow from SharePoint using Rest services:
Calling the SharePoint 2013 Rest API from a SharePoint Designer Workflow

Sunday, May 5, 2013

Adding geolocation field to SharePoint Online

One of the hidden gems in Sharepoint is the new geolocation field. Geolocation field enables you to annotate SharePoint lists with location information. In columns of type Geolocation, you can enter location information as a pair of latitude and longitude coordinates. The reason it is hidden is because it is not available by default in SharePoint list and there is also no user interface to add it. The only way to add it is through code or powershell. There are already many posts with code samples for adding geolocation field so that wont be the topic of this post. I would suggest to you to check out this post http://zimmergren.net/technical/sp-2013-getting-started-with-the-new-geolocation-field-in-sharepoint-2013 if you want to get a good insight in those code samples. This post will describe how I have created a small wizard form for adding those fields to my SharePoint lists. I am using pure HTML and javascript so this will work both in SharePoint Online and in your on premise environment. First create a page where you wish to place this wizard. On that page add a Script Editor web part. In this web part we will add both our javascript methods and our html.
First add this javascript:


And after that add this HTML form:

Web relative URL: &nbsp
Bing Maps Key: &nbsp
List name: &nbsp
Field name: &nbsp

This will be your end result:


And now you have your form for adding geolocation field anywhere on your site collection. Once you have entered relative path to your web ("/" is root web) you can use Get Bing key to check if you have a BING maps key placed in that web and with Set BING key you can change or add a BING maps key to that web.

And once you enter List name and Field name you can use Create field to add a geolocation field with the name you specified to the list on the web.

Hope this helps you create you geolocation fields faster.