Use Visual Studio for SharePoint framework development

When it comes to develop on SharePoint framework, you are free to use environment as your preference. It may be open source tool or proprietary. In the legacy models of SharePoint development, its highly coupled with the Visual Studio, but when it comes to this model you can use VS Code, Sublime, Brackets, Notepad++, Eclipse or any developer as you love most.

Following describes how to develop on SharePoint framework and you still like to develop with Visual Studio which is fully fledged development experience.

Step 1: Scaffolded your Office template to your dev folder.  Reference: SharePoint Framework Scaffolding

 Step 2: Install Node.js to to your Visual Studio. Following link for VS 2015 Community and search for your version of VS.

https://www.visualstudio.com/en-us/features/node-js-vs.aspx

 Step 3: Create new project as below

 Step 4: Select where your node JS files are placed. This should be place where you have scaffolded office templates

Step 5: Select your startup file. This should be gulp file if you go with defaults nothing to change.

Advertisements

How, what and Why| X-RequestDigest (FormDigestValue) header value in SharePoint?

This value is get in to play mostly when we do POST, PUT, MERGE and DELETE requests via the SharePoint REST API. Unless you match with server digest value you won’t be able to perform the REST requests and it gives security validation issues (mostly 403 forbidden status).

How to get this value?

Send a POST request to below end point it will return the form digest value between “FormDigestValue”

http://<Site URL>/_api/contextinfo

What is X Request Digest (Form Digest Value)?

If you are not entitled to SharePoint using OAuth, your will require this value to authorize your request.

For more information: https://msdn.microsoft.com/en-us/library/office/fp142384.aspx

If you’re creating SharePoint hosted Add-in, you can take the digest value as below with JQuery

 Using JQuery

$("#__REQUESTDIGEST").val();

Using Angular JS

Sample Digest value :

0x5A846B1414597F46DB8E88D039E949D54BF62773B7E876730C1191F68240C935D57A17904E37992D2A78F9EC75AD462CF2C9AADFCDB30E1E044C1898358F04B6,13 May 2016 10:51:08 -0000May 2016 10:05:13 -0000

It’s specific to user, time period, site and changes time to time (basically it every 24 hours).

Further reading;

https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.formdigest.aspx

File attach (POST) to SharePoint 2013 List (custom) using Angular JS via REST API

Following describes how to upload attachment to SharePoint 2013 custom list using Angular JS.

Note: You can be consumed the JSOM libraries to achieve this, but there is limitation of 1.5 Mb. Better approach would be consuming exposed REST API (SharePoint OOTB) which allowed up to 2 Gb of file to attached using client side scripts i.e. Angular JS. .

Here I have used the “Angular File Upload” which capable of doing more tasks other than basic HTML input file control. By consuming this we can attach multiple files either to the list and etc. You can be found the information on how to include this module to your Angular view in following link.

Use package manager command to install the scripts.

For bower  -->        bower install angular-file-upload

For nugget -->       npm install angular-file-upload

It requires file buffer array to POST (save) our attachment via REST API, browsers FileReader API is required to use. Its available with almost all common browsers. You need to ensure that is available before in your environment to consume this.

HTML5 FileReader API

Its an API exposed to handle with read contents of BLOB or files. Its supported in most of the latest versions of browsers. If you further required information

View (HTML)

<div ng-app="app" ng-controller="FileUpload as vm" ng-cloak>
 <div class="row">
 <span id="btn" class="btn btn-default">Select file(s)</span>
 <!-- Example: nv-file-select="" uploader="{Object}" options="{Object}" filters="{String}" -->
 <input id="fileUploader" type="file" nv-file-select="" uploader="vm.uploader" multiple style="visibility:hidden;" />
 {{ vm.uploader.queue.length }} files attached.
 </div>
 <div class="row">
 <div uploader="vm.uploader" filters="queueLimit, customFilter">
 <table class="table">
 <tbody>
 <tr ng-repeat="item in vm.uploader.queue">
 <td wrap>{{ item.file.name }}</td>
 <td>
 <button type="button" class="btn btn-danger-focus btn-xs" ng-click="item.remove()">
 <span class="glyphicon glyphicon-trash"></span> Remove
 </button>
 </td>
 </tr>
 </tbody>
 </table>
 </div>
 </div>
</div>

 

Controller


(function () {
'use strict'

angular
.module('app')
.controller('FileUpload', ['FileUploader', 'AttachmentSvc', function (FileUploader, AttachmentSvc) {

var vm = this
, filesObj = [];

//initialization
function init() {
// Check for FileReader API (HTML5) support.
if (!window.FileReader)
console.log(&quot;[Debug] This browser does not support the FileReader API.&quot;);

vm.save = saveFile;
}
init();

//
//FILE UPLOAD
//
vm.uploader = new FileUploader({
url: ''//url for file upload
});

vm.uploader.filters.push({
name: 'customFilter',
fn: function (item /*{File|FileLikeObject}*/, options) {
//constraint for 10 files
return this.queue.length &lt; 10;
}
});

// file callbacks
vm.uploader.onAfterAddingFile = function (fileItem) {
//file added to the object array
filesObj.push(fileItem);
console.log(&quot;Files object&quot;, filesObj);
};

vm.uploader.onAfterAddingAll = function (addedFileItems) {
//console.info('onAfterAddingAll', addedFileItems);
//this will be called after adding all
//by default calls every time after file adding
};

//Code for SharePoint upload
function saveFile(event) {
event.preventDefault();
event.stopPropagation();

//get file selected
var file = filesObj[0]._file;

//convert to arraybuffer
AttachmentSvc.getFileBuffer(file)
.then(function (data) {
if (data != null)
AttachmentSvc.saveFile(data, file.name, 1);

})
.catch(function (err) {
console.log(&quot;Error on getting file array buffer&quot;)
});

}
}]);
})();

Service


(function () {

'use strict'

angular
.module('app')
.factory('AttachmentSvc', ['$q', '$resource', '$window', '$http', function ($q, $resource, $window, $http) {
var service,
ListName = 'test',
serviceId = 'AttachmentSvc';//name of document library

service = {
saveFile: saveFile,
getFileBuffer: getFileBuffer
};

//Initialization
function init() {
console.log(&quot;Initiated..&quot;, serviceId);
}
init();

return service;

//save file to custom list
function saveFile(fileArrBuffer, fileName, itemId) {
var deferred = $q.defer();
//POST request
$http({
method: 'POST',
url: spContext.webUrl + '/_api/web/lists/getbytitle(\'' + ListName + '\')/items(' + itemId + ')/AttachmentFiles/add(FileName=\'' + fileName + '\')',
headers: {
'Accept': 'application/json;odata=verbose',
'Content-Type': undefined,
'X-RequestDigest': spContext.securityValidation,//TODO: provide your digest value here,else it will throw security issues
},
data: new Uint8Array(fileArrBuffer),
transformRequest: []
}).then(function successCallback(data) {
// this callback will be called asynchronously
deferred.resolve(data);
console.log('Successfully saved.', data, serviceId, false);
}, function errorCallback(error) {
// called asynchronously if an error occurs
deferred.reject(error);
console.log('Failed to save!!!.', error, serviceId, false);
});
return deferred.promise;
}

// getting file array buffer
function getFileBuffer(file) {
var deferred = $q.defer();
var reader = new $window.FileReader();
reader.onloadend = function () {
deferred.resolve(reader.result);
}
reader.onerror = function () {
deferred.reject(reader.error);
}
reader.readAsArrayBuffer(file);
return deferred.promise;
}
}]);
})();

 

Hope this helped you! Don’t forget to share with others @kushanlahiru

References

https://msdn.microsoft.com/en-us/library/dn292553.aspx

https://msdn.microsoft.com/en-us/library/office/dn769086.aspx#UploadFile

Further references

https://msdn.microsoft.com/en-us/library/jj163201.aspx

https://msdn.microsoft.com/en-us/library/jj164022.aspx#LargeFiles

Generics Example in C#

using System;

namespace Generics
{

public class MyGeneric<T>
{   //type of the class is ommited
private T[] array;
public MyGeneric(int size)
{
array = new T[size + 1];
}
public T getItem(int index)
{
return array[index];
}
public void setItem(int index, T value)
{
array[index] = value;
}
}
class Program
{
static void Main(string[] args)
{
//declare double array
MyGeneric<double> doubleArray = new MyGeneric<double>(5);

//set values
double x;
for (int c = 0; c < 5; c++)
{
x = c * 10;
doubleArray.setItem(c, Convert.ToDouble(x));
}

//get values
for (int a = 0; a < 5; a++)
{
Console.WriteLine(doubleArray.getItem(a));
}

Console.ReadLine();
}

}
}