Wednesday, June 24, 2015

Get SharePoint list item attachments using REST API


Get SharePoint list item attachments using REST API


I wanted to get the URLs of the list item attachments so that i could use it in my html. To fetch it, one of the prerequisites is the we have ID of the list item. Once we have the ID of the list item , we can construct the URL which would be as below:

var queryUrl = _spPageContextInfo.webAbsoluteUrl "/_api/web/lists/getbytitle('TestList')/items(" + id +")/AttachmentFiles";


You can paste this into a browser and verify whether it works or not.

Now, in case we will use it in a normal REST query , which will get the Title and ID of the list items and iterate it through to get list of all attachments associated with list items.

Use the below code to get the Title, ID and the associated list item attachments. This will handle all case such as if SharePoint list item has multiple attachments or a single attachment or no attachments. We are using the concept of  jquery promises to fetch attachment of list items

//this function make list api call & get data in json form
function getListData(){ try { $.ajax( { url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('TestList')/items?$select=Title,ID", method: "GET", headers: { "accept": "application/json; odata=verbose", }, success: function (data) { if (data !== null) { var dataResults = data.d.results; BindListData(dataResults); } }, error: function (xhr) { console.log(xhr.status + ': ' + xhr.statusText); } ); } catch (err) { console.log(JSON.stringify(err)); } }


//this function will bind the list data in our custom html

 function BindListData(data) {

   if (data.length>0) {  
  for (var i = 0; i < data.length; i++) {                  

//url to get attachment for list item, pass the item id 
var attachmentUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('TestList')/items(" + data[i].ID + ")/AttachmentFiles";

var attachment = getAttachmentUrl(attachmentUrl);

var attachUrl = [];

attachment.success(function (data) {
if (data) {
$.each(data.d.results, function () {
attachUrl.push(this.ServerRelativeUrl);
 });
}
});

if(attachUrl.length == 1)
{
//if the list item has only one attachment
var downloadHTML+= '<a href="'+attachUrl[0]+'" class="anchorClass">File Name</a>';     
$("#downloadLinks").html(downloadHTML);
}
else if(attachUrl.length > 1)
{  
//if the list item has multiple attachments
var downloadHTML= '<div class="DownlinkContainer">';
for(var i=0;i < attachUrl.length;i++)

 downloadHTML+= '<a href="'+attachUrl[i]+'" class="anchorClass">File Name</a>';            
}
downloadHTML+='</div>';
 
$("#downloadLinks").append(downloadHTML);
}
else if(attachUrl.length == 0)
{
//if the list item has no attachments
$("#downloadLinks").hide();
}
  }  
}
}

function getAttachmentUrl(attachmentUrl) {

//returns the list attachment absolute url
return $.ajax({
url: attachmentUrl,
type: "GET",
async: false,
headers: { "accept": "application/json;odata=verbose" },
success: function (data) {
if (data.d.results) {
var getUrl = onAttachmentSuccess(data);
return getUrl;
}
},
error: function (xhr) {
console.log(xhr.status + ': ' + xhr.statusText);
}
});
}

In our onAttachmentSuccess method, we will iterate through the attachments and do whatever operations we need such as binding them.  This will return all attachments and then we can bind it in our custom HTML.

function onAttachmentSuccess(data) {
var url = "";
if (data) {
$.each(data.d.results, function () {
url = this.ServerRelativeUrl;
});
}
return url;
}

In the above example, I check to ensure the data object came back.  I then loop through on data.d.results.  That object will have a property ServerRelativeUrl which has a relative URL that you can use.  This is great for providing a link to the document or to bind to something like an img tag.

function onAttachmentError(error) {
console.log(error.statusText);
}


As you can see, getting list item attachments is pretty easy using REST.  Do test it out and build amazing things !









SharePoint 2013 : Working on navigation using REST API


SharePoint 2013 : Working on navigation using REST API

1) To access the global navigation links, we can use jQuery and make an AJAX request to fetch the links as below:

On any SharePoint page, add a "script editor web part" or "content editor web part" or in the master page, add the script tags.

Add the below script :


$(document).ready(function () {  
    //call the function on document.ready
    getNavigationSiteMap();
});


function getNavigationSiteMap() {
    // Getting our links to render
    $.ajax({
     
        url: _spPageContextInfo.siteAbsoluteUrl + "/_api/navigation/menustate?mapprovidername='GlobalNavigationSwitchableProvider'",
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        success: function (data) {
            // Returning the results
            getNavigationSiteMapSuccess(data);
        },
        error: function (data) {
            getNavigationSiteMapfailure(data);
        }
    });
}

function getNavigationSiteMapSuccess(data)
{  
    if (data != null)
    {
        var result = data.d.MenuState;
     
        //Binding datasource result to JQuery template
        $("#SiteMapTemplate").html(result);
    }


}

function getNavigationSiteMapfailure(result)
{  
    console.log("Failed getting navigation data!");
}


2) To create a link in the quick launch bar or in the top navigation bar, we have two REST endpoints:

QuickLaunch endpoint - /_api/web/Navigation/QuickLaunch

TopNav endpoint - /_api/web/Navigation/TopNavigationbar



Creating link in quick launch -

//Create a Quicklaunch Navigation
function createQuickNavLink() {
    var quickLaunchUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/navigation/QuickLaunch";
    var headers = {
        "accept": "application/json;odata=verbose",
        "content-Type": "application/json;odata=verbose",
        "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
    }
    var call = jQuery.ajax({
        url: quickLaunchUrl,
        type: "POST",
        data: JSON.stringify({
            "__metadata": { type: "SP.NavigationNode" },
            'IsExternal': true,
            'Title': "Google",
            'Url': "http://google.co.in"
        }),
        headers: headers
    });
    call.done(success);
    call.fail(failure);
}
function success(data, textStatus, jqXHR) {
   SP.UI.Notify.addNotification("Navigation created Successully", false);
  }
function fail(error) {
    console.log("request failed: unable to create navigation: " + JSON.stringify(error));
}


Creating a link in Top Navigation bar - 

//Create a top navigation link
function createTopNavLink() {
  var topNavUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/navigation/TopNavigationbar";
    var headers = {
        "accept": "application/json;odata=verbose",
        "content-Type": "application/json;odata=verbose",
        "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
    }
    var call = jQuery.ajax({
        url: topNavUrl,
        type: "POST",
        data: JSON.stringify({
            "__metadata": { type: "SP.NavigationNode" },
            'IsExternal': true,
            'Title': "Google",
            'Url': "http://google.co.in"
        }),
        headers: headers
    });
    call.done(success);
    call.fail(fail);
}

function success(data, textStatus, jqXHR) {
   SP.UI.Notify.addNotification("Top navigation link created Successully", false);
  }
function fail(error) {
    console.log("request failed: unable to create top navigation link: " + JSON.stringify(error));
}






Implement Business Connectivity Services in SharePoint 2013 with CRUD forms

Implement Business Connectivity Services in SharePoint 2013 with CRUD forms:

You can use SharePoint 2013 as a hub for creating rich productivity and collaboration solutions that can work with a variety of external systems. Business Connectivity Services (BCS) provides the infrastructure that enables SharePoint 2013 to bring data from those external systems into a central system. By providing a flexible and extensible means to describe the external system data source and how to interact with it, BCS makes a compelling argument for using SharePoint 2013 as the central interface for working with legacy business systems in addition to new apps for SharePoint.

What can BCS do?

BCS provides mechanisms to enable experienced users, developers, and business unit IT professionals to do the following much more easily:
  • Reveal external data from enterprise applications, web services, and OData services in SharePoint Server 2013 and in rich-client Office applications.
  • Provide Office-type behaviors (such as Contacts, Tasks, and Appointments) and capabilities to external data and services.
  • Provide complete interaction with the data, including write-back capabilities from Office applications and SharePoint Server to the underlying external system data and business objects.
  • Enable offline use of external data and processes.
  • Bridge the unstructured world of documents and people and the appropriate structured data that is locked in external systems.

What is an external content type?

The external content type is a core concept of Business Connectivity Services (BCS). Used throughout the functionality and services offered by BCS, external content types are reusable metadata descriptions of connectivity information and data definitions plus the behaviors you want to apply to a certain category of external data.
External content types enable you to manage and reuse the metadata and behaviors of a business entity, such as a customer or order from a central location, and enable users to interact with that external data and processes in a more meaningful way.
To create external content types with external lists which allow CRUD operations to sql db , please follow the below mentioned steps: 


1) Connect With External Data Source (here we are using SQL Server 2014)
Open SPD and click on the open site icon:









2) Insert the site link for the site we need to open:













3) Enter the admin credentials and once the site opens , click on the External Content Types link as below and then click on Add Connection > External Data Source Type Selection > SQL Server :











4) On clicking the SQL Server , a dialog opens wherein we enter the credentials required to connect to database:













5) In this we can view all the tables present in the database as well as views and routines as below :









6) Select the table on which you want to perform CRUD operations :










7) Make the parameter configurations as per your requirements , similar to  below screenshot :










8) Make the filter configurations as per your requirements , similar to below screenshot :










9) Once this is completed , we need to create external lists as below : 








10)  Enter the list name and description(optional) as below :













11) After that, go the SharePoint site and refresh it, we can see the external list here and click on the list we get the "Access denied by Business Data Connectivity" error as below :




















12) To fix this issue, go to Central Admin > Manage Service Applications > Business Data Connectivity Service Application. In this service application, you will find your External Content Type :













In this, select your External Content type by marking the checkbox. After that, click on Set Object Permissions.

13) In this step, set the permissions as per your requirement :























14) After that, refresh the site and hope this will work… but again, it has a problem. The error message like Login failed for user “NT AUTHORITY\ANONYMOUS LOGON”.

15) To fix this error, we need to change the connection property to BDC identity. Go to your external content type and click on Edit Connection Property as below:

















16) Once this is done, open you SharePoint managed powershell and run the below commands:

$bdc = Get-SPServiceApplication | 
where {$_ -match “Business Data Connectivity Service”}
$bdc.RevertToSelfAllowed = $true
$bdc.Update();


After that, refresh the external list in the site. It would work as expected and you would be able to do the CRUD operations.













17) In case there are too many records , you can get an error related to resource throttling as below:

Database Connector has throttled the response.
The response from database contains more than '2000' rows. 
The maximum number of rows that can be read through Database Connector is '2000'. 

The limit can be changed via the 'Set-SPBusinessDataCatalogThrottleConfig' cmdlet 

To fix this error , run the below commands:


$bcs = Get-SPServiceApplicationProxy | where{$_.GetType().FullName 
-eq (‘Microsoft.SharePoint.BusinessData.SharedService.’ + ‘BdcServiceApplicationProxy’)}
$BCSThrottle = Get-SPBusinessDataCatalogThrottleConfig -Scope database 
-ThrottleType items -ServiceApplicationProxy $bcs
Set-SPBusinessDataCatalogThrottleConfig -Identity $BCSThrottle -Maximum 1000000 -Default 20000