Category Archives: SharePoint

Upgrading sp-pnp-js to 1.0.5

You have already working SharePoint project which is using SharePoint PnP JavaScript Core Component library. (https://github.com/SharePoint/PnP-JS-Core). You want to update it or you accidently updated it from earlier version to 1.0.5.

I have used in this example Patrick Rodgers’ Yeoman sample project (https://www.npmjs.com/package/generator-sp-pnp-js-sample).

Before you will do anyting everything works fine and if you execute gulp build you will get successful build.

update_sp-pnp-js_before_update

Updating sp-pnp-js

Before we can update to new version of the sp-pnp-js package, we need to check how it’s installed to the project. This can be done by checking the project.json file. It has two sections for external packages (dependencies and devDependencies).

update_sp-pnp-js_pnpversion_100

We will execute

npm install sp-pnp-js@latest --save

to update sp-pnp-js to latest version. Note that you need to use –save parameter instead of –save-dev, because sp-pnp-js is in dependencies section instead of devDepencencies.

update_sp-pnp-js_update_sp-pnp-js

You can see that we have now the 1.0.5 version which we were looking for. Now if we will try to build our project, we notice that it will fail. At first everything seems to go fine.

update_sp-pnp-js_build_fails1

but then we can see only red error lines and lots of those.

update_sp-pnp-js_build_fails2

Updating Typescript

Now it’s time to read the manual or something like that. In our case explanation comes from GitHub commit comments. “Updates to TypeScript 2.0”. Ok. What this means? What version we have? It’s easy to find out. You can see it right after gulp build has started. It says that our version is 1.8.10.

update_sp-pnp-js_typescript_version_1_8

Execute

npm install typescript@latest --save-dev

Note that now you need to use –save-dev, because typescript is in devDependencies section.

update_sp-pnp-js_typescript_update

Now everything should work as we have updated TypeScript to required version.

update_sp-pnp-js_build_fails3

Wait!! Why we get all those errors even though we have correct TypeScript version?

update_sp-pnp-js_build_fails4

Removing extra typings

It seems that we have duplicate type definitions for all those typescript files. Previously sp-pnp-js required several external typings before it worked. Now those require typings have been added inside the package.

update_sp-pnp-js_typings

We need to remove external typings. Extra typings can be found from project\typings\ folder.

Execute following commands

typings uninstall whatwg-fetch --global
typings uninstall es6-promise --global

update_sp-pnp-js_typings_uninstall

Now you can execute

gulp build

Everything works now.

update_sp-pnp-js_build_succeeds

PnP-JS-Core samples

This is the part four of my posts about SharePoint client side development using Node.js.

You can see previous parts from here:

During this post we will extend existing PnP Workbench with different common scripts.

Code Template

I have created following template that can be used to test different codes easily. You just need to write your own code after // write code here comment. I have used this template for all example codes here unless I have told otherwise.

var testbench = testbench || {};
testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: Test name</h2>");
        // write code here
    };   
    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_EmptyCode

Web

Here are scripts related to Web.

Show title of the web

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: getWebTitle</h2>");
        $pnp.sp.web.select("Title").get()
            .then(function(web){
                targetElement.append(web.Title + "<br />");
            })  
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        })
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_WebTitleCode

If everything went fine, you should see the title of the web in test bench area.

PnPJsSamples_WebTitleBrowser

Show all properties from web object

This can be useful when you try to see what is current state of the web object.

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: getWeb</h2>");
        $pnp.sp.web.get()
            .then(function(web){
                for (var key in web) {
                    targetElement.append(key + ": " + web[key] + "<br />");
                }
            })  
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        });
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_GetWebCode

If everything went fine, you should see all properties of the current web in test bench area.

PnPJsSamples_GetWebBrowser

Lists

Enumerate all lists from current web

This enumerates all lists from current web and shows all their properties.

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: enumLists</h2>");
        $pnp.sp.web.lists.select('Id', 'Title').orderBy('Title').get()
            .then(function(listIds) {
                for (var index in listIds) {
                    var l = $pnp.sp.web.lists.getById(listIds[index].Id);
                    l.get()
                        .then(function(list){
                            for (var key in list) {
                                targetElement.append(key + ": " + list[key] + "<br />");
                            }
                            targetElement.append("<hr />");
                        })  
                        .catch(function(error){ 
                            targetElement.append(error + "<br />");
                    });
                }
            })
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        });
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_EnumListsCode

If everything went fine, you should see all lists under current web and all properties of the list in test bench area. This is quite long list, so I have taken just a snapshot of the first list.

PnPJsSamples_EnumListsBrowser

Enumerate List Items

Enumerates all items from the selected list.

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: enumListItems</h2>");
        $pnp.sp.web.lists.getByTitle("Documents").items.get()
            .then(function(items){
                for (var i=0; i < items.length; i++) {
                   for (var key in items[i]) {
                        targetElement.append(key + ": " + items[i][key] + "<br />");
                    }
                    targetElement.append("<hr />");
                }
            })  
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        });
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_EnumListItemsCode

If everything went fine, you should see all lists items from the selected list and all properties of each list item in test bench area. This is quite long list, so I have taken just a snapshot of the first list item.

PnPJsSamples_EnumListItemsBrowser

Search

Search sites

This example uses search to list all site collections from the tenant. It lists only those current user has rights.

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: searchSites</h2>");
        $pnp.sp.search('contentclass:sts_site')
            .then(function(searchResult) {
                targetElement.append("Search took " + searchResult.ElapsedTime + "ms to complete.<br />");
                targetElement.append("Total rows " + searchResult.TotalRows + ".<br />");
                targetElement.append("Total rows including duplicates " + searchResult.TotalRowsIncludingDuplicates + ".<br />");
                targetElement.append("<hr />");

                for (var index in searchResult.PrimarySearchResults) {
                    var resultItem = searchResult.PrimarySearchResults[index];
                    for (var key in resultItem) {
                        targetElement.append(key + ": " +resultItem[key] + "<br />");
                    }
                    targetElement.append("<hr />");
                }
            })
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        });
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_SearchSitesCode

If everything went fine, you should see list of search results and all properties of each search result item in test bench area. This is quite long list, so I have taken just a snapshot of the first item.PnPJsSamples_SearchSitesBrowser

Creating a PnP-JS-Core Workbench

This is the third part of my posts about SharePoint client side development using Node.js.

You can see previous parts from here:

During this post we will load Office PnP client side scripts and create simple workbench to test our applications in SharePoint.

Setting up project

Create project

The first this is to create a new project. It’s called PnPTestBench. I have covered these steps more detailed in part 2 so I will just show commands and end result here.

Open Node.js Command Prompt

cd \Source
md PnPTestBench
cd PnPTestBench
npm init

name: pnptestbench
version: (Accept default value)
description: PnP-JS-Core Test Bench
entry point: (Accept default value)
test command:
git repository:
keywords:
author: (Enter your name)
license: (Accept default value)

npm install --save-dev gulp

WebStack_GulpLocalInstall

npm install --save-dev gulp-serve

PnPTestBench_GulpServeInstall

Copy files from existing project

We have already created working gulpfile in our previous project so we can reuse those in this also.

PnPTestBench_CopyFilesSource

PnPTestBench_CopyFilesTarget

Copy gulpfile.js, dev_sharepoint_local.crt and dev_sharepoint_local.key from MyFirstProject folder to PnPTestBench folder.

Add required scripts

Office PnP scripts can be loaded as npm package manager. If you are not familiar with Office PnP, you can go to see more information from their GitHub project page. https://github.com/OfficeDev/PnP-JS-Core

jQuery

npm install jquery --save-dev

PnPTestBench_JQueryInstall

Typings

npm install typings --save-dev

PnPTestBench_TypingsInstall

Sp-pnp-js

npm install sp-pnp-js –save-dev

PnPTestBench_SpPnPInstallSuccess

If you will get following error message “’typings’ is not recognized as an internal or external command and “Failed at the sp-pnp-js@x.x.x postinstall script ‘typings install’.”, you didn’t install typings package before installing sp-pnp-js package.

PnPTestBench_SpPnPInstallFails

Building test bench

Creating folders

Now we have installed required packages to get our project working.

We need to create a new folder called app and couple sub folders for it. This is because gulpfile.js contains reference to it.

md app
md app\scripts
md app\styles

PnPTestBench_CreateAppFolders

Open Visual Studio code

PnPTestBench_OpenVSCode

Creating files

Now we can create one html, style sheet and JavaScript file with following content.

app.css

(This is empty file)

app.js

var testbench = testbench || {};
testbench.tests = function() {
   var targetElement = jQuery("#pnp-test-bench");
   targetElement.empty();

   writeGreeting = function(name) {
      targetElement.append("<h2>Test: writeGreeting</h2>");
      targetElement.append("Hello " + name + "<br />");
   };
   return {
      writeGreeting: writeGreeting
   }
};

jQuery('document').ready(function(){
   var t = new testbench.tests();
   t.writeGreeting("Jani");
});

PnPTestBench_AppJs

index.html

<html>
<head>
<title>SharePoint PnP test bench</title>
<style>
body {
   font-family: Verdana, Geneva, sans-serif;
}
.example {
   margin: 10px;
}
.example .code {
   border: 1px solid lightgray;
   padding: 10px;
   font-family: "Lucida Console", Monaco, monospace;
}
</style>
</head>

<body>
<h1>SharePoint PnP test bench</h1>
<div class="example">
<p>Copy following code to your SharePoint site:</p>
<p class="code">
&lt;script type="text/javascript" src="https://dev.sharepoint.local/scripts/jquery.min.js"&gt;&lt;/script&gt;<br />
&lt;script type="text/javascript" src="https://dev.sharepoint.local/scripts/pnp.min.js"&gt;&lt;/script&gt;<br />
&lt;script type="text/javascript" src="https://dev.sharepoint.local/scripts/app.js"&gt;&lt;/script&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="https://dev.sharepoint.local/styles/app.css" /&gt;<br />
&lt;div id="pnp-test-bench"&gt;&lt;/div&gt;<br />
</p>
</div>
</body>
</html>

PnPTestBench_IndexHtml

Copying library files

But wait… What about pnp javascript file. It’s located in node_modules\sp-pnp-js\dist sub folder, but we are not serving that folder. It doesn’t make sense to serve content from every single library folder. It makes the testing of the application much harder.

We can use Gulp to copy library file from its original location to app\scripts folder.

Open gulpfile.js and add following content to it.

gulp.task('copy-files', function() {
   gulp.src('./node_modules/jquery/dist/jquery.min.js').pipe(gulp.dest('./app/scripts'));
   gulp.src('./node_modules/sp-pnp-js/dist/pnp.min.js').pipe(gulp.dest('./app/scripts'));
});

PnPTestBench_GulpFileJs

Because we don’t modify these files that often, we can copy library files to scripts folder when we add new library files. This is done by executing following command in Node.js Command Prompt.

gulp copy-files

PnPTestBench_GulpCopyFiles

Now we can start our test bench

gulp serve-https

PnPTestBench_GulpServeHttps

Then we need to copy html from the example code block to SharePoint test page. If you are unsure how to do this, check instructions from Getting ready for SharePoint development using node.js: http://salomaa.info/sharepoint/getting-ready-for-sharepoint-development-using-node-js/ posting.

PnPTestBench_Browser

Our test bench works fine. Now we can continue working with it. I have created few test cases that use Office PnP JavaScript Core. I will

Getting ready for SharePoint development using node.js

There has been lot of discussion about new SharePoint Framework to be released soon. Here are instructions how you will get your development environment ready for new SharePoint programming model. You can also use these instructions to start working with OfficePnP JavaScript libraries.

Install required / recommended software

Visual Studio Code

You can download lightweight Visual Studio for free from Microsoft (https://code.visualstudio.com/).WebStack_VSCodeDownload

Installation of the VSCode is really simple. I have noticed that if you select “Open with Code” actions will help you working with VSCode better. So during “Select Additional Tasks” step, remember to select both Add “Open with Code”… checkboxes as shown on below.

WebStack_VSCodeInstallPath

Node.js

Next thing is to install Node.js to host your new development environment. You can download it from Node.js web site (https://nodejs.org/en/download/). Installation is Next – Next installation that won’t require any configurations.

Gulp

The first thing is to install gulp. Gulp needs to be installed globally so that every project can use it.

Open Node.js command prompt and type

npm install --global gulp-cli

It will install Gulp for you. This won’t take long.

WebStack_GulpGlobalInstall

After we have installed Gulp, we will create a folder for the project.

Create Project

Create project folders

C:\Users\janis>cd \
C:\>md Source
C:\>cd Source
C:\Source>md MyFirstProject
C:\Source>cd MyFirstProject
C:\Source\MyFirstProject>

WebStack_ProjectCreateFolders

Execute init command to setup project. Project initialization asks several questions about your project. This is almost identical for Visual Studio project window. At this time we don’t connect project to any Source code repository. Note that you need to use lowercase characters in project name.

Configure project

Install gulp to project. It will add required configurations and packages for Gulp to work.

init npm

WebStack_NpmInit

name: myfirstproject (Note that you need to use lower case characters here so you can’t accept default value.)
version: (Accept default value)
description: My First node.js project
entry point: (Accept default value)
test command: (Leave empty)
git repository: (Leave empty)
keywords: (Leave empty)
author: (Enter your name)
license: (Accept default value)

WebStack_NpmInitDetails

After accepting license, init will create package.json file for you like this. You need to confirm it.

WebStack_NpmInitFile

After you have initialized project, you can install gulp to your project.

install --save-dev gulp

WebStack_GulpLocalInstall

Open Windows Explorer and go to C:\Source.

Select MyFirstProject and select Open with code from Context menu.WebStack_OpenVSCode

Create a new file called gulpfile.js and copy following code there.

var gulp = require('gulp');

gulp.task('default', function() {
  // place code for your default task here
});

WebStack_VSCodeGulpFile

Then you can execute gulp. If you get error message that says “No gulpfile found”, you can have created gulpfile.js to wrong folder or made a mistake in its name.

WebStack_GulpExecuteDefault

Adding web server to project

Before you can start developing application, you need to enable web server to your project. This will be done by adding gulp-serve package to your project.

npm i --save-dev gulp-serve

WebStack_CmdInstallGulpServe

After we have added gulp-serve package to our project, we need to edit gulpfile.js to enable web server functionality. This will be done with following lines of code.

var serve = require('gulp-serve');

gulp.task('serve', serve(['app']));

WebStack_VSCodeGulpFileServe

Now you can execute following command in Node.js Command Prompt. System tells us that it will be serving files in localhost port 3000.

gulp serve

WebStack_VSCodeGulpFileServing

Open web browser and type to address bar http://localhost:3000. As you can see from the result, there is nothing to serve for the clients.

WebStack_BrowserNoContent

Creating content

Create a new folder called app and subfolders for it called scripts and styles.

Create also files called app.js, app.css, and index.html with following contents.

function greet() {
    alert("Hello");
}

WebStack_VSCodeAppJs

body {
    background-color: lightgray;
}

WebStack_VSCodeAppCss

<html>
    <head>
        <title>Hello world</title>
        <script type="text/javascript" src="scripts/app.js"></script>
        <link rel="stylesheet" type="text/css" href="styles/app.css" />
    </head>
    <body>
        <h1>Hello world!</h1>
        <button onclick="greet();">Greet</button>
    </body>
</html>

WebStack_VSCodeIndexHtml

Refresh your browser page. Now you can check that you can actually see our test page in your browser. If you click greet button, you will see greeting.

WebStack_BrowserTestContent

Connecting to SharePoint

Creating test site

Now we have created a working test bench and it is time to connect our code to SharePoint. The first thing is to create a test site for us. Log into you tenant and go to Site Contents page.

Select New | Subsite

WebStack_O365SiteContents

Enter site title, description and url.

Select Team Site as site template.

WebStack_O365NewSite

Editing page

Edit page and add Script Editor Web Part to the page.

WebStack_O365AddScriptWebPart

Edit Script Editor Web Part and click EDIT SNIPPLET link.

WebStack_O365EditScriptWebPart

Add following lines to Script Editor.

<script type="text/javascript" src="http://localhost:3000/scripts/app.js"></script>

<link rel="stylesheet" type="text/css" href=" http://localhost:3000/styles/app.css" />

<button onclick="greet();">Greet</button>

Accept changes. Now you can try to click Greet button. As you can see it won’t work. The problem is that our SharePoint site is using encrypted HTTPS connection and our added scripts are using normal HTTP connection. If you try this with Edge as I did in, you may notice that there is no way of getting our button work.

WebStack_O365GreetButtonNotWorking

If you open same page in Internet Explorer, you will see following notification. If you click the Show all content button, you will notice that background changes to light gray and you can click the button.

WebStack_IEShowAllContentNotification

Setting up HTTPS

We don’t always want to confirm that we actually want to see our development work. This requires that we will set up HTTPS service to our development environment.

Creating certificates

Before you will enable HTTPS service, you need to create certificates for you. I have created another post to cover this. http://salomaa.info/sharepoint/setting-up-https-certificates/

Configuring project

We need to copy our certificates to project folder.

Go to C:\Source\DevCertificate folder.

Select dev_sharepoint_local.crt and dev_sharepoint_local.key files and copy files to C:\Source\MyFirstProject folder.

Webstack_ExplorerCopySource

Webstack_ExplorerTargetSource

Open gulpfile.js in Visual Studio Code and add following lines to it.

gulp.task('serve-https', serve({
  root: ['app'],
  port: 443,
  https: {
    key: 'dev_sharepoint_local.key',
    cert: 'dev_sharepoint_local.crt'
  }
}));

WebStack_VSCodeGulpFileHttps

Open Nodejs Command Prompt.

Go to project folder and start gulp with https

gulp serve-https

WebStack_GulpServeHttps

Testing connection

Open your browser and verify that connection to https://dev.sharepoint.local is actually working and you won’t get any certification errors.

webstack_browserhttps

Modifying SharePoint

Now we can modify our scripts from SharePoint.

Go back to your SharePoint test page and replace existing code with this.

<script type="text/javascript" src="https://dev.sharepoint.local/scripts/app.js"></script>
<link rel="stylesheet" type="text/css" href="https://dev.sharepoint.local/styles/app.css" />
<button onclick="greet();">Greet</button>

Click Insert, accept changes and save page.

WebStack_O365EditScriptWebPartHttps

Now you can see that background has been changed to light gray, button works and you don’t get any warnings about the page.

WebStack_O365WorkingScript

Now we have finalized the first part of the SharePoint development with Node.js.

 

Setting up HTTPS certificates

If we want to make proper node.js development for our SharePoint applications, we need to enable HTTPS for our project.

Add host name

Before we can create certificates for our development environment, we need to define host name for development site.

Click Search icon and type note too list Notepad.

Select “Run as administrator” from context menu.

SSL_OpenNotepad

Open C:\Windows\System32\drivers\etc folder.

Change File type to All Files.

Select hosts file and click open.

SSL_OpenHostsFile

Add new entry to hosts file with following information: 127.0.0.1 dev.sharepoint.local

SSL_EditHostsFile

Save file and close Notepad.

Creating certificates

I have used OpenSSL toolkit (https://www.openssl.org/) to generate certificates that I use for HTTPS. OpenSSL is open source toolkit, but they only provide source code.

Install OpenSSL client

You can install OpenSSL client from this location. http://slproweb.com/products/Win32OpenSSL.html.

I have used default settings for it so my application is installed to C:\OpenSSL-Win32. If you have installed it do different location, you need to check paths of next commands.

I have used this excellent post from Dieter Stevens as a base of this part of the post. https://blog.didierstevens.com/2015/03/30/howto-make-your-own-cert-with-openssl-on-windows/ He has shown step by step installation of the client so I won’t cover that in this document.

Note that default length for country name is 2 letters.
If your country has three letter country code, you need to change countryName_max value from openssl.cfg file before going forward.

Creating Certificates

When you have installed the client, you need to create a folder for certificates.

Open Command Prompt.

Go to Source folder.

Create DevCertificate folder and go there.

set RANDFILE= C:\Source\DevCertificate\.rnd
set OPENSSL_CONF=C:\OpenSSL-Win32\bin\openssl.cfg

SSL_CreateFolders

Start OpenSSL client

C:\OpenSSL-Win32\bin\openssl

SSL_OpenSSLExecute

genrsa -out ca.key 4096

SSL_OpenSSLCAGenRsa

req -new -x509 -days 1826 -key ca.key -out ca.crt

Country Name: (Enter 2 letter country code for your country).
State: (Enter your state)
Locality Name: (Enter your city)
Organizational Name: (Enter your company). I have added Development after company name, so that nobody actually thinks that this is real certificate.
Organizational Unit Name: (Enter your OU)
Common Name: sharepoint.local
Email address: (Enter your email address)

SSL_OpenSSLCAReq

genrsa -out dev_sharepoint_local.key 4096

SSL_OpenSSLDevGenRsa

req -new -key dev_sharepoint_local.key -out dev_sharepoint_local.csr

Country Name: (Enter 2 letter country code for your country).
State: (Enter your state)
Locality Name: (Enter your city)
Organizational Name: (Enter your company). I have added Development after company name, so that nobody actually thinks that this is real certificate.
Organizational Unit Name: (Enter your OU)
Common Name: dev.sharepoint.local
Email address: (Enter your email address)
Challenge password: (Enter proper password or leave empty)
Optional company name: (Leave empty)

SSL_OpenSSLDevReq

x509 -req -days 730 -in dev_sharepoint_local.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out dev_sharepoint_local.crt

SSL_OpenSSLx509

pkcs12 -export -out dev_sharepoint_local.p12 -inkey dev_sharepoint_local.key -in dev_sharepoint_local.crt -chain -CAfile ca.crt

SSL_OpenSSLPkcs12

Installing certificates

Before you can use certificates you need to install those to local machine.

Go to C:\Source\DevCertificate.

Install Root certificate

Select ca.crt file and select Install Certificate from context menu.

SSL_ExplorerCA

Select Current User and click next.

SSL_StoreLocationCA

Select Place all certificates in the following location and click Browse…

Select Trusted Root Certification Authorities and click OK.

Click Next

SSL_CertStoreCA

 

Click Yes to security warning.

SSL_SecurityWarningCA

Click OK to close final dialog.

Install development certificate

Select dev_sharepoint_local.crt file and select Install Certificate from context menu.

SSL_ExplorerDev

Select Automatically select the certificate store based on the type of the certificate.

Click Next

Click Finish

Click OK to close final dialog.

SSL_CertStoreDev

Now you have successfully created one root certificate and one certificate for development server.

Install First Approach Explained

I have worked with SharePoint since 2005 and I have seen quite many ways of building SharePoint solutions.

Now when more and more companies are using cloud based services it’s time to make small change to development also. If you have followed at least a little bit of SharePoint scene during last few years, you have heard Microsoft talking about SharePoint Online and Apps model (currently Add-Ins, perhaps they will change that again to something new). At first it was how to build Apps with User Interface and how all developers should start building AppParts instead of WebParts. It has been now little less that three years since Richard diZerega posted an article about an app that will create new site collections to SharePoint (http://blogs.msdn.com/b/richard_dizeregas_blog/archive/2013/04/04/self-service-site-provisioning-using-apps-for-sharepoint-2013.aspx) using Client Side Object Model (CSOM). Now we can benefit from the work done by pioneers. OfficeDevPnp and OfficeDevPnp-PowerShell provide us excellent base to build on. Thank you for all who has made this possible.

Creating the first project

We will create two projects (PowerShell and Web Application) inside one solution. The idea behind this is

To be able to deploy from the first second of the project.
To be able to configure each environment identical.

Why this is important? It’s important because we are building application in development environment. Then we need to deploy same code and configurations to test environment and after acceptance test we will deploy everything to production environment. We can (re)create out development or test environment whenever we want with one script even development environment would be our O365 development tenancy.

Start Visual Studio and select PowerShell | PowerShell Script Project.
Name: MyProject.SharePointApp1.Scripts
Solution name: MyProject.SharePointApp1
Delete Script1.ps1 file.

Add New ASP.Net Web Application to the Solution.
Name: MyProject.SharePointApp1.Web
Select Empty Template
Clear selection from Host in the cloud.
After you have created a project add new folder called Content.

After you have completed all tasks your solution should be similar to this.

Add New PowerShell Script Item ‘CreateSiteCollection.ps1’ to Scripts project. You can see list of time zone id’s and web templates from my previous posts. Execute script. It will create default team site that we can use as playground for next projects.

#
# CreateSiteCollection.ps1
#
Connect-SPOnline -Url “https://tenant-admin.sharepoint.com” -UseWebLogin
New-SPOTenantSite -Title App1 -Url https://tenant.sharepoint.com/sites/app1 -Owner “admin@tenant.onmicrosoft.com” -TimeZone 59 -Lcid 1053 -Template “STS#1” -RemoveDeletedSite

Now when we can create site, we also need to delete sites when we want to erase all old configurations. Therefore, we need to create new PowerShell Script Item ‘DeleteSiteCollection.ps1’.

#
# DeleteSiteCollection.ps1
#
Connect-SPOnline -Url “https://tenant-admin.sharepoint.com” -UseWebLogin
Remove-SPOTenantSite -Url https://tenant.sharepoint.com/sites/app1 -SkipRecycleBin

Adding jQuery

We will continue working with our App1 project by adding jQuery NuGet package to Web project.

  1. Selecting Web project from Solution Explorer
  2. Select Manage NuGet Packages from context menu.
  3. Change tab to Browse
  4. Use search to find jQuery and install it.

Creating the first script

Now we have added jQuery to our project. It’s time for simple hello world demo. Create new JavaScript file ‘project.js’ to Scripts folder inside Web project.

jQuery(document).ready(function () {
alert(“Hello World!”);
});

Updating files to SharePoint

After we have installed jQuery and created project.js file we need to create new PowerShell Script ‘UpdateFiles.ps1’. We will upload jQuery with our own script to the site.

#
# UpdateFiles.ps1
#
Connect-SPOnline -Url “https://tenant.sharepoint.com/sites/app1” -UseWebLogin
Add-SPOFolder -Folder “SiteAssets” -Name “Scripts” -ErrorAction:SilentlyContinue
Add-SPOFolder -Folder “SiteAssets/Scripts” -Name “jQuery” -ErrorAction:SilentlyContinue
Add-SPOFile -Path “C:\SourceCode\MyProject.SharePointApp1\MyProject.SharePointApp1.Web\Scripts\jquery-2.2.0.min.js” -Folder “SiteAssets/Scripts/jQuery”
Add-SPOFile -Path “C:\SourceCode\MyProject.SharePointApp1\MyProject.SharePointApp1.Web\Scripts\Project.js” -Folder “SiteAssets/Scripts”

Files have been uploaded there successfully as we can see from the following image, but the problem is that we didn’t get the message. We still need to add those scripts to the page so that we can execute them in user’s browser.

Adding scripts to the site

Adding custom scripts to site can be done using Add-SPOCustomAction. The problem is that you can’t define script source even it has parameter called Url. At first we need to create custom action and then we need to update ScriptSrc property. Now you can see “Hello World!” text on you site.

#
# ActivateScripts.ps1
#
Connect-SPOnline -Url “https://tenant.sharepoint.com/sites/app1” -UseWebLogin
Add-SPOCustomAction -Description “jQuery” -Location “ScriptLink” -Name “jQuery” -Title “jQuery” -Group “Project” -Sequence 10050 -Scope “Site”
$action = Get-SPOCustomAction -Scope “Site” | ? { $_.Description -eq “jQuery” }
$action.ScriptSrc = “~sitecollection/SiteAssets/Scripts/jQuery/jquery-2.2.0.min.js”
$action.Update()
Execute-SPOQuery

Add-SPOCustomAction -Description “ProjectScript” -Location “ScriptLink” -Name “ProjectScript” -Title “ProjectScript” -Group “Project” -Sequence 10051 -Scope “Site”
$action = Get-SPOCustomAction -Scope “Site” | ? { $_.Description -eq “ProjectScript” }
$action.ScriptSrc = “~sitecollection/SiteAssets/Scripts/Project.js”
$action.Update()
Execute-SPOQuery

Now we have simple template that allows us to update scripts and sites with scripts. If we need to set up new environment, all we need to do is to execute those scripts and environment is ready for action.

SharePoint Development: How to start?

Introduction

There are two versions of SharePoint available:

  • SharePoint 2013 (SharePoint 2016 will available soon).
  • SharePoint Online (Hosted by Microsoft)

You can use either of those to develop SharePoint applications. There is one huge difference. Older SharePoint developers have used Solutions (specially Farm Solutions) to develop applications for SharePoint. This type of development is not an option in Online version of the SharePoint. Farm solutions have been developed using C# and they are packages that contain configurations for SharePoint and also DLL files containing executable code. Biggest problem in this model is that one poorly written application can bring whole server down and there are no way of isolating poorly behaving application.

Figure 1 Principle of Farm Solution

This is totally impossible scenario in cloud environment where single shared environment can host several companies in their isolated tenants. If one company could install poorly written application, it could make harm to several companies and that is not acceptable. To address this type of issues, Microsoft started designing new way of developing applications. This was called User Solutions.

Get you own tenant

Starting SharePoint development is really easy. All you need is own tenant from Office 365. There are several ways of getting your own playground:

  • If you have existing MSDN subscription, you can get Office 365 development tenant. This tenant is available for you as long as you have valid MSDN subscription.
  • If you don’t have MSDN, but you are an employee of the Microsoft partner, you can order demo tenant from Microsoft. This option has expiration date, so you can expect that Microsoft will close you tenant in the future.
    https://demos.microsoft.com/

  • If you don’t have any other mean, you can always order trial tenant from Microsoft. This option has expiration date, so you can expect that Microsoft will close you tenant in the future.
  • If you really want to be a “pro” you can buy your own tenant. This is ultimately the best option, because it allows you to use all Office365 features without limiting factors of previous options.

In any case, it doesn’t matter which option you choose, because we are going to script everything and you can always setup everything in place if you happen to lose your tenant.

Setting up your development environment

You need following tools to start developing SharePoint:

  • OfficeDevPnP.PowerShell Commands https://github.com/OfficeDev/PnP-PowerShell.
    This is set of PowerShell commands that will utilize SharePoint Client Side Object Model (CSOM) and can be used with SharePoint Online. This is huge help for every developer who is working with SharePoint, because it allows you to automate your installation and configuration tasks.
  • Visual Studio https://www.visualstudio.com/vs-2015-product-editions
    Remember to select both Office and Web Developer Tools. Both options are required for proper SharePoint development.

Configuring Visual Studio

Start Visual Studio and install PowerShell Tools for Visual Studio 2015.
Tools | Extensions and Updates.
Select Online and type powershell to search box.
This will require Visual Studio restart.

Now we have configured Visual Studio ready for SharePoint development.

SharePoint Online Templates

Here is a list of SharePoint Online web templates. These are needed if you want to create a new site collection.

#
# ListWebTemplates.ps1
#
Connect-SPOnline -Url “https://tenant-admin.sharepoint.com” -UseWebLogin
Get-SPOWebTemplates -Lcid 1033
Name Title Category Compatiblity Level
STS#0 Team Site Collaboration 15
BLOG#0 Blog Collaboration 15
BDR#0 Document Center Enterprise 15
DEV#0 Developer Site Collaboration 15
OFFILE#1 Records Center Enterprise 15
EHS#1 Team Site – SharePoint Online configuration Enterprise 15
BICenterSite#0 Business Intelligence Center Enterprise 15
SRCHCEN#0 Enterprise Search Center Enterprise 15
BLANKINTERNETCONTAINER#0 Publishing Portal Publishing 15
ENTERWIKI#0 Enterprise Wiki Publishing 15
PROJECTSITE#0 Project Site Collaboration 15
PRODUCTCATALOG#0 Product Catalog Publishing 15
COMMUNITY#0 Community Site Collaboration 15
COMMUNITYPORTAL#0 Community Portal Enterprise 15
SRCHCENTERLITE#0 Basic Search Center Enterprise 15
visprus#0 Visio Process Repository Enterprise 15

SharePoint Time Zones

Here is a list of SharePoint Online time zone id’s. These are needed if you want to create a new site collection.

#
# ListTimeZones.ps1
#
Connect-SPOnline -Url “https://tenant.sharepoint.com” -UseWebLogin
Get-SPOTimeZoneId
Id Description Identifier
0 None No:ne
2 GREENWICH MEAN TIME DUBLIN EDINBURGH LISBON LONDON UTC
3 BRUSSELS COPENHAGEN MADRID PARIS UTC+01:00
4 AMSTERDAM BERLIN BERN ROME STOCKHOLM VIENNA UTC+01:00
5 ATHENS BUCHAREST ISTANBUL UTC+02:00
6 BELGRADE BRATISLAVA BUDAPEST LJUBLJANA PRAGUE UTC+01:00
7 MINSK UTC+02:00
8 BRASILIA UTC-03:00
9 ATLANTIC TIME CANADA UTC-04:00
10 EASTERN TIME US AND CANADA UTC-05:00
11 CENTRAL TIME US AND CANADA UTC-06:00
12 MOUNTAIN TIME US AND CANADA UTC-07:00
13 PACIFIC TIME US AND CANADA UTC-08:00
14 ALASKA UTC-09:00
15 HAWAII UTC-10:00
16 MIDWAY ISLAND SAMOA UTC-11:00
17 AUKLAND WELLINGTON UTC+12:00
18 BRISBANE UTC+10:00
19 ADELAIDE UTC+09:30
20 OSAKA SAPPORO TOKYO UTC+09:00
21 KUALA LUMPUR SINGAPORE UTC+08:00
22 BANGKOK HANOI JAKARTA UTC+07:00
23 CHENNAI KOLKATA MUMBAI NEW DELHI UTC+05:30
24 ABU DHABI MUSCAT UTC+04:00
25 TEHRAN UTC+03:30
26 BAGHDAD UTC+03:00
27 JERUSALEM UTC+02:00
28 NEWFOUNDLAND AND LABRADOR UTC-03:30
29 AZORES UTC-01:00
30 MID ATLANTIC UTC-02:00
31 MONROVIA UTC
32 CAYENNE UTC-03:00
33 GEORGETOWN LA PAZ SAN JUAN UTC-04:00
34 INDIANA EAST UTC-05:00
35 BOGOTA LIMA QUITO UTC-05:00
36 SASKATCHEWAN UTC-06:00
37 GUADALAJARA MEXICO CITY MONTERREY UTC-06:00
38 ARIZONA UTC-07:00
39 INTERNATIONAL DATE LINE WEST UTC-12:00
40 FIJI ISLANDS MARSHALL ISLANDS UTC+12:00
41 MADAGAN SOLOMON ISLANDS NEW CALENDONIA UTC+11:00
42 HOBART UTC+10:00
43 GUAM PORT MORESBY UTC+10:00
44 DARWIN UTC+09:30
45 BEIJING CHONGQING HONG KONG SAR URUMQI UTC+08:00
46 NOVOSIBIRSK UTC+06:00
47 TASHKENT UTC+05:00
48 KABUL UTC+04:30
49 CAIRO UTC+02:00
50 HARARE PRETORIA UTC+02:00
51 MOSCOW STPETERSBURG VOLGOGRAD UTC+03:00
53 CAPE VERDE ISLANDS UTC-01:00
54 BAKU UTC+04:00
55 CENTRAL AMERICA UTC-06:00
56 NAIROBI UTC+03:00
57 SARAJEVO SKOPJE WARSAW ZAGREB UTC+01:00
58 EKATERINBURG UTC+05:00
59 HELSINKI KYIV RIGA SOFIA TALLINN VILNIUS UTC+02:00
60 GREENLAND UTC-03:00
61 YANGON RANGOON UTC+06:30
62 KATHMANDU UTC+05:45
63 IRKUTSK UTC+08:00
64 KRASNOYARSK UTC+07:00
65 SANTIAGO UTC-04:00
66 SRI JAYAWARDENEPURA UTC+05:30
67 NUKU ALOFA UTC+13:00
68 VLADIVOSTOK UTC+10:00
69 WEST CENTRAL AFRICA UTC+01:00
70 YAKUTSK UTC+09:00
71 ASTANA DHAKA UTC+06:00
72 SEOUL UTC+09:00
73 PERTH UTC+08:00
74 KUWAIT RIYADH UTC+03:00
75 TAIPEI UTC+08:00
76 CANBERRA MELBOURNE SYDNEY UTC+10:00
77 CHIHUAHUA LA PAZ MAZATLAN UTC-07:00
78 TIJUANA BAJA CALFORNIA UTC-08:00
79 AMMAN UTC+02:00
80 BEIRUT UTC+02:00
81 MANAUS UTC-04:00
82 TBILISI UTC+04:00
83 WINDHOEK UTC+02:00
84 YEREVAN UTC+04:00
85 BUENOS AIRES UTC-03:00
86 CASABLANCA UTC
87 ISLAMABAD KARACHI UTC+05:00
88 CARACAS UTC-04:30
89 PORT LOUIS UTC+04:00
90 MONTEVIDEO UTC-03:00
91 ASUNCION UTC-04:00
92 PETROPAVLOVSK KACHATSKY UTC+12:00
93 COORDINATED UNIVERSAL TIME UTC
94 ULAANBAATAR UTC-08:00