Whether you have been following the guidance for Centralized Deployment of Web Add-ins or you do not have Office 365 and you want to create a SharePoint catalog for deployment, but realize it has limitations:
App catalogs on SharePoint do not support add-in features that are implemented in the VersionOverrides node of the add-in manifest, such as add-in commands.
That is where this new tool that a fellow co-worker (Marty Andren) and I created will come in handy: The Web Add-in Side Loader Tool. Here is the link to the GitHub where it and it’s documentation are located:
A customer I was working with wanted help developing a fully on-premises Outlook web add-in. By this, they wanted no part of it to reach out to the Internet (Azure or Office 365). They wanted:
To connect to their internal Exchange server
An internal IIS website
And no references to the Internet (including the Office.js).
This is the topology we are trying to achieve:
If you have developed an Office Web Add-in lately, you find it is inherently biased to the Internet. Even the samples and solutions provided assume Office 365/Exchange and Azure websites. In a default, new Visual Studio solution, the links to the Office.js libraries and stylesheets are all pointing to the web. And, so as you might expect, there are some challenges to getting it to work on-premises only.
This posting covers what you must do to get such a solution to work, including getting past some pitfalls.
First, you have to download the Office.js files locally. And especially for Outlook because the Office.js files that are provided by default in your solution folder (“for offline debugging” as part of VS2015U3 or earlier) are missing some features to work with specific builds of Outlook 2013 and Outlook 2016. You will run into some strange “type” missing and “Office not defined” errors if you forget this step.
Once you have downloaded the Office.JS files, you will delete all the files under the Scripts\Office\1 folder and copy in the contents you downloaded in step 1.
Comment out that line and add the following two lines:
[code language=”html”]
<!– <script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript></script> –>
<script src="../../Scripts/Office/MicrosoftAjax.js" type="text/javascript"></script>;
<script src="../../Scripts/Office/1.1/office.js" type="text/javascript"></script>;
[/code]
Once you have developed your solution, you must setup your IIS server. In general here is what you must do:
The IIS Server must have ASP.NET installed, it must have .NET4 installed and you must have the Web Application role enabled.
Open IIS Manager
Create a site, and figure the folder path
Convert the site to an Application
Apply an SSL certificate that is already trusted on all your client computers or that has a root certificate authority that is trusted on all your client computers. If you browse to your site using HTTPS and you get a RED warning about an untrusted site, then the certificate is not trusted or properly setup.
Next, and this was a major issue to troubleshoot, your Exchange Web Services certificate cannot be expired. If it is, any EWS call you make will return “succeeded” but will be blank – missing data. Digging into the logs you might find an error: “ErrorInvalidClientAccessTokenRequest” The Microsoft Exchange Server Auth Certificate that is used for OAuth needs to be updated. To do this you have to be logged into the Exchange server as administrator:
Run this cmdlet to identify the thumbprint of the certificate being used for OAUTH:Get-AuthConfig | FT currentcertificate*
Run this cmdlet to identify the thumbprint of certificates used for other Exchange servers (IIS, SMTP, etc.):Get-ExchangeCertificate | Fl *thumb*
Run these cmdlets to configure Exchange to use the valid certificate (copy/paste the thumbprint from the Get-ExchangeCertificate output):$today = Get-Date
Set-AuthConfig -NewCertificateThumbprint newthumbprint -NewCertificateEffectiveDate $today -Force
Run this cmdlet to make sure the changes are published to the environmentSet-AuthConfig -PublishCertificate
Run this cmdlet to verify the certificate thumbprintGet-AuthConfig | FT currentcertificate*,previouscert*
Now you can deploy your solution to IIS, update your manifest to point to the IIS server (do not forget the HTTPS) and then install it on the Exchange Server Control Panel (ECP) under the Organization / Add-ins option as a mandatory add-in.
Finally, and this last bit is important: IF USING OUTLOOK 2013 or OUTLOOK 2016, YOU MUST BE LOGGED INTO WINDOWS ON THE SAME DOMAIN AS YOUR EMAIL. I know, I know… for some folks this sucks. I have reported this to our product team and they are looking into it. If you are not logged into the same domain controller as your email address is registered, you will not see the advertised add-in. It will load in Outlook Web Access (OWA), but will not appear in Outlook 2013/2016. The exact cause of this problem is unknown, but hopefully it will be addressed in a future version of the product (Exchange or Outlook or both).
Setting up for 100% on-premises is difficult, but it CAN be done. There are a lot of steps, but if you follow the above prescription, you should get it to work. In time, I hope to see this process get easier. But in an online world where Microsoft Office 365 and Azure are main focus, “old fashioned” on-premises solutions are going to require a little more elbow grease.
NOTE: This entry was contributed to by Arthel Bibbens (MSFT) / Exchange PFE. You can follow his posts on this topic here:
I recently worked with a developer to deploy an Office add-in within an Exchange 2013 on-premises environment. This project highlighted a capability of Exchange and Outlook that is a huge shift in the way mail add-ins are developed, deployed, and maintained. Let’s take a look at the key components of Exchange 2013 that support this…
It is sometimes tough to determine what is happening in a production environment and you need to get logging information from the add-in to see what is happening. How can you do that?
One way is to build a console.log() option into your add-in that looks for a Debug flag in the manifest. So, you will create two manifest, one that enabled Debugging and another than disables it. More on that in a bit. To start, here is the basic class I created in order to handle this:
[code lang=”javascript” collapse=”true” title=”click to expand if the github.com embedding below is not visible.”]
/*!
* logger JavaScript Library v1.0.1
* http://davecra.com
*
* Copyright David E. Craig and other contributors
* Released under the MIT license
* https://tldrlegal.com/license/mit-license
*
* Date: 2016-08-09T12:00EST
*/
var console = (function () {
"use strict";
var console = {};
console.initialize = function () {
///
<summary>
/// Add a textarea/console to the bottom of the page and then setup the logger
/// </summary>
/// <param name="DebugMode" type="Boolean">If debug mode enabled – we show the console for logging</param>
var debugMode = getParameterByName("Debug") == "true";
if (debugMode) {
// add the console to the screen
$("body").append("<textarea id=’log’ style=’width:100%’ cols=’2000′ rows=’7′ wrap=’off’></textarea>");
$("body").append("<button id=’saveLog’>Copy Log to Clipboard</button>");
$("#saveLog").click(function () {
var field = $("#log");
field.select();
document.execCommand("copy");
});
}
console.log = function (msg) {
///
<summary>
/// GLOBAL: Logs to the textarea on the page
/// </summary>
/// <param name="msg" type="string">The message to log</param>
if (debugMode) {
var d = new Date(Date.now());
var current = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds();
var data = $("#log").val();
$("#log").val(current + " – " + msg + "\r\n" + data);
}
};
}
function getParameterByName(name) {
///
<summary>
/// Get a parameter form the URL
/// </summary>
/// <param name="name" type="String">Name of the parameter to get from the query string</param>
/// <returns type="String">Value of the paramater</returns>
var url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return ”;
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
return console;
})();
[/code]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
To enable logging you will add the following code to your initialize:
[code language=”javascript”]
console.initialize();
console.log("Started…");
[/code]
Once initialized this will add a TEXTAREA to the bottom on the page where the log entries will be loaded. Additionally, it will place a “Copy To Clipboard” button at the bottom that when clicked will copy the contents of the TEXTAREA to the clipboard so that they can be forwarded to you as needed.
Once implemented and initialized, you can add a console.log() anywhere you want in your code to add an entry to the log. Now, how do you turn this on. What this is doing in initialize is to see if the debug flag is set in the Query String of the SourceLocation setting in the Manifest. To turn on debugging, you change the following line as such:
That is it. From this you will be able to share two manifests with your users/administrators. The first one will be your default production manifest and the second one can be loaded if you need debugging information from the add-in.
First, let’s discuss the architecture and from an Outlook/Exchange perspective:
First, you load your manifest on the Exchange server. The manifest is simply an XML file that contains pointers to your web site (on the IIS server).
When you load Outlook Web Access and click the add-ins button, the Add-ins pane will appear and each application manifest you have loaded will appear in the list.
When you click on one of the add-is, the task pane will load (in Orange) and your site (located on the IIS Server) will populate in the pane.
The problem arises when you have but ONE Exchange server or ONE developer account for development and test. Developers want to be able to debug the code they are working with which typically loads from the local instance of IIS Express (localhost). But testers need to be able to work with the latest release build to test.
So, how do you do this?
The key is in the Manifest file. If you open the Manifest file, you will see the <Id> field. This is the most important piece, but there are other areas you should/need to update as well. What you will essentially have is two copies of your manifest file:
The first file will use the default ID provided in the project, it should have a name like Developer Release and it will point to your localhost (this is default with the setup of a new Web Add-in).
The real key is having different ID’s and publishing them separately. In Visual Studio the developers will have everything set as shown above (essentially leave everything as default). When they are ready to drop a build to the testers:
Right-click on the Website project and click Publish. Follow the steps to publish the site to the Testers server.
Right-click on the Manifest project and click Publish. Click the “Package the add-in” button.
In the resulting dialog, enter the URL to the Testers site, This will ONLY update the URL, but not change the ID.
Open the <manifest>.xml file in Notepad and then change the fields as shown above:
Modify the ID
Change the name so that you can identify which one is which
Verify the URL is correct.
At this point you are ready to go. And you can create MULTIPLE versions of your manifest. If for example you need one for Testers, one for Developer and then another for Pilot and yet another for experimental testing (each pointing to different IIS instances, sites or even to the Cloud (Azure). You can create as many manifests as you need this way, have them all show up in the Add-ins task pane allowing the testers/users to select the one they wish to work with.