Using Multiple Properties Or The Entire Object In a Converter Class for Windows Phone and WinRT

Kind of a long wordy title, what does it really mean?  When you are creating a custom converter for Windows Phone or WinRT, you create a class that inherits from IValueConverter and implement a Convert method.  In that method you’re given (among other things) the value that has been bound (bind-ed sounds too funky, sorry) to your element and optionally a converter parameter that you can use to help you decide what your Convert method should return.  For example, your parameter could return “true”, “backwards”, “Blazers”, or whatever you want.  The main limitation as you may be noticing here is that you can only pass a single value back.  So what happens when you need to look at multiple properties of the item that is being used in the data binding in order to decide what to pass back from Convert? 

Here’s a simple example from something I was working on.  I’m binding to an item that has an “IsMine” and “IsOpen” property.  If the current item has “IsMine” equal to true, then I will return different values depending on whether IsOpen is true or false.  This obviously is not possible if you are just passing a single string back as your converter parameter.  The trick is to not assign a value to the binding; when you do that, the entire item is passed in as the “bind-ed” value.  So assume you’ve written a custom Convert method called MyColorConverter.  You want to use that for the background color of a Border element, so you would configure the binding for it like this:

 

<BorderBackground=”{Binding Converter={StaticResource DataItemsColorConverter}}”>

 

Notice that usually you would say what field you are binding too like this:  {Binding myField, Converter={blah}.  By omitting a specific field for the binding value, you get access to the entire object.  Then in my Convert method I can work with it like this:

 

    public class DataItemsColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {

            SharePointData.DataItem di = (SharePointData.DataItem)value;

 

            if (di.IsMine)
            {
                if (di.IsOpen)
                    return “#FF41719C”;
                else
                    return “#FFED7D31”;
            }
            else
                return “#FF7030A0”;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            //not going to be converting back
            return value;
        }
    }

 

 

Advertisements

Windows Phone 8 Support for SharePoint and SAML

This is a fortunately small update to the post about Windows Phone 7.x and SAML SharePoint sites I originally wrote here:  http://blogs.technet.com/b/speschka/archive/2011/09/09/windows-phone-7-and-other-mobile-access-to-sharepoint-2010-saml-sites-after-applying-sp1-and-june-2011-cu.aspx.  I was asked today about Windows Phone 8 support for SharePoint SAML sites on both SharePoint 2010 and SharePoint 2013.  Well the short and good news is that it all seems to work flawlessly.  I was able to access my SharePoint 2010 site without having to modify the web.config as I described in the above post.  Support on SharePoint 2013 was even better – when I opened the site it automatically recognized that I was using a mobile device and so it rendered a nice mobile friendly view of the site contents for me.  Not only that, but I tested my new SharePoint App that runs in a SAML site on my phone (and uses CSOM to retrieve data from a SharePoint SAML site) and it all worked flawlessly – the circle here is basically complete.  I’ll have more details in a future post on hooking up SharePoint Apps in FBA and SAML SharePoint sites to provider-hosted apps in FBA and SAML sites, but for now just wanted to report the happily uneventful news for Windows Phone 8.  I am using the Nokia Lumia 920 by the way and it has been great! 

How To Send An Authenticated Message to the Windows Phone Push Notification Service

The Push Notification Service is a cool feature of Windows Phone that lets you do things like send toast messages, update a Live Tile, etc. for your Windows Phone application.  You can use the service without any additional transmission security protocols, but if you do you are limited to a maximum of 500 messages per day.  If you use SSL to set up a mutually authenticated session to the Push Notification Service however, you can send an unlimited number of messages.  This makes securing your conversation that much more appealing.  The actual process for doing so is unfortunately documented about as poorly as anything I’ve ever seen.  Fortunately the social forums in the Windows Phone App Hub are quite useful so you can piece it together from reading through them.  To save you the time though of trying to hunt down all of the pieces needed to do this, I thought I would bring it all together here in one simple document.  You know, kind of like the product team should have done.  🙂  So here goes:

  1. You can read about the requirements for the certificate that’s used for establishing this secure communication here:  http://msdn.microsoft.com/en-us/library/ff941099(v=vs.92).  To make it simple though, I found that if you have an SSL certificate from one of the supported certificate authorities, it works just fine.  To see the list of supported certificate authorities, see here:  http://msdn.microsoft.com/en-us/library/gg521150(v=vs.92).
  2. You need to take this certificate and upload it to the App Hub.  You don’t need the PFX with the private key, just the public version of the certificate (i.e. the .cer file).  To upload it, sign into the App Hub, sign-in and then click on your account name in the upper left corner.  When you go into the account management page you will see a link called Certificates under the My Account banner.  Click on that and follow the instructions there to upload the certificate.
  3. In your Windows Phone application you create a HttpNotificationChannel class instance.  When you create the new HttpNotificationChannel, use the common name (CN) of the SSL certificate as the second parameter for the new channel.  You can find the common name of your certificate by double-clicking on the .cer file top open it, click on the Details tab, and then click on the Subject property.  You will see values displayed in the window below and the first one should be something like “CN = www.contoso.com“; you want to use just the “www.contoso.com” in this example.  So when you created your new channel it would look something like this:  pushChannel = new HttpNotificationChannel(“myChannelName”, “www.contoso.com“);
    1. NOTE:  If you have already created channels for different devices, then you will need to find your channel using the HttpNotificationChannel.Find method, then .Close and .Dispose the channel.  Then you need to recreate it so you can associate your common name with the connection.
  4. Where run your server side code, you need to install the certificate, including the private key (so the .pfx file).  You also need to ensure that the account for your application pool has access to the private keys for that certificate.  To do that, open the MMC tool and add the Certificates snap-in for the Local Computer.  After you’ve installed your certificate into the Personal node, right-click on the certifcate in the MMC and select All Tasks…Manage Private Keys.  You then need to add the account for the application pool your application is using and grant it at least Read rights to the keys.
    1. NOTE:  If you are using the new built in accounts in IIS 7.5, like ApplicationPoolIdentity, then you need to grant access to IIS apppool\ASP.NET v4.0, where “ASP.NET v4.0” is the name of your app pool.
  5. In the code where you are sending the message to the Push Notification Service you need to add the certificate to the HttpWebRequest object.  You would typically do this by opening up the X509 Store, getting the certificate collection for the My store, doing a Find on the collection by thumbprint, where you need to copy and paste the certificate’s thumbprint from the certificate properties to your code, and then using the first certificate in the collection it returns (i.e. myCollection[0]).  Once you have the certificate you can add it to your request like this:  myRequest..ClientCertificates.Add(mySslCertificate);

The other important things to note:

  • Your certificate that you upload in only used for four months.  If you don’t submit an application for certification to the marketplace that uses the certificate then it will need to be uploaded again.  When you submit your app for certification to the marketplace you will have an opportunity to select a certificate for it from the list of certificates that you have uploaded.  Just select the certificate that you uploaded for these communications and you are set.
  • How do you know if this works?  Well, when you create the HttpNotificationChannel class instance on the Windows Phone client, you will get back a notification channel Uri that send your messages to.  Look at that Uri – if you are not using an authenticated connection, then you will see “throttledthirdparty” in the path.  However if you created your class instance correctly, the path will contain “unthrottledthirdparty”; in addition the protocol it shows will be HTTPS instead of HTTP.  Now of course, to really make sure it works, after you get that Uri back you need to successfully send a message.  If it arrives at your device okay then you know it worked.

CloudTopia: Connecting o365, Apps, Azure and Cortana – Part 1

This is going to be a multi-part series to dissect and tear apart an application I tweeted about using the #yammerofjuly hashtag.  This is an application I developed a couple of months ago as a means of illustrating some of the different complexities and options when building applications that span several cloud services.  Through the course of this series I’ll start out by looking at the application overall, and then start breaking down some of the different components of it and how everything is tied together in the hopes that you can use it to integrate some of these same service connection points within your own applications.

NOTE:  You can find ALL of the source code for everything in this series on GitHub at https://github.com/OfficeDev/CloudTopia-Code-Sample

Here’s some quick links to the whole series:

  1. Intro
  2. Open Graph
  3. Web API
  4. Azure Integration
  5. Office 365 Integration
  6. Cortana, Speech and Windows Phone Integration

We’ll start by looking at the business requirements for the application.  In our scenario we are working with a company that manages public events for their customers.  They have the basic collaboration needs – for each event they create brochures, flyers, calendars, budgets, schedules, etc.  In addition to that they want to be able to have a discussion forum around the event so they can talk through different aspects of the event with the team.  They also want to have some way to get a feel for the buzz about the event that’s happening out in the public.  They’re just looking for some way to get a feel for how their marketing of the event is working.

Given those requirements, I built the application I call CloudTopia.  It uses several services and technologies that will be described in subsequent posts:

  • Office 365
  • Yammer Open Graph
  • SharePoint Cloud App Model in a provider hosted app
  • JavaScript and jQuery
  • Web API 2.1
  • Azure web sites
  • SQL Azure
  • SQL Scheduler service
  • Twitter

So as you can see, a lot of things working together here to make our solution.  To start things off, I created a demo video of the application – you can watch it here:  https://onedrive.live.com/redir?resid=96D1F7C6A8655C41!18616&authkey=!AC4csVj2oAU6B7M&ithint=video%2cmp4.  After you’ve watched the video come back here and let’s talk a little bit about what you saw and how it was built.

 

Design and Architecture

Here’s a screenshot of the home page of the CloudTopia application with callouts for the different technologies and services being used:

 

 

Here’s a brief summary of each component:

  • Office 365 – the whole application starts out in an Office 365 site.  I just created a new site in o365 tenant and made it the home page for the application.
  • Cloud App Model – the SharePoint 2013 Cloud App Model (CAM) was the starting point that I used to create this application.  It ultimately relied upon several other services and technologies, but it was all delivered through CAM.  One of the main features of the application – the UI you see in the o365 site – is just the standard iFrame that you get with a provider hosted application.  From where it says “Upcoming Social Events” on down is all part of the app.
  • Azure Web Sites – one of the great things about CAM and provider hosted apps is that you can host them pretty much anywhere.  In my case I decided to use one of the free Azure web sites that I get with my Azure subscription to be the “host” in my provider hosted application.  It also underscores an important theme with this application: it’s called “CloudTopia” because it is 100% running in the cloud; there are NO on premises components to this application.
  • SharePoint List Data – all of the events and some related metadata is stored in a hidden list in the o365 Events site.  The list is created by a remote event receiver when the application is installed.  The event receiver creates the list, makes it hidden, and removes the list from the quick navigation links on the left side of a standard team site page.  For more information on this process of creating a list this way in the host web of an application see my previous post here:  http://blogs.technet.com/b/speschka/archive/2014/05/07/create-a-list-in-the-host-web-when-your-sharepoint-app-is-installed-and-remove-it-from-the-recent-stuff-list.aspx.
  • More o365 sites and Yammer Open Graph Items – each time a new event is added, a new o365 site is created for the event and a Yammer Open Graph item is created that is used or discussions on the event.  More details follow below where I describe what all happens when you create a new site.  In terms of working with Yammer Open Graph from .NET, I have already covered that in previous posts on my blog.  You can go to the Open Graph specific post at http://blogs.technet.com/b/speschka/archive/2014/05/29/using-yammer-open-graph-in-net.aspx; it’s also part of the bigger Yammer toolkit for .NET that I’ve been building over time that started with this post:  http://blogs.technet.com/b/speschka/archive/2013/10/05/using-the-yammer-api-in-a-net-client-application.aspx.
  • SQL Azure – the application uses SQL Azure to store certain data that is necessary to query twitter and add discussion items to Yammer Open Graph objects.  In a later part in this series I’ll explain why I chose to use SQL Azure instead of SharePoint list data to store this information.  As an added bonus, I used a free SQL Azure data instance that comes with an MSDN subscription.  I’ll also cover that a little later.
  • Azure Scheduler – as you saw in the demo video, one of the things the application does is go find tweets that match the hashtags for our event and then add those tweets to the Open Graph discussion for the event.  That work happens once a day and is triggered using a job in the Azure Scheduler service.  Due to the low volume of these requests it falls within the number of free jobs that can be scheduled with Azure.
  • Web API 2.1 – a key component to the entire CloudTopia application is the use of Web API.  It’s primary use case is that it does all of the hard work for all of the features of the application – creating o365 sites, creating Yammer Open Graph items, searching Twitter, etc.  One of the big reasons why it’s so valuable for SharePoint Apps is that it allows me to control the UI entirely client side, but still use all the power of CSOM and any other .NET API.  You saw a lot of activity in the demo video and all of that was done through JavaScript and jQuery calling the custom REST endpoint that was created for the CloudTopia application.  In addition to that, it allowed me to create a REST endpoint just for the Azure Scheduler job.  A job can call an HTTP or HTTPS endpoint to do something, but there needs to be a listener that can “do something” when invoked.  Adding an endpoint in my REST controller provides the interface for just that kind of automated integration with other applications.

 

What Happens When You Create a New Event

There are quite a few things that get triggered when you go through the seemingly simple process of creating a new event.  Let’s take a look at what happens.

  1. A new o365 site is created for the event.
  2. The out of the box Site Feed web part is removed from the new o365 site.
  3. A new Open Graph (OG) item is created in Yammer.
  4. The Url link for the OG item is set to be the Url of the new o365 site
  5. This also means you can go into Yammer and just search for your o365 site Url and you’ll find the Open Graph object.  Pretty cool.
  6. A welcome post is added to the Open Graph discussion.
  7. A script editor web part is added to the new o365 site; it uses Yammer Embed to display the feed for the Open Graph item.
  8. A new item is added to the hidden SharePoint list in the host site where the App part is installed; that’s how it shows up in the event list in the host site.
  9. A new item is added to SQL Azure with the Open Graph ID along with the new Site Url and Twitter tags.

That’s a lot of stuff!  That’s also good for the intro of this series.  In Part 2 of this series I’ll talk about some of the work I did around Yammer Open Graph objects in CloudTopia.

CloudTopia: Connecting o365, Apps, Azure and Cortana – Part 2

In Part 1 of this series, I introduced you to the CloudTopia app.  In Part 2 we’re going to look at some of the work we did with Open Graph items in CloudTopia.

Here’s some quick links to the whole series:

  1. Intro
  2. Open Graph
  3. Web API
  4. Azure Integration
  5. Office 365 Integration
  6. Cortana, Speech and Windows Phone Integration

As I described in Part 1, Yammer Open Graph (OG) items are used in CloudTopia in a couple of different ways:  1) to provide a forum for discussion for the team working on an event and 2) as a way to bring in external discussions from Twitter to the OG item so the team can get a good sense of the external buzz that’s happening around their event…like #yammerofjuly (inside joke for those of you who have been following me on Twitter).  As I also described in Part 1, I covered the basic details of working with OG items in a previous post here:  http://blogs.technet.com/b/speschka/archive/2014/05/29/using-yammer-open-graph-in-net.aspx.  I won’t be covering that all over again, but I will be covering some of the other implementation details and things you should be aware of when working with your own OG items.  And that’s really the point of this entire series – not how to write this application per se, but cover some general purpose implementation details and things you should be aware of.

Okay, so we’ll use the blog post above as a starting point for working with OG items, now let’s look at some of the implementation details.  In my previous posts on OG I talked about the object model that I created over an OG item and how to use it to create a new OG item in Yammer.   For review, here’s what my object model looks like:

 

To use it you need to send a chunk of JSON to Yammer to create the OG item.  What I did to facilitate this is let you create an OG item using my object model, and then when you call the ToString() method I’ve overridden that so that it produces the JSON you need.  With that in hand you can use one of the methods I included in my original Yammer and .NET posting to create the item, by calling the MakePostRequest method.  The net of this is that your code looks pretty straightforward:

YammerGraphObject go = new YammerGraphObject();

go.Activity.Action = “create”;

 

go.Activity.Actor = new YammerActor(“Steve Peschka”, “speschka@yammo.onmicrosoft.com”);

 

go.Activity.Message = “This is the discussion page for the ” + eventName + ” event on ” + eventDate;

 

go.Activity.Users.Add(new YammerActor(“Anne Wallace”, “annew@yammo.onmicrosoft.com”));

go.Activity.Users.Add(new YammerActor(“Garth Fort”, “garthf@yammo.onmicrosoft.com”));

 

YammerGraphObjectInstance jo = new YammerGraphObjectInstance();

jo.Url = Url;

jo.Title = eventName; 

jo.Description = “This is the discussion page for the ” + eventName + ” event on ” + eventDate; 

jo.Image = “https://socialevents.azurewebsites.net/images/eventplanning.png&#8221;;

jo.Type = “document”;

 

go.Activity.Object = jo;

 

string postData = go.ToString();

 

string response = MakePostRequest(postData, graphPostUrl, yammerAccessToken, “application/json”);

 

The other thing I mentioned in part 2 of that series on OG items is how important it is to have the OG ID; it is required whenever you want to read from or write to the discussions for the OG.  As I mentioned in that post there are basically three ways to get the OG ID:

  1. Capture it when the OG item is created.  You’ll get some JSON back if the create is successful and we can use that to extract out the ID of the newly created item.
  2. Search for an OG item.  You can search using the Url property of the OG item; however this only returns results if there is at least one discussion item created for the OG.  This is another reason why the CloudTopia app creates an initial discussion item when creating the OG.
  3. Do a “fake” update to the OG item.  What I mean by fake is that I just pass in my own username and email address as the actor, I change the Action to “follow”, and I set the Private property of the Activity to true.  When I do that I get back the same chunk of JSON as I do when I create an OG, so again I can extract out the ID from there.

 

In the case of CloudTopia I simply capture the ID at the time I create the item; that’s clearly the best option if you can do so.  In CloudTopia I take the ID of the newly created OG item and I save it to SQL Azure so I can use it later when creating new discussion items for the OG based on tweets I found for the event.  To extract the ID I built another class to serialize the JSON into and it looks like this:

 

 

Using it is quite simple:

//create the OGO

string response = MakePostRequest(postData, graphPostUrl, yammerAccessToken, “application/json”);

 

if (!string.IsNullOrEmpty(response))

{

      YammerGraphObjectItem gi = JsonConvert.DeserializeObject<YammerGraphObjectItem>(response);

}

Finally, remember that you always need the OG ID when reading or writing discussion items for it.  Also, the Url to use to read OG discussion items is currently undocumented “officially”, but I have covered all of this in greater detail in part 2 of my series on working with Yammer Open Graph from .NET (http://blogs.technet.com/b/speschka/archive/2014/05/29/using-yammer-open-graph-in-net-part-2.aspx).

Now let’s bring all the discussion of this back around to a concrete example – what we did in the CloudTopia app.  Remember that we create a new OG item when a new o365 site is created, and we use the Url for the new o365 site as the key for the OG item.  Here’s what that code looks like in CloudTopia:

//NOTE:  WILL EXPLAIN MORE OF THIS CODE

//IN A SUBSEQUENT PART OF THIS SERIES

//create a new site

string newUrl = AddNewSite(se.accessToken, se.hostUrl, se.eventName, se.eventDate);

 

//if it works, plug in the new site url

if (!string.IsNullOrEmpty(newUrl))

{

//create a new GraphObject item

YammerGraphObjectItem gi = CreateOpenGraphItem(newUrl, se.eventName, se.eventDate, se.twitterTags);

 

The CreateOpenGrahpItem method looks like this:

YammerGraphObjectItem gi = null;

 

YammerGraphObject go = new YammerGraphObject();

go.Activity.Action = “create”;

go.Activity.Actor = new YammerActor(“Steve Peschka”, “speschka@yammo.onmicrosoft.com”);

go.Activity.Message = “This is the discussion page for the ” + eventName + ” event on ” + eventDate;

 

go.Activity.Users.Add(new YammerActor(“Anne Wallace”, “annew@yammo.onmicrosoft.com”));

go.Activity.Users.Add(new YammerActor(“Garth Fort”, “garthf@yammo.onmicrosoft.com”));

 

YammerGraphObjectInstance jo = new YammerGraphObjectInstance();

jo.Url = Url;

jo.Title = eventName; 

jo.Description = “This is the discussion page for the ” + eventName + ” event on ” + eventDate; 

jo.Image = “https://socialevents.azurewebsites.net/images/eventplanning.png&#8221;;

jo.Type = “document”;

 

go.Activity.Object = jo;

 

string postData = go.ToString();

 

string response = MakePostRequest(postData, graphPostUrl, yammerAccessToken, “application/json”);

 

//serialize the results into an object with the OG ID

if (!string.IsNullOrEmpty(response))

{

gi = JsonConvert.DeserializeObject<YammerGraphObjectItem>(response);

string newMsg = “Welcome to the Yammer discussion for the ” + eventName +

” event, happening on ” + eventDate + “.  We’ll also be tracking external ” +

“discussions about this event on Twitter by using the tags ” + twitterTags + “.”;

CreateOpenGraphPost(gi.object_id, newMsg);

}

One quick note about the code above.  You may notice that I made the OG object Type a “document”.  You can find the complete list of Types that are supported at http://developer.yammer.com/opengraph/#og-schema.  There isn’t a type for “web site” so I just used document, but you can obviously choose one that works for you.  Finally, assuming our OG was created successfully then we serialize the return JSON to get the YammerGraphObjectItem so we have the object_id we need to update it later on.  Then we create the first discussion post to the OG item in the CreateOpenGraphPost method.  It is extraordinarily simple, just the way I like it:

string msg = “body=” + Message + “&attached_objects[]=open_graph_object:” +

ID + “&skip_body_notifications=true”;

 

//try adding the message

string response = MakePostRequest(msg, messageUrl + “.json”, yammerAccessToken);

That’s it!  We’ve talked about the semantics of working with Yammer Open Graph items, and we’ve looked at the specific implementation we used in the CloudTopia application.  In the next post in this series we’ll look at adding a Web API component to your standard out of the box SharePoint App project.  This can be extremely simple, I regularly use them in my SharePoint Apps now so I hope you’ll tune in and read more about it.

CloudTopia: Connecting o365, Apps, Azure and Cortana – Part 3

In Part 2 of this series we looked at some of the details of working with Yammer Open Graph items in the CloudTopia app.  In Part 3 we’re going to talk about adding and using Web API 2.1 functionality to a standard out of the box SharePoint App, and then look at what we do with that in CloudTopia.

Here’s some quick links to the whole series:

  1. Intro
  2. Open Graph
  3. Web API
  4. Azure Integration
  5. Office 365 Integration
  6. Cortana, Speech and Windows Phone Integration

 

In CloudTopia I use a Web API REST endpoint for my implementation of virtually everything.  It allows me to create an end user experience free of postbacks, but still access all the functionality of CSOM as well as .NET.  I can use JavaScript and jQuery to manage the front end interface because the code in my Web API controller is doing all the work.  In addition to that, by adding a REST endpoint to my application I open it up to be consumed and/or provide services to other applications.  A good example of this is the Twitter integration.  That process is kicked off by an Azure Scheduler job that makes a GET request on a REST endpoint I set up.  That’s a pretty key use case for Web API in your SharePoint Apps – without it, all of your application functionality is wrapped up in the fairly narrow confines of some browser based application.  By adding a Web API endpoint on top of it, now I can integrate that same functionality into many other applications across my organization or even, as demonstrated with the Azure Scheduler, outside my organization if I wish.

Now, adding the plumbing to support Web API 2.1 is not necessarily easy to find, so let me give you the steps here:

  1. Add the following two NuGet packages to your web application project:  Microsoft ASP.NET Web API 2.2 Core Libraries and Microsoft ASP.NET Web API 2.2 Web Host (NOTE:  the “2.2” refers the current version at the time of this blog post; you may find a more current version).
  2. Add a new class file to the root of your project and call it WebApiConfig.cs.
  3. Add the following code to your WebApiConfig.cs file (NOTE: You can add a different default route for your REST endpoints if you wish, I’m just following common convention here):

 

    public class WebApiConfig

    {

        public static void Register(HttpConfiguration config)

        {

            config.MapHttpAttributeRoutes();

 

            config.Routes.MapHttpRoute(“API Default”, “api/{controller}/{id}”,

                new { id = RouteParameter.Optional });

        }

    }

 

  1. Add this code to Application_Start in Global.asax:

protected void Application_Start(object sender, EventArgs e)

{

//for WebApi support

GlobalConfiguration.Configure(WebApiConfig.Register);

}

UPDATE 12/29/2014:  IMPORTANT!  Make sure you call the GlobalConfiguration.Configure method BEFORE you do any other configuration calls in the Start event.  For example, if you are adding this to a full blown MVC app then you will already have this in you Start code:  RouteConfig.RegisterRoutes(RouteTable.Routes);.  If you add the call for WebApiConfig.Register AFTER RouteConfig.RegisterRoutes then your Web API routes will not be found and your controller actions not hit.

Once you’ve done the configuration above, you can add a new Web API Controller Class v2 to your project and start creating your REST endpoints.  Before you get started writing code here a few tips:

  • Make sure the name of your class contains the word “Controller” (i.e. EventsController.cs); otherwise it won’t be found.  That one can drive you a little crazy if you don’t write much Web API and so aren’t familiar with this little nuance.
  • To create an overload inside your controller add a Route attribute and optionally an HTTP verb; that is how I added multiple POST endpoints to my single Web API controller class.  For example I do a POST request to api/events/currentevents to get the list of current events, a POST to api/events to create a new social event, etc.  Here’s an example of what the currentevents route looks like:

 

[Route(“api/events/currentevents”)]

[HttpPost]

public List<SocialEvent> Get([FromBody]string value)

{

//code goes here

}

  • Make sure your Route attribute uses the same path as a route you defined in WebApiConfig.cs.  For example, if your route definition uses “api/{controller}/{id}, your Route attribute should also start with “api/”.

 Once you have your controller added and configured as described above, calling it from jQuery is quite simple.  Here’s an abbreviated look at the jQuery in my SharePoint App that gets the list of events: 

//some SharePoint vars I get and will explain next

formData = JSON.stringify(formData);

 

$.post(“/api/events/currentevents”, { ”: formData })

.success(function (data)

{

       //code goes here

}).fail(function (errMsg)

{

alert(“Sorry, there was a problem and we couldn’t get your events: ” +

errMsg.responseText);

});

 

One of the biggest challenges when using a REST endpoint as part of your SharePoint App is getting an access token to work with (assuming you are doing more than just app only calls).  I looked three different options for this when I was writing CloudTopia:

  1. Persist token info to storage, like we recommend for the CAM “permissions on the fly” scenario
  2. Persist token info to ViewState
  3. Write out tokens to hidden fields on page

Of these options #1 is the safest and most enterprise-worthy of the bunch.  It also takes the most time and investment to do it right.  Because of the limited time I had to build the CloudTopia application I did not take this approach.  If I were though, I would consider having a method in my REST endpoint called something like RegisterRequest.  I could imagine calling a method like that and passing in a SharePointContextToken as I described in this post here:  http://blogs.technet.com/b/speschka/archive/2013/07/30/security-in-sharepoint-apps-part-4.aspx.  With the SharePointContextToken I have a) a guaranteed unique cache key for it and b) a refresh token that I can use to obtain an access token.  So when my RegisterRequest method was called I could then store that somewhere, like SQL Azure or whatever.  Then I could require that any calls into my REST endpoints provide the cache key, and all I have to do is look up what I’ve stored and if there’s something there, use the refresh token to get an access token and go to work.  This is just one idea I had, you may have others of your own.

Given my limited time, I chose to try both option 2 and 3.  Option 2 was really something I just wanted to play with to see if there would be any issues in using it.  So in that case I took the access token I got and wrote it to ViewState, and then I used it for one button in the page, which cleans the app up (i.e. deletes the hidden list I use to track new events).  I’m happy to report that it worked fine so if you want to go that way and you are doing your code in post back events it should work fine.  That’s really the key – you switch to a post back model if you want to use values from ViewState.

Primarily what I did was option 3.  I wrote both the SharePoint site Url as well as the access token to the page to some hidden fields, and then I pass those variables in to my REST calls.  It all travels over SSL, the access token has a limited lifetime, etc. so it was a reasonable choice given what I had to work with. 

The end-to-end implementation of if then went something like this:

 

  • I had client side script that looks like this:

//get the hiddens

var hostUrl = $(“#hdnHostWeb”).val();

var accessToken = $(“#hdnAccessToken”).val();

 

//create the JSON string to post

var formData = “{hostUrl:” + hostUrl + “,” +

“accessToken:” + accessToken + “}”;

 

//make it POST ready

formData = JSON.stringify(formData);

 

//call my REST endpoint

$.post(“/api/events/currentevents”, { ”: formData })

 

  • In my REST endpoint I parsed out the JSON that was sent in like this (NOTE:  ParseJson is just a custom method I wrote for my SocialEvent class):

SocialEvent se = SocialEvent.ParseJson(value);

 

  • The SocialEvent class has a hostUrl and accessToken property, so I just used them when calling methods that used CSOM to work with SharePoint:

List<SocialEvent> results = GetEventListItems(se.hostUrl, se.accessToken);

 

  • In my code that uses CSOM I created the ClientContext using the hostUrl and accessToken like this:

using (ClientContext ctx = TokenHelper.GetClientContextWithAccessToken(hostUrl, accessToken))

 

There you have it – that’s a roadmap for how to add Web API 2.x support to your SharePoint Apps.  I’m becoming a pretty big fan of this approach because it provides so much flexibility for making a client experience exactly like you want it, plus it opens up the capability to integrate all of your application functionality across other applications.  Now that we’ve wrapped up this piece of plumbing, in Part 4 of this series we’ll take a look at the Azure integration points.

CloudTopia: Connecting o365, Apps, Azure and Cortana – Part 4

In Part 3 of this series we looked at the plumbing required to add support for Web API 2.x to your SharePoint Apps, as well as some of the integration needed to have it work with SharePoint and CSOM.  In Part 4 we’re going to look at the integration with various Azure services in the CloudTopia app.

Here’s some quick links to the whole series:

  1. Intro
  2. Open Graph
  3. Web API
  4. Azure Integration
  5. Office 365 Integration
  6. Cortana, Speech and Windows Phone Integration


To begin with I started the CloudTopia project like any other SharePoint App – I cracked open Visual Studio 2013 Update 2, and then I created a new SharePoint App.  I made it a provider-hosted app, and it created two projects for me – one with the application manifest needed for app registration and the other a web site project.  Deployment was straightforward but I’ll cover that in the next post; I just wanted to set the stage for how we get things started.  Now let’s look at how we took this application and integrated with a variety of Azure services.

Azure Web Sites

CloudTopia is deployed to an Azure web site.  You get 10 free web sites with an Azure subscription so I used one of those to deploy my app.  The process for doing so is quite simple of course – you go to the Azure Management Portal and click the Web Sites link in the navigation and Add a new one.  There is some subtlety to adding a new one for this project, but I’ll cover that in the SQL Azure section (it will make sense why when we get there).  Once my web site is created I just downloaded the publishing profile from the Azure management portal page for the web site, and then in Visual Studio I chose the option to publish my site.  When the publish wizard ran I gave it the location of the publishing profile file that I had downloaded and away we went.  Whenever I made changes I just republished the site and about 30 seconds later my latest code was up and running in the Azure web site.  Good stuff.

One other thing worth noting here is debugging.  Debugging is possible for web sites hosted in Windows Azure, you just do it a little differently than if you were running your web site locally.  I’ve previously posted about this process for debugging your SharePoint Apps that are hosted in an Azure web site – you can find that post here:  http://blogs.technet.com/b/speschka/archive/2013/11/25/debugging-sharepoint-apps-that-are-hosted-in-windows-azure-web-sites.aspx.

SQL Azure

I used SQL Azure in the CloudTopia app primarily to simplify the process of the daily task to go out and find matching tweets for social events.  As I described earlier, I was able to take advantage of a free 20MB SQL Azure database that I get with my Azure subscription.  You actually create and/or connect it to your application at the time you create your Azure web site – that’s why we’re covering site creation here in the SQL Azure topic.  To connect these up you want to first do a custom create for your new Azure web site:

When you do that you’ll have the option of selecting a database.  Click the drop down and if you have an MSDN subscription you should see an option to create a free 20MB database (assuming you have not created it already; if you have then you can just select the instance you already created):

Now I’m going to take what might seem like a brief detour but I’ll bring it back around when I’m done.  One of the features of the CloudTopia app is that it will take a set of Twitter tags that have been defined for an event and go do a search to find tweets in the previous 24 hours that have used them.  Every tweet that is found is added to the discussion on the Yammer Open Graph item that’s associated with the event.   That’s how we get this nice integrated discussion in our events:

We’re just running this code once a day, so the process to gather these matching tweets is kicked off when an Azure Scheduler job makes a GET request to our REST endpoint that runs this code.  So why am I sharing this information here?  Because way back in Part 1 of this series I mentioned that I was using SQL Azure to store some of the CloudTopia data versus just keeping everything in a SharePoint list.  Understanding this piece of functionality should help explain why SQL Azure.

As I also mentioned previously in this series, you always need the ID of a Yammer Open Graph item in order to read or write to the discussion that’s associated with it.  Also, as I described above, this process kicks off once a day from an Azure Scheduler job.  The distinction in this scenario is that there is no human present.  That means that I don’t have a user context in order to make a call back into SharePoint.  So if I wanted to store ALL of the CloudTopia metadata in a SharePoint list, I would need to configure my app to use an app only request.  While I could certainly do that, it requires an elevated level of permissions versus a simple user-driven request and that was something I did not want to do.  That’s how I landed on using SQL Azure for this purpose.  Not only is it free for my application, I’m able to use it without any user context at all – I just use a connection string with a set of credentials for a SQL Azure user that has rights to my CloudTopia database.  It’s also significantly easier for most developers to create SQL queries then the “sometimes mystical, sometimes magical, sometimes maddening” world of SharePoint CAML queries.  SQL Azure makes it easy to retrieve the information needed for the CloudTopia app, and also doesn’t require a high level of permission from the application itself.  Score one for SQL Azure!

Azure Scheduler

The final Azure service I used on CloudTopia is the Azure Scheduler service.  This is a pretty straightforward service to use and configure so I’m not going to spend a ton of time talking about it.  There are always several options when you are looking to schedule tasks; for CloudTopia though, as the name implies, I wanted it to be 100% hosted in the cloud – and cheap.  The Azure Scheduler service is a great solution for these requirements.  You get a set number of job iterations for free, and since I’m only making one job run a day – to get the tweets from the last 24 hours – this fits the bill perfectly.  When you create your job you can choose an HTTP or HTTPS endpoint to invoke, and you can define whether you want to do a GET, POST, PUT or DELETE.  For POST and PUT you can optionally provide a Body to send along with the request; for all of them you can add one to many custom Http headers to send as well.  After you configure your job endpoint you set up your schedule – a one time run to something that reoccurs on a regular basis.  That is basically it, but here’s some pictures to show you the UI that was used to create the CloudTopia Scheduler job:

When the Scheduler job runs here’s the REST endpoint that it invokes:

public async Task<HttpResponseMessage> Get()

{

HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK);

 

try

{

await Task.Run( () => UpdateYammerWithTwitterContent());

}

catch (Exception ex)

{

result = Request.CreateErrorResponse(

HttpStatusCode.BadRequest, ex.Message, ex);

}

 

return result;

}

So I just go off and run my code to update the Yammer Open Graph item with any tweets from the last 24 hours.  If it works I return an HTTP status code 200, and if it fails I decided to return an HTTP status code 400.  Yeah, it’s not really a bad request, but I’ve always wanted to return that to someone else for a change.

Here’s an abbreviated version of the code to actually go out and get the tweets and write them to Yammer.  First I connect to SQL Azure and get the list of events and their associated Twitter tags and Open Graph IDs:

using (SqlConnection cn = new SqlConnection(conStr))

{

SqlCommand cm = new SqlCommand(“getAllEvents”, cn);

cm.CommandType = CommandType.StoredProcedure;

SqlDataAdapter da = new SqlDataAdapter(cm);

 

DataSet ds = new DataSet();

da.Fill(ds);

 

With my dataset of events I enumerate through each one and go get the event tweets.  I start out by getting an access token for Twitter:

if (string.IsNullOrEmpty(TWT_ACCESS_TOKEN))

{

//create the authorization key

string appKey = Convert.ToBase64String(

System.Text.UTF8Encoding.UTF8.GetBytes(

(HttpUtility.UrlEncode(TWT_CONSUMER_KEY) + “:” +

HttpUtility.UrlEncode(TWT_CONSUMER_SECRET))));

 

//set the other data for our post

string contentType = “application/x-www-form-urlencoded;charset=UTF-8”;

string postData = “grant_type=client_credentials”;

 

//need to get the oauth token first

response = MakePostRequest(postData, TWT_OAUTH_URL, null,

contentType, appKey);

 

//serialize it into our class

TwitterAccessToken accessToken =

TwitterAccessToken.GetInstanceFromJson(response);

 

//plug the value into our local AccessToken variable

TWT_ACCESS_TOKEN = accessToken.AccessToken;

}

 

Now that I’m sure I have a Twitter access token I can go ahead and query twitter for the tags I’m interested in:

//now that we have our token we can go search for tweets

response = MakeGetRequest(TWT_SEARCH_URL +

HttpUtility.UrlEncode(query), TWT_ACCESS_TOKEN);

 

//plug the data back into our return value, which is just a

//custom class with a list of SearchResult so I can work

//with it easily from my code

results = SearchResults.GetInstanceFromJson(response);

 

//trim out any tweets older than one day, which is how frequently

//this task should get invoked

if (results.Results.Count > 0)

{

//retrieve items added in the last 24 hours

var newResults = from SearchResult oneResult in results.Results

where DateTime.Now.AddDays(-1) <

DateTime.Parse(oneResult.Published)

select oneResult;

 

results.Results = newResults.ToList<SearchResult>();

}

Once I get my search results back, I can add each one to the discussion on the Yammer Open Graph item:

foreach (SearchResult sr in queryResults.Results)

{

string newPost = “From Twitter: ” +

sr.User.FromUser + ” says – ” + sr.Title + “.  See the post and more at ” +

https://twitter.com/&#8221; + sr.User.FromUser + “.  Found on ” +

DateTime.Now.ToShortDateString();

 

CreateOpenGraphPost(objectGraphID, newPost);

}

You may notice that I’m calling the same CreateOpenGraphPost that I described earlier in this series – I used it previously to create the initial post for new Open Graph items.

That’s it for this post.  In Part 5 of the series we’ll look at all of the integration that was done with Office 365.  It was a lot, so stay tuned.