Softlanding: SharePoint Consulting & Managed Services | Vancouver, BC

    ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​Delivering Solutions, Empowering Clients

    Softlanding helps organizations be their best by providing technology solutions and services that make them more productive. Softlanding specializes in Microsoft enterprise technology platforms, leveraging a combination of cloud, on-premises and hybrid configurations to increase productivity from the data center on out to end business users. Platform specialties include SharePoint, Azure, Office 365, Power BI, EMS and System Center.​​


     SharePointROI Sustainment Services

                                                           SharePointROI is a, fixed- fee managed service providing end-to-end SharePoint sustainment, user support and adoption services. Eliminate SharePoint expertise hiring headaches and get the most out of your SharePoint investment.​

    Learn More >>

     Current Openings


    Looking for a career? We're on the lookout for fun, talented people to join our growing teams. If you're looking to progess your career, apply here:

    Openings >>

     

     

    Takes Place:
    Description: Microsoft Canada opens its datacentres to Canadian businesses. Learn how Softlanding and Microsoft are working together to deliver the cloud Canada-wide.

     Featured Solutions

    Connecting Talent and Resources for Better Performance

    Corix finds a scalable solution to communication issues and improves organizational performance in the process. Read more here

     

     Hidden Title

    Strategic IT to Support Organizational Change

    The BC First Nations Health Authority finds a strategic partner for a major transition, plus continued IT support for successful delivery of essential services. Read more here​. 

     

     


    Posted on:
    Categories: SharePoint
    Description: How to enable IntelliSense in Visual Studio for SharePoint-addin project type
    ​Let me start this post with a statement I'm a developer and developers love IntelliSense. If you are a developer too, you know what I'm talking about! Recently, I created a SharePoint-hosted add-in in Visual Studio 2013. While starting to code, I recognized that IntelliSense wasn't working correctly. Here is an example I tried to create a new ClientContext, but as you can see, IntelliSense is not providing the proper functions nor properties In fact, all the JSOM functions and properties were missing, which makes coding a SharePoint-hosted add-in needlessly difficult. IntelliSense is a very helpful feature, and I refused to continue coding without proper IntelliSense. So I started some investigation to see why IntelliSense wasn't able to show the JSOM stuff. First, I checked the _references file which is usually located in the project's Scripts folder. This file was existing, and its content looked correct. In a nutshell, this file is referencing the SharePoint JSOM libraries and the files listed here are supposed to be added to the IntelliSense database – but for some reason, this isn't working for my current project. My next step was to check if the _references file is actually used by Visual Studio to feed the IntelliSense database. To check this, I opened <Tools> <Options> in Visual Studio. In the text box at the top, I typed in 'JavaScript' and the following dialog is shown I clicked on References just below IntelliSense to see which libraries were included to build the IntelliSense database. The file _references.js was included just like some other libraries. Although _references file was listed here, it was not used to update the IntelliSense database. The basic configuration looked ok, and so I was looking for a workaround to get IntelliSense to show the functions and properties of the JSOM objects. I manually downloaded the file SP.runtime.js from SharePoint and added it to the Scripts section of my Visual Studio project. Because I did not want this file to be re-deployed back to SharePoint each time the app gets deployed to SharePoint, I changed the Deployment Type of this file to NoDeployment and I repeated this with the file SP.js. Time for a new test - and this time IntelliSense was working as expected! Now the IntelliSense database has been updated properly and was able to show all functions and properties which are part of the JSOM libraries – and this makes coding with JSOM a lot easier! It looked like Visual Studio wasn't able to access the referenced files which are listed in _references.js. Adding them as downloaded copies to the Scripts folder in my Visual Studio project enables IntelliSense to access them and update its internal database. As long as those files are kept locally and are not deployed back to SharePoint, this workaround can be used to fix the initial IntelliSense problem. But keep in mind as those files are local copies now, they won't get updated automatically!


    Posted on:
    Categories: Office 365;SharePoint
    Description: How to code Cross-Domain access within a SharePoint-hosted add-in
    ​Recently I was debugging a SharePoint-hosted add-in, which should be used in 'SharePoint online' and in 'SharePoint on-premises'. The initial situation was this the add-in was working on 'SharePoint online' as expected, but when trying to run it on SharePoint on-premises, an error was displayed immediately. The error reported that the response received from the server was unexpected. Because this error happened as soon as the add-in was trying to access the host web for the first time, I checked this part of the add-in's code first. Let's see what this code is doing. If you run a SharePoint add-in, SharePoint is providing some additional parameters via the URL. In my local development environment, the URL of the add-in looks like this http//app-af2e37d0f342ef.apps.domain.com/sites/ABAT/AP/Pages/Default.aspx?SPHostUrl=http//sp2013-ow/sites/ABAT&SPLanguage=en-US&SPClientTag=0&SPProductNumber=15.0.4797.1000&SPAppWebUrl=http//app-af2e37d0f342ef.apps.domain.com/sites/ABAT/AP The above code is trying to extract the values for SPHostUrl and SPAppWeb from this URL. "SPHostUrl" is the URL of the add-in's host web (the web that this add-in should be used in) and "SPAppWeb" is the URL of the internal web of this add-in (the web that add-ins are usually using to store their configuration data and that's not accessible to the common user). As you can see, both URLs are very different, and they are pointing to different domains. The host URL starts with http//sp2013-ow and the app web URL starts with http//app-af1e37d0f372ef.apps.domain.com. That's intended because SharePoint add-ins should be separated from common SharePoint webs and that's done by providing a separate app domain (it's usually called domain separation). In SharePoint on-premises, this app domain is configurable via the Central Administration, in SharePoint online the app domain is configured upon setting up the tenant automatically. If a SharePoint add-in needs to access its host web, it first needs to have proper permissions. Usually, this is done by adding the desired permissions to the AppManifest.xml file. The following image shows an example When using the add-in for the first time, a user needs to trust this add-in and while doing so, these permissions are granted to the add-in. But that's just the easy part. With proper permissions, the add-in is just allowed to access its host web, but some lines of code need to be added as well to finally enable the add-in to access the host web. We have just learned that SharePoint add-ins are usually existing in a different domain. To be able to access the web which is existing outside of the add-in's app domain, the add-in needs to perform something which is called Cross-Domain Access. Let's have a look back on the initial code. This code is trying to get access to the host web like this var hostWebContext = new SP.ClientContext(getRelativeUrlFromAbsolute(hostWebUrl)); The code takes the URL of the host web and creates a new ClientContext based on this URL. Although this does not take into account that we need to perform a Cross-Domain access, this line appears to be working in a SharePoint online environment. In other words getting the host web object like this is working in SharePoint online, although it is not the recommended way of doing this var hostWeb = hostWebContext.get_web(); You can find some posts on the internet providing the above code as a sample. I don't want to speculate, why this is working in a SharePoint online environment and not in a SharePoint on-premises environment. Let' focus on how to do it the right way. Microsoft published a great article which is explaining the details. You can access this article by clicking on this link. The recommended way how to access an add-in's host web is this // Get URL of the host web var hostWebUrl = getQueryStringParameter("SPHostUrl"); // Get URL of the app web (web where the add-in is living) appWebUrl = getQueryStringParameter("SPAppWebUrl"); // Get context of host web to be able to access it context = new SP.ClientContext(appWebUrl); var factory = new SP.ProxyWebRequestExecutorFactory(appWebUrl); context.set_webRequestExecutorFactory(factory); hostWebContextSite = new SP.AppContextSite(context, hostWebUrl); The first two steps are almost the same the URLs need to be extracted from the add-in's URL. The next step is that we need to create a new client context based on the URL of the add-in's web (not the host web!). To enable the Cross-Domain access, a new object of type ProxyWebRequestExecutorFactory needs to be created. This object will take care of handling the Cross-Domain access we are about to establish. To be able to create that object, another JavaScript library needs to be loaded first. This could be done within the content of the page or by manually loading the library. This is how the library is loaded when using the first approach The additional JavaScript library (SP.RequestExecutor.js) is loaded by the last line in the above snippet. This new RequestExecutor object is then passed to the client context by a call to set_webRequestExecutorFactory(). Now the client context can handle a Cross-domain access. Technically this is achieved by installing a local proxy object with is handling the cross-domain data transfer. But there is an additional subject we need to take care of too. The way we need to access an object which is existing in the host web, changed also. Instead of using this code var hostWeb = hostWebContext.get_web(); we now need to get a web object which is existing in the host web like this var oWeb = hostWebContextSite.get_web(); hostWebContext.load(files); hostWebContext.executeQueryAsync(onSuccess, onFail); As you can see the host web is accessed by using the hostWebContextSite object now – and not by using the context object directly. If you are accessing an add-in's host web like this, your add-in will run on SharePoint on-line and SharePoint on-premises – and probably won't have any issues with Cross-Domain access anymore. Before I close this blog post, here is another tip which usually helps me when debugging a SharePoint-hosted add-in. I usually change the onFail functions used by executeQueryAsync() like this function onFail(sender, args) // Called if operation not has been successful ReasonWhyFailed = args.get_message(); StackTrace = args.get_stackTrace(); With this modification, you will get a better error description if something went wrong.

    ​​​​​