CHUVASH.eu

CHunky Universe of Vigourous Astonishing SHarepoint :)

Tag Archives: csom

Add Search Verticals by code

search-verticals-001

Adding own search verticals is a common task in the Search Configuration in SharePoint. Here I want to share a code sample for achieving this programmatically. I hope, this model can be added to SPMeta2.

First of all, Search Verticals are dedicated Search Results Pages and links to them. How to add them manually is described on technet:

There is no API in CSOM for that. Luckily, Mikael Svenson found how to get the Search Navigation and contributed to PnP by writing an Extension: web.LoadSearchNavigation.

Here is my sample code for adding new Search Verticals programmatically:

NavigationNode searchNav = context.Web.Navigation.GetNodeById(1040);
NavigationNodeCollection nodeCollection = searchNav.Children;
NavigationNodeCreationInformation everything = new NavigationNodeCreationInformation
{
    Title = "Everyting",
    Url = "/search/Pages/results.aspx",
};
NavigationNodeCreationInformation myresults = new NavigationNodeCreationInformation
{
    Title = "My Results",
    Url = "/search/Pages/myresults.aspx",
};
nodeCollection.Add(everything);
nodeCollection.Add(myresults);
context.ExecuteQuery();

Method “GetList” does not exist

I troubleshooted a piece of CSOM code in SharePoint 2013. I got the following error:

Method “GetList” does not exist

The reason was that the method GetList was not imlemented until March 2015 CU (15.0.4701.1001), and the SharePoint farm I had was SharePoint 2013 SP1 (15.0.4569.1000). So the solution is to install the Cumulative Update or use web.Lists.GetByTitle. GetByTitle has one aweful shortcoming: it doesn’t work in multilingual environments. So I have recommended to install the March 2015 CU.

AppLoader Concept for SharePoint apps

In this post I want to share an unusual, nevertheless interesting conceptual idea of loading content from SharePoint 2013 apps on many pages. The original awesome concept was proposed and developed by my colleague Martin Villysson at Bool.

The problem we are trying to solve

SharePoint apps are great to extend functionality in SharePoint and integrate other systems (full page apps available through Site Contents), they also provide tools to enrich the default SharePoint experience by App Parts (Client Web Parts) and Custom Actions (additional menus).

One of the biggest shortcomings of that model is the need to add app parts on all pages where it is needed. Let’s say, we want to have some app parts present on every single page in our whole SharePoint tenancy, to provide a consistent look and feel (e.g. navigation, notifications). Traditionally, on premises, we have added user controls in our customized master page. In SharePoint Online that is impossible. The complicated workaround is to add those client web parts (app parts) on every page, be it manually or by automating it (powershell or app). It will require updating all pages. Nevertheless, it will not work on Out-of-the-box application pages (pages from layouts folder). It becomes even more unacceptable when you realize that your app must be added as an app instance on every single site (SPWeb) in your tenancy. 

Towards a solution

Allright, we don’t want to have thousands of app instances of the same app. What we can do is to use Tenant scoped apps (Tenant Apps). Then we’ll need only one app instance. But wait, app parts from a tenant app are only available in the parent site (HostWeb), meaning – App Catalog. That’s not good. So what Martin found in the SharePoint internal javascript code is using of _layouts/15/TenantAppInfo.ashx, a http handler that provides information about all Tenant Apps and their custom actions.That’s how the idea of the AppLoader was born.

Vesa Juvonen

After we had created a working Proof-of-Concept of the AppLoader concept, I met Vesa Juvonen at the SharePoint Conference in Las Vegas and introduced this idea to him (although I didn’t call it AppLoader). He liked it although he pointed out that this TenantAppInfo.ashx is an internal utility only in SharePoint and it is not supported by Microsoft. That’s correct. There is even almost no information about it on the Internet. But I got a feeling of Microsoft that they are willing to hear feedback and improve the product. Vesa encouraged me also to blog about it. So now I am telling about this idea. I hope to hear feedback about it. Unfortunately I cannot share the source code of the working Proof-of-Concept solution.

AppLoader Concept in colors

The AppLoader Concept is quite simple. Look at this picture:

apploader-concept

 

The solution contains a custom Master Page (blue) that references a javascript file called apploader.js (red). This file initializes the whole process. Tenant Apps (green) are the apps that an administrator has installed in the App Catalog and deployed to the whole tenancy. TenantAppInfo.ashx (black) is a handy but officially unsupported OOB service utility (http handler) that returns a json-formatted list of all Tenant Apps (green). AppLoader (red) receives the app list (black) and renders it on the Page (blue) inside new iframes (red). The page a user has navigated to can be any page (wiki page, publishing page, application page, really any page).

To summarize the colors in the diagram: red is our javascript code, green are all the tenant apps and their content, black is the utility and its output, blue is a sharepoint page and its underlying component (master page).

The steps in the AppLoader process:

  1. Make an ajax request to TenantAppInfo.ashx using XHR (XmlHttpRequest)
  2. Receive the app list
  3. For every app information, render app part, or inject css and javascript references. 

 

Reading what to render on the page

You probably have already have tried to navigate to _layouts/15/TenanAppInfo.ashx while reading this post, I know you are curious. Then you’ve noticed that there is no information about app parts. So you may ask: how do we know what app parts to render and where to put them in the page, and how do we know what resources (css and javascript files) to inject on the page. Well there is no information about it in the apps list. But if you have an app with custom actions you’ll see that they are listed in this json-formatted list we receive from the TenantAppInfo.ashx. So the solution is the brilliant idea of my colleage Martin to define custom actions in the app. CustomActions contain a ActionUrl. The ActionUrl points to the url to render (app part page) or to inject (javascript or css file). The apploader.js reads the ActionUrl in the Custom Actions for every app information and takes action upon it (rendering an app part iframe, or injecting a javascript or css file). That’s it. 

Usage and Limitations

This bright idea takes advantages from a huge SharePoint API (that contains a lot of good but not supported parts) to make using of apps in Client Application Model solutions more pragmatic and still provide a consistent design and behavior. By consistent design I mean same parts like additional navigation, notifications etc in the whole Intranet. The AppLoader renders and injects whatever you have rolled out to your whole tenancy (Tenant Scoped Apps) and that on every page (!). It also improves the perceived performance of the page load, because it renders app parts (iframes) after the main page has been loaded preventing freezing of the page. 

There are of course some limitations in the AppLoader Concept. Today we cannot rely on the TenanAppInfo.ashx API (because it is not supported and future updates can break solutions). We have to define our own custom actions in the apps. That means we can only use our own apps, it will hardly work with the apps installed from the Office Store. On the other hand, your customer will not want to have generic apps from the Office Store to be a part of every page on their intranet.

Apps can only call the OOB CSOM and REST endpoints

As a SharePoint architect or a SharePoint developer, you must have been thinking about the benefits/limitations of SharePoint apps a lot. I want to point out one of them today, which is very important: using custom webservices deployed to SharePoint inside apps. That is impossible and it is designed to be so due to the security architecture in the sharepoint app framework.

I have read much about SharePoint apps (books, whitepapers, blog posts) and stumbled over these two contradictive statements:

[…] app authenticatton is supported only for scenarios in which an app is calling to the SharePoint host environment by using client-side object model (CSOM) or the REST API. SharePoint 2013 does not support app authentication in any other endpoints beyond these. This means it is not possible to develop and deploy a set of custom web service entry points that support app authentication.

Microsoft SharePoint 2013 App Development, Microsoft Press, page 88.

This is really important to know, because it is exactly the opposite to what it is said in a Microsoft WhitePaper, where we are requested to “some outside-of-the-box thinking”:

The main reason why you would still use full-trust solutions is that a feature or API you want to use is not yet available through the REST endpoints or CSOM APIs. However, this doesn’t mean you can’t still use the server object model from an app that is on-premises. It just requires some outside-of-the-box thinking. Instead of writing a full-trust solution that completely covers the entire business scenario you are trying to satisfy, write a full-trust solution that exposes the functionality you are looking for as a REST endpoint and write an app that can use that endpoint. This will allow your solution to scale while reducing the overall exposure of full-trust code to the SharePoint environment.

Deciding between apps for SharePoint and SharePoint solutions, Microsoft. Keenan Newton.

Just to clearify, the first statement is correct. The second is unfortunately not correct. To be sure I created a web service which I deployed as a farm solution. And when I tried to invoke this webservice from my app I got 403 error and this message

The endpoint /testapp1/_vti_bin/mywebservice.svc
 is not accessible in the context of a SharePoint App.

The endpoint cannot be added within the manifest neither:
endpoint-001

Summary

While developing SharePoint apps we are restricted to the OOB CSOM and REST endpoint only.

OOB here means out-of-the-box, not outside-of-the-box.

JSOM: Alter a column’s DisplayName

Here is another article in my JSOM series. For one month ago I showed how to alter a column’s ShowInDisplayForm property with JSOM. This time I’ll show a code sample for changing a column’s (field’s) display name. If you want to alter the displayname with Server Object Model, grab the code in the sharepoint.stackexchange.com: Change Field’s DisplayName in a List.

var ctx = SP.ClientContext.get_current(),              //SP.ClientContext
    field = ctx.get_web()                              //SP.Web
               .get_lists()                            //SP.ListCollection
               .getByTitle('MyList')                   //SP.List
	       .get_fields()                           //SP.FieldCollection
	       .getByInternalNameOrTitle("Body");      //SP.Field
ctx.load(field, "Title");                              //load only Title
ctx.executeQueryAsync(function() {
	field.set_title("Beskrivning");
	field.update();
	ctx.executeQueryAsync();
});

Delete all list items with jsom

Today I needed to “clean” a list, meaning to remove all list items. For some time ago I wrote a post about different ways of removing list items in bulk: Server Object Model, SPLinq and RPC.  This time I had only the web browser. So I tried the jsom way. By the way, the javascript documentation for jsom on msdn is getting really good. Don’t miss that: How to: Complete basic operations using JavaScript library code in SharePoint 2013.

Now here comes theworking code I used to remove all items in my list:

var ctx = SP.ClientContext.get_current(),
   list = ctx.get_web().get_lists().getByTitle('MyList'),
   query = new SP.CamlQuery(),
   items = list.getItems(query);
ctx.load(items, "Include(Id)");
ctx.executeQueryAsync(function () {
    var enumerator = items.getEnumerator(),
        simpleArray = [];
    while (enumerator.moveNext()) {
        simpleArray.push(enumerator.get_current());
    }
    for (var s in simpleArray) {
        simpleArray[s].deleteObject();
    }
    ctx.executeQueryAsync();
});

Enjoy

JSOM: Last Modified Date of a List

The data transfer between server and client can heavily affect the performance. One of the measures to reduce the amount data transferred from the server to the client is storing data on the client. In many modern browsers we can use html5 localStorage. Even in older browsers there are ways to store data.

I would recommend a nice js lib called amplify.js. The interface is much easier, then:

amplify.store("key", { title: "value" });

It comes in nicely, if we have much data which we get with JSOM. But we have to care about eventual changes to list items done after we got them the last time.

So we have to store the last modified date. This property is also available in JSOM:

var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var lists = web.get_lists();
var list = lists.getByTitle("Tasks");
ctx.load(list, "LastItemModifiedDate");
ctx.executeQueryAsync(
	function() {
		var lastmodified = list.get_lastItemModifiedDate();
	},
	function() {}
);

Be sure you load only the properties you need:

ctx.load(list, "LastItemModifiedDate");

I took a screenshot to show the difference:

Next time we want to load our items, we can check if we have them saved locally and get the last modified date of the list. If this hasn’t changed, just load from the localStorage.

Another property to keep an eye for is “LastItemDeletedDate”…

Three ways to get the id of last created SPListItem

An interesting question came on SharePoint StackExchange: How to retrieve the guid of the last uploaded file. It is only possible in CSOM as far as I know. But if we simplify the task, how to get the id of the last item, the we can compare three ways of getting them: SPServices, jQuery + listdata.svc and CSOM.

SPServices

The most easiest way, but not available in async:

$().SPServices.SPGetLastItemId({	
	listName: "Documents"
});

listdata.svc

Just combine some query strings and try in the browsers address bar:

http://dev/_vti_bin/listdata.svc/Documents()?
         $filter=CreatedById eq 1
         &$orderby=Created desc
         &$top=1&$select=Id

CSOM

Not so easy to get started, but very powerful and you can get much more of information than with other methods.

function getLastItemId() {
    var userId = _spPageContextInfo.userId;
    var caml = "<View><Query><Where>"
        + "<Eq><FieldRef Name='Author' LookupId='TRUE' /><Value Type='Integer'>" 
        + userId + "</Value></Eq></Where>" 
        + "<OrderBy><FieldRef Name='Created' Ascending='False' /></OrderBy>" 
        + "</Query><RowLimit>1</RowLimit></View>";
    var ctx = SP.ClientContext.get_current()
    var web = ctx.get_web()
    var list = web.get_lists().getByTitle("Documents")
    var query = new SP.CamlQuery();
    query.set_viewXml(caml);
    var items = list.getItems(query);
    ctx.load(items)
    ctx.executeQueryAsync(function() {
        // success actions
        var count = items.get_count();
        //should only be 1
        if (count > 1)  {
           throw "Something is wrong. Should only be one latest list item / doc";
        }

        var enumerator = items.getEnumerator();
        enumerator.moveNext();
        var item = enumerator.get_current();
        var id = item.get_id();
        // do something with your result!!!!
        alert(guidString);

    }, function() { 
        //failure handling comes here
        alert("failed"); 
    });
}
getLastItemId();
Discovering SharePoint

And having fun doing it

Bram de Jager talking Office 365, SharePoint and Azure

My view and thoughts on Productivity and more.

My programming life

and everything in between

SharePoint Development Lab by @avishnyakov

It is a good place to share some SharePoint stories and development practices.

SharePoint Dragons

Nikander & Margriet on SharePoint

RealActivity - Real-time and trustworthy

Blog site of founder, RealActivty - Paul J. Swider

Mai Omar Desouki - Avid SharePointer

Egyptian & Vodafoner - Senior SharePoint Consultant

Cameron Dwyer | Office 365, SharePoint, Outlook, OnePlace Solutions

Office 365, SharePoint, OnePlace Solutions & Life's Other Little Wonders

.:paul.tavares:.

Me and My doings!

Share SharePoint Points!!

By Mohit Vashishtha

Jimmy Janlén "Den Scrummande Konsulten"

Erfarenheter, synpunkter och raljerande om Scrum från Jimmy Janlén

SPJoel

SharePoint for everyone

SharePointRyan

Ryan Dennis is a SharePoint Solution Architect with a passion for SharePoint and PowerShell

SharePoint 2020

The Vision for a Future of Clarity

Aharoni in Unicode, ya mama

Treacle tarts for great justice

... And All That JS

JavaScript, Web Apps and SharePoint

blksthl

Mostly what I know about SharePoint - CommunicoCuspis