Thursday, February 28, 2013

SharePoint 2013 hosted App License check

How do you manage/enforce licensing on a fully SharePoint hosted app with JavaScript only?

You need a couple of things:

1. JavaScript that checks for the license.

2. Landing pages, telling you that your license has expired or is invalid.

3. An app that helps you creating test keys for testing your App with licensing.


Is the License code valid for the App store?

Yes, the code is valid, because it is implemented in Site Tree View app that has been approved for the App Store.

1. JavaScript

After searching the web for a solution, I found this http://social.msdn.microsoft.com/Forums/en-US/appsforsharepoint/thread/f022893c-3927-4471-8ae8-7dbcd0b8e5fe

However I needed a more clean solution and rewrote the script. Please note that the code depends on jQuery.Cookie.js, JQuery.xml2json.js plugin and the SP client side libraries.

window.SF = window.SF || {};
window.SF.LicenseConstructor = function($) {

    var licenseCollection;

    var response;

    var licenseSettings;

 

    this.Check = function (s) {

        licenseSettings = s;

        var token = $.cookie(licenseSettings.productId);

        if (token) checkToken(token);

        else {

            licenseCollection = SP.Utilities.Utility.getAppLicenseInformation(licenseSettings.context, licenseSettings.productId);

            licenseSettings.context.executeQueryAsync(onRetrieveLicenseFromSPSuccess, onRetrieveLicenseFromSPFailure);

        }

    };

 

    function onRetrieveLicenseFromSPSuccess() {

        var topLicense;

        var encodedTopLicense;

 

        if (licenseCollection.get_count() > 0) {

            topLicense = licenseCollection.get_item(0).get_rawXMLLicenseToken();

            encodedTopLicense = encodeURIComponent(topLicense);

        } else {

            Redirect(licenseSettings.licenseUrl);

        }

 

        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(licenseSettings.context, request);

        licenseSettings.context.executeQueryAsync(onVerificationCallSuccess, onVerificationCallFailure);

    }

 

    function onRetrieveLicenseFromSPFailure(sender, args) {

        Redirect(licenseSettings.licenseUrl);

    }

 

    function onVerificationCallSuccess() {

        var xmltoken = response.get_body();

        $.cookie(licenseSettings.productId, xmltoken, {

            expires: 180

        });

        checkToken(xmltoken);

    }

 

    function checkToken(xmltoken) {

        var token = $.xml2json(xmltoken);

        switch (token.EntitlementType.toLowerCase()) {

            case "free":

                break;

            case "paid":

                break;

            case "trial":

                if (token.IsEntitlementExpired.toLowerCase() === "true") Redirect(licenseSettings.expiredUrl); // Trial app has expired!

                break;

        }

    }

 

    function onVerificationCallFailure() {

        Redirect(licenseSettings.licenseUrl);

    }

 

    function Redirect(url) {

        window.location.href = url;

    }

    return this;

};

 

window.SF.License = new SF.LicenseConstructor(jQuery);

2. Landing pages

Include the SF.License.Check(…) in be beginning of you document onload after the SP libraries has loaded.

var settings = {

    context: SP.ClientContext.get_current(),

    licenseUrl: "http://domain/nolicense.html",

    expiredUrl: "http://domain/trialexpired.html",

    productId: "{[App ID guid]}"

};

SF.License.Check(settings);

 

Finally you need to specify the verificationservice endpoint in the AppManifest.xml for your app.

https://verificationservice.officeapps.live.com/ova/verificationagent.svc

image

3. Test

Now you need to test you licensing code. Do this by installing a test License key, so you are able to test your app. Further reading on the subject can be found on Licensing your apps for SharePoint.

Direct link to the license manager app: 4760.LicenseSPAppSample.zip

Tuesday, February 19, 2013

SharePoint 2013 StandardTokens with IntelliSense

Update: 21 february 2013. Fixed a problem with the json not being valid in Internet Explorer 8. 

Problem:  The standard function getQueryStringParameter used to get the querystring parameters in SharePoint Apps is a bit poor. It does not offer any help on IntelliSense and will spilt the url every time you request a value, making it a bit slow function to use.

I love IntelliSense, especially when working with JavaScript. So I came up with this:

Solution:

window.SF = window.SF || {};

 

window.SF.CreateQueryString = function () {

    // Added defined properties for IntelliSense.

    var q = {

        SPAppWebUrl: '',

        SPClientTag: '',

        SPHostLogoUrl: '',

        SPHostTitle: '',

        SPHostUrl: '',

        SPItemId: '',

        SPItemUrl: '',

        SPLanguage: '',

        SPListId: '',

        SPProductNumber: '',

        SPRecurrenceId: '',

        SPRemoteAppUrl: '',

        SPSite: '',

        SPSiteCollection: '',

        SPSiteUrl: '',

        SPSource: ''

    };

    var hash;

    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');

    for (var i = 0; i < hashes.length; i++) {

        hash = hashes[i].split('=');

        var val = decodeURIComponent(hash[1].replace(/\+/g, ' '));

        q[hash[0]] = val;

        q[hash[0].toLowerCase()] = val;

    }

 

    return q;

};

 

window.SF.Response = {

    QueryString: SF.CreateQueryString()

};

Usage:
Start with adding the javascript file with the code to the _references.js file, in order to get the IntelliSense going.

clip_image001

Now accessing the Standardtokens is like an easy game.

If you want to access other parameters in the url, there are sadly no IntelliSense, but the parameters are still available in a case mode and lower case mode. This is very handy when creating custom properties for an App Part and accessing those properties from the App Part iframed page.

<Content Type="html" Src="~appWebUrl/Pages/SiteTreeViewPage.aspx?{StandardTokens}&amp;showrootweb=_showrootweb_" />

Makes the “showrootweb” parameter available in the QueryString.

var showRootWeb = SF.Response.QueryString.showrootweb;

It does not matter what case the parameter have in the url, because it will always be available in lowercase and its normal form.

Monday, February 18, 2013

SharePoint 2013 App Part scrollbars

I had this problem the other day with no scrollbar showing up when the content of my App Part was larger than the iframe.

It turned out to be the /_layouts/15/1033/styles/themable/corev15.css that was the reason. This file is included on my App Part aspx page, in order to get the same style as the rest of the site.

The simple solution to the problem was just to add a style tag with overflow to the body tag on the App Part aspx page.

<body style="overflow:auto;">

Result:

image

If you wanner resize from your iframed page, its possible by use of the postMessage command.

Found on the forum posted by Yina Arenas

<script type="text/javascript">

    window.onload = function () {

        var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);

        var regex = new RegExp(/[Ss]ender[Ii]d=([\daAbBcCdDeEfF]+)/);

        results = regex.exec(this.location.search);

        if (null != results && null != results[1]) {

            target.postMessage('<message senderId=' + results[1] + '>resize(500,200)</message>', '*');

        }

    }

</script>

Futher more Richard diZerega has written this very good blog post on Optimizing User Experience of Apps for SharePoint 2013

Wednesday, February 13, 2013

FullControl is not allowed in apps on the SharePoint 2013 App Store.

When building an app for SharePoint App Store, the FullControl permission is not allowed. This was not easy to find and is very well “hidden” in the documentation on permissions. However building local deployed apps the FullControl permission is allowed.
To quote Microsoft: Only Read, Write, and Manage rights are allowed for Office Store apps. If you try to submit an app to the Office Store that requires FullControl rights, your app is blocked from submission.
http://msdn.microsoft.com/en-us/library/fp142383.aspx#Perm_rightlist