Building real o365 SharePoint apps

Preview:

DESCRIPTION

My presentation for #SPSNY About my experience building commercial apps for office 365 hosted SharePoint

Citation preview

How I built our first commercial SharePoint hosted app

Lessons learnt from building the KWizCom Cascading LookApp

KWizCom Corporation

• Founded in 2005

• Headquartered in Toronto

• Global vendor of SharePoint Add-Ons

• 5000+ customers worldwide

Shai Petel

Director of Research and Development at KWizCom

MCPD, MVP: SharePoint

shai@kwizcom.com | @shaibs | http://kwizcom.blogspot.com

Overview

OVERVIEWSharePoint apps, your options

SharePoint app store

Provided Hosted?

SharePoint Hosted?

Use JSLink to customize columns and list views

Build app parts to display information whoever you wish, from any data source you want.

OVERVIEWApp licensing

Use Microsoft Store licensing

Per seat, unlimited threshold

Subscription or Purchase*

Auto generate trial liense

Or, build your own licensing service.

OVERVIEWPublish a new version

OVERVIEWUpdates, upgrades

Go to site contents

Updates will show up here, next to the app. Click the link

to update your app.

App web vs. Host web

APP WEB VS. HOST WEBApp login problem, single sign on

App login problem, single sign on

App web on different url, requires separate login

Single sign on in place for most cases

Single sign on will not work for resource files (css, js, images, etc…) but only in iframes

APP WEB VS. HOST WEBIE 8,9 known issue with trusted sites

IE 8,9 known issue with trusted sites

Known issue on IE 8, 9

Requires adding both domains to trusted sites

Read more: KWizCom KB http://support.kwizcom.com/KnowledgebaseArticle50208.aspx

APP WEB VS. HOST WEBProvisioning files to host web

Provisioning files to host web

Find site assets library, create a sub folder for your app and upload the files there

Cannot read files, only upload

Minimize your foot print as files are not cleaned up on uninstall

APP WEB VS. HOST WEBLoading additional resources from app web

Loading additional resources from app web

After single sign on issue resolved

In effort to minimize footprint, only provision the file that will handle the single sign on issue

Can use host web URL, will redirect to app web URL automatically

APP WEB VS. HOST WEBCheck for app license from host web

Check for app license from host web

Only for SharePoint hosted apps

Only within the app site itself

From host web, must use an iframe (licensechecker.aspx)

Using JSLink

USING JSLINKPower of client side rendering

Customize the way your columns and views look

Add special logic in editing your lists

USING JSLINKHow to register for specific field, not for type

How to register for specific field, not for type(function () { var ageFiledContext = {}; ageFiledContext.Templates = {}; ageFiledContext.Templates.Fields = { "Age": { "NewForm": ageFiledTemplate, "EditForm": ageFiledTemplate } }; SPClientTemplates.TemplateManager.RegisterTemplateOverrides(ageFiledContext);})();function ageFiledTemplate(ctx) { var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx); formCtx.registerGetValueCallback(formCtx.fieldName, function () { return document.getElementById('inpAge').value; }); return "<input type='number' id='inpAge' min='18' max='110' value='" + formCtx.fieldValue + "'/>"; }

Register to field name “Age”, or field

type “choice”

How to register for specific field, not for type Pass field name in query stringfield.set_jsLink("mycsr.js?FieldName=Status");field.update();

Catch it in the JS file, use it to register your templatevar scripts = document.getElementsByTagName('script');for (var i = 0; i < scripts.length; i++) { if (scripts[i].src.toLowerCase().indexOf("mycsr.js") >= 0) { var currentField = KWizComUtilities.GetQueryStringParameterByName("FieldName", scripts[i].src);… currentFieldRendering.Templates = {}; currentFieldRendering.Templates.Fields = {}; currentFieldRendering.Templates.Fields[currentField] = {}; currentFieldRendering.Templates.Fields[currentField].EditForm = myTemplate; currentFieldRendering.Templates.Fields[currentField].NewForm = myTemplate; SPClientTemplates.TemplateManager. RegisterTemplateOverrides(currentFieldRendering);}

How to register for specific field, not for type

TIP: Query strings are very important. You need SharePoint to tell your external website important information about where in SharePoint it is coming from.

USING JSLINKSupport MDS

Notice it always stay on the same page

Support MDS

On MDS enabled sites, most online samples will not work after few page navigations

When you revisit a page, document.ready event does not fire

Instead, you must register your init code here:RegisterModuleInit(jsfileName, initHandler);

USING JSLINKStore additional settings

Store additional settings Additional column settings can be stored in field schema or query string In schema, under<Customization> <ArrayOfProperty> <Property> <Name>x</Name> <Value>Y</Value> </Property> </ArrayOfProperty></Customization> Schema changes might break OneDrive support in document library For simple settings, you can use JSLink query string

App License

APP LICENSECheck for license using script

Check for license using script

Check for license using script Requires adding remote endpoint to

https://verificationservice.officeapps.live.com Request must come from the app web Get a collection of licenses, sometimes expired

licenses as well

licenseCollection = SP.Utilities.Utility .getAppLicenseInformation(context, '{cd8d046c-91d4-401f-825d-494e6c2776c5}'); context.executeQueryAsync(onRetSuccess, onRetFail);

On Success:if (licenseCollection.get_count() > 0) { license = licenseCollection.get_item(0) .get_rawXMLLicenseToken(); processRawXmlLicense(license);}

Process license:

var request = new SP.WebRequestInfo();request.set_url("https://verificationservice.officeapps.live.com/ova/verificationagent.svc/rest/verify?token=" + encodedTopLicense);

request.set_method("GET");response = SP.WebProxy.invoke(context, request);

context.executeQueryAsync(onVerifySuccess, onVerifyFail);

On Success:

var verificationResponse = response.get_body();var xmlDoc = $.parseXML(verificationResponse);var $xml = $(xmlDoc);var licenseType = $xml.find("EntitlementType").text();var licenseIsValid = $xml.find("IsValid").text().toLowerCase() == "true";var licenseIsTest = $xml.find("IsTest").text().toLowerCase() == "true";var isExpired = $xml.find("IsEntitlementExpired") .text().toLowerCase() == "true";

Prompt user on license issues, once is enough

APP LICENSETest licenses

Test licenses

Create / Manage using code or tool: http://code.msdn.microsoft.com/office/SharePoint-2013-Import-f5f680a6/view/SourceCode#content

Don’t forget to check if a license is a test license

Block test licenses on production build, or show a message

SharePoint 2013 Import, validate, and manage app licenses.zip

Adding a ribbon button

ADDING A RIBBON BUTTONCheck for license using script

Adding a ribbon button Limited use of CustomAction element allows to add ribbon buttons

CommandAction can only open a page or a popup<CommandUIHandler Command="cmd1"CommandAction="~appWebUrl/Pages/ListDialog.aspx?{StandardTokens}&amp;SPListItemId={ItemId}&amp;SPListId={ListId}"/>

Open as popup option<CustomAction … HostWebDialog="TRUE"HostWebDialogHeight="600" HostWebDialogWidth="1050"

Scripts are blocked

Single sign on issue cause image to be missing…

Will start working once the user had the iframe log him

into the app web.

Protecting your code

PROTECTING YOUR CODEProtect JS code

Protect JS code

Have app.debug.js with your source

Upon publish, obfuscate it and save in app.js

Consider not publishing debug.js with your app to protect your full source

PROTECTING YOUR CODEDebug

Debug client code, or on your server. Nothing to debug on SharePoint since your app does not run on SharePoint.

Debug

Use fiddler, IE developer tools

On your customer’s site you will still get the obfuscated script.– For files in the app site, live with it!– For provisioned files, upload the source file for easier

debug

On prem vs. o365

ON PREM VS. O365API is different

API is different

Client side API is different and more hardened usually in O365

Basic changes in functionality, some APIs are blocked while other behave different

Example: field.update will cancel field.set_schemaxml on o365 only

ON PREM VS. O365Updates

Updates

On O365, updates are regularly pushed and installed throughout the farm.

Not all tenants are upgraded at the same time! Your dev/test might be older or newer than some tenants.

ON PREM VS. O365Maintenance

Maintenance

App break. You need to keep an eye out.

Updates sometime will break your app. (App / user throttling)

Support and publishing updates is key to success.

QUESTION?

Shai Petel

Director of Research and Development at KWizCom

MCPD, MVP: SharePoint

shai@kwizcom.com | @shaibs | http://kwizcom.blogspot.com

Recommended