Creating connectors for your Logic Apps/Flow (Part 1–regular Connectors)

  Azure logic apps have been around for a while now, most of the time as a preview. These apps allow you to create workflow-like apps, by connecting so called Connectors together. These connectors are actually just REST-services, with some extra's, like the exposure of metadata by using Swagger. These Logic apps have also been made available through Office 365, where it is known as "Flow". Office 365 Flow, or Azure Logic apps have access to a library of Connectors, like connectors for Twitter, Facebook, Outlook Mail and Calendar, SharePoint and many more. At the moment I write this there are 84 connectors available. But of course we can add our own connectors. You can find information on how to do this on the internet, however I found myself struggling with Azure because of incomplete information, even in the official Azure documentation. So, I decided to complete the information. From a developer perspective, there are two types of connectors we can create: "regular" connectors and triggers. A regular connector can just be used within your flow, but not at the start. It can take input from connectors preceding it in the flow, and it can return output to the flow.  A trigger can be used in the beginning of a flow and is responsible for starting the flow. Creating a regular Connector Connectors are REST services. In my example I will do this with Web API, but it can be done in any other web-technology. While creating a web application just choose Azure API App. I will create a simple example in which I just reverse an incoming string. The code is pretty simple : [SwaggerResponse(HttpStatusCode.OK,Type =typeof(StringManipulator))] [SwaggerOperation("GetReversedString")] public IHttpActionResult GetReversedString(string id) { var temp = ""; foreach (var item in id) { temp = item + temp; } return Ok(new StringManipulator { Original = id, Reversed = temp }); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } However, the second argument in your SwaggerResponse-attribute, the Type, is super important. Without this argument Logic apps, using your API, will just assume your function returns nothing ! It took me some time to find this out, since it used to work fine without Type in an earlier version of Logic apps, and it's nor really clear from the documentation. So, beware.  After deploying your API app to Azure, there are two more things to do. Locate your API app in the Azure portal, and go to the API settings. The API definition should point to your swagger metadata. Make sure you refer to it using https !!!.Also make sure that CORS is enabled for your logic app, or just use * here. After that you need to restart your app. Otherwise your logic app will not pick it up. There you go. If you want to use it in a Logic app just add the Action App Services, select you API app, and select the action you want to use. And there you go, the following connectors have access to the output of your API app. Pretty straightforward, if you don't forget the Type in your SwaggerResponse-attribute. Using API apps as triggers is somewhat more work. We'll discuss that in part 2.

Announcing the SharePoint Add-in “Export to Word”

Today, we’re glad to announce the FREE SharePoint Add-in “Export to Word”, developed by the team at U2U. This add-in fixes one of those issues that you’ll probably will have come across with in SharePoint, namely generating Word documents based on SharePoint list items. A bit like a mail merge for list items! This functionality has never been out of the box available for regular SharePoint list items. You could achieve something like it on document libraries only, using Quick Parts in Word. But however, that only works for document libraries. Now, what does the add-in allow you to do? It allows you to configure, per SharePoint list, one or more Word templates. You can even upload your own templates! The add-in then allows you to link fields from your selected list to the content of the template. Once your template is completely designed, you can just go to the SharePoint list and export any item to Word using your template. You can even export multiple items in bulk!    Do you want to know more about this add-in? Just go to the official site.Do you want to install it from the Office Store? You can find the add-in here. For a quick start guide on how to work with the add-in, have a look at the following video:   Do note that this is the first version of the Add-in, and we want your feedback to further extend and improve the add-in. You can contact us via the regular ways.

Consuming SharePoint CSOM from an Office 365 app

I’ve been a C# developer for more than five years now. When SharePoint 2013 was released, I started doing development for SharePoint 2013 and later also SharePoint Online. My focus was on developing web services (in combination with the SharePoint App model), native client and mobile applications using the Client Side Object Model. When I was at the Barcelona TechEd conference in 2014, I decided to follow quite some breakout sessions about Office 365 and the “new” Office 365 APIs. It was around that time also that they released the new Office 365 Apps look and feel by means of the new “App Launcher” and the “My Apps” page. Without having the knowledge about Apps for Office 365, I initially thought that these would be quite comparable to Apps for SharePoint. However, Apps for Office 365 are completely different. Apps for Office 365 An app for Office 365 is conceptually: An application that is running externally (i.e. on some website) or standalone (i.e. mobile or desktop). The application can be accessible from within the office 365 website, but also could be surfaced from within Word or Outlook. Integrating somehow with Office 365 (this is not required). Registered in the Azure Active Directory (AAD) that is running behind your Office 365 tenant. Can use the same authentication mechanism as Office 365, resulting in single sign-on. So before you can use your app in Office 365, you have to register it in Azure Active Directory. When registering you app in Azure AD, you also configure the permissions it gets to access the Office 365 services like mail, contacts, events and OneDrive for Business, but also SharePoint! Then I started thinking: “Does this mean that you can register an app in Azure AD and let it access SharePoint online?”. Getting the access token I was eager to discover whether it was possible to access SharePoint using the Client Side Object Model and the Azure Authentication mechanism. Jeremy Thake briefly mentioned in a blog post that it is possible to use the token you get from Azure as the Bearer token in you ClientContext requests.So I created an ASP.NET MVC5 web application, registered it in Azure AD, set the permissions for Office 365 SharePoint Online (see above) and started experimenting. You can get the access token as follows: /// <summary> /// Get the access token for the required resource /// </summary> /// <param name="clientID">The client ID of your app</param> /// <param name="appKey">The app key</param> /// <param name="resource">The resource you would like access to</param> /// <returns></returns> public static async Task<string> GetAccessToken(String clientID, String appKey, String resource) { // Redeem the authorization code from the response for an access token and refresh token. ClaimsPrincipal principal = ClaimsPrincipal.Current; String authorizationUri = "https://login.windows.net"; String nameIdentifier = principal.FindFirst(ClaimTypes.NameIdentifier).Value; String tenantId = principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; AuthenticationContext authContext = new AuthenticationContext( string.Format("{0}/{1}", authorizationUri, tenantId), new ADALTokenCache(nameIdentifier) ); try { // Get the object identifier String objectId = principal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; // Authenticate AuthenticationResult result = await authContext.AcquireTokenSilentAsync( resource, new ClientCredential(clientID, appKey), new UserIdentifier(objectId, UserIdentifierType.UniqueId) ); return result.AccessToken; } catch (AdalException exception) { //handle token acquisition failure if (exception.ErrorCode == AdalError.FailedToAcquireTokenSilently) { authContext.TokenCache.Clear(); } } return null; } You obtain the values for the ClientID and AppKey from the application page in Azure AD. You typically store the values for these properties in the configuration file of your application. Now what is the Resource you have to supply? Well the resource is as follows: If you want access to the discovery service: https://api.office.com/discovery/ If you want access to a SharePoint Online site: https://tenant.sharepoint.com/ If you want access to the SharePoint Admin site: https://tenant-admin.sharepoint.com/ … So in order to access a SharePoint, you can get the access token as follows: String clientID = ConfigurationManager.AppSettings["ida:ClientId"] ?? ConfigurationManager.AppSettings["ida:ClientID"]; String appKey = ConfigurationManager.AppSettings["ida:AppKey"] ?? ConfigurationManager.AppSettings["ida:Password"]; String spSiteUrl = "https://tenant.sharepoint.com"; String accessToken = await GetAccessToken(clientID, appKey, spSiteUrl) Accessing a SharePoint Online Site In order to be able to use this token for your ClientContext, you need to set the Authorization Header on each webrequest the clientcontext sends out: ClientContext clientContext = new ClientContext(spSiteUrl); clientContext.ExecutingWebRequest += (sender, e) => { e.WebRequestExecutor.WebRequest.Headers["Authorization"] = "Bearer " + accessToken; }; You can now access this site through the clientcontext you created (taking into account the permissions you’ve set in Azure AD). In case you do not have the permissions to access something through the clientcontext, you’ll typically get a UnauthorizedaccessException. Research Tracker application Jeremy Thake often refers to a cool Office 365 project that combines different application types to access the same data in your SharePoint site. You can find these projects on GitHub.One of these projects uses the SharePoint REST API to access a SharePoint site, create lists, manage list items. I cloned this project and extended it to also include the functionality by means of CSOM. You can also find this project on GitHub.

Presenting @ the Belgian SharePoint Saturday and Techorama

This month I had the privelege to present a session at the Belgian SharePoint Saturday and the Techorama conference. As promised you can download both slidedecks at the links below:SharePoint Saturday: The SharePoint 2013 Design Manager: From HTML to SharePoint (2,2MB)Techorama Building a provider-hosted SharePoint app with ASP.NET MVC5 (726,8KB)

New version of U2U CAML Query Builder

The original U2U CAML Query Builder has been around for many years, and is being used by many SharePoint professionals. So we thought it was time for giving it some small changes, and bringing it to version 4.2.0.0. The query builder now uses CSOM for connecting to SharePoint, and it also allows connecting to Office365 now.Next to these changes we also have two smaller changes: The different types of queries that can be created has been reduced to two for simplification. We added some tabs for directly copying Server- and Client-side code: There you go, I hope you’ll enjoy it as much as previous versions.We’ll try to get you some more CAML query goodies later ! For now: you can find the Query Builder at http://u2u.be/software. (function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/nl_NL/all.js#xfbml=1"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); Tweet !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');