CHUVASH.eu

CHunky Universe of Vigourous Astonishing SHarepoint :)

Tag Archives: api

Hiding Teamify Prompt

If you want to remove the Microsoft Teams Banner on your SharePoint Site, the only thing you need is to set a web property on a site: TeamifyHidden=TRUE. I’ll give you some guidance below. But before you do that, consider following:

  • If there is already a team created for a group connected site, the prompt won’t show up. Why fix something that is not a problem?
  • Only group owners will get the prompt, if they are few and they know what it is, it is better to let them to decide whether to create or not to create a team.
  • Only licensed users within your organization will be shown that choice. No external users or users without a license.
  • And the most important part: if any site owner selects “Don’t show me again” it will stop popping up for all other site owners. If you happen to have a manual step in the group creation process, then you can just click it away.
“Don’t show me again” option is per site, not per user.
Internally, it is stored as a web property on root site of a site collection.

How to hide Teamify programmatically

Allright, if you still want to hide this prompt and you want to do it programmatically, you need to ensure that this web property is on every site collection root site.

Iterate through all sites

You can find a script for that on Microsoft Fasttrack github repository:

This script has a couple of drawbacks:

  1. Performance and need for re-run. It iterates through all existing sites, meaning that it takes time to iterate through all of them and it requires that you run it again. In an organization with many new collaboration sites it might be a bad option.
  2. Access to all sites. It requires SharePoint Admin, which is okay-ish, but it also requires that this admin account has access to all sites, in order to update the web property, which is not a good option when admins have a restricted access to actual sites due regulations.
  3. CustomScript. CustomScript is disabled by default for a reason. Because it is a security risk. At least you should alter the script to reset the CustomScript setting on a site after you have changed the web property.

Hide Teamify site by site

You can of course hide the Teamify Prompt on a site without iterating. It is the same principle, but it doesn’t require iterating through all sites. You still need to be a SharePoint Administrator (or a Global Admin of course) in order to enable Custom Script. As in the case with all sites, you should reset the CustomScript to what it was.

Use GroupSiteManager Api

There is a new SharePoint Site API that you can call to hide a Teamify Prompt. All you need is to use the solution described in this sharepoint stackexchange answer:

This still requires that access to the site, but you will not need SharePoint Admin, nor will you need to change any CustomScript settings on a site. That’s better.

Calling PnP Rest Call to hide the Teamify Prompt.

Summary

There are ways of hiding the Teamify Prompt on a site collection. If you do that you should include that step in some provisioning process, and not iterate through all sites. It is better to not alter the CustomScript settings at all. First of all it is best to ask yourself why you should disable something that is done for users and for a better user adoption. Also consider that usually only few will be shown that (group owners with a license and within the organization). The group owners can also hide it by clicking “Don’t show me again” and it will disappear for all other group owners.

Using CAML with SharePoint REST API

Do you prefer REST over CSOM as I do? I’ll skip the whys. Andrew Connell put it already in wrtiting so nicely. Well, if you do prefer REST, then you must have discovered some shortcomings of REST, or its incompleteness compared to CSOM. I think of:

  1. Inability to filter items based on multivalued taxonomy fields
  2. Inability to filter items based on user fields where user is added through a group, rather than directly, e.g. AssignedTo=[Me] combined with a SharePoint group.

In such situations I was forced to use CSOM. Until yesterday. Yesterday I learned that we can actually use CAML queries in REST requests.

 

This enables using REST in all situations. The REST API is still developed and many features are added. Maybe a particular operation that needs a CAML query today, can be supported in the core REST API and can be easily refactored then.

But until then, we can use CAML queries in REST requests. Here are the important things about it:

  • A REST request with a CAML query is always a POST request
  • A REST request with a CAML query has always to have X-RequestDigest http header (actually because it is a POST request)
  • A REST request with a CAML query should always have the attached CAML query in the request body (and not in a query string). We don’t want to mess with long urls, do we?
  • A REST request with a CAML query must have the http header “Content-Type: application/json;odata=verbose” unless you use xml in the request body.

Needed HTTP Headers in REST requests

HTTP headers you have to provide in REST requests with CAML queries

You can use jQuery or SP.RequestExecutor to make an ajax call. The REST endpoint is:

_api/web/Lists/GetByTitle('<your list title>')/GetItems

The request body (if you use json, and I bet, you do) is in this format:

{ "query" :
   {"__metadata": 
      { "type": "SP.CamlQuery" }
      , "ViewXml": "<YOUR CAML QUERY>" 
   }
}

Here is the boilerplate for a REST request with a CAML Query:

function getDataWithCaml(listName, caml) {
    var endpoint = "/_api/web/lists/GetByTitle('" 
        + listName + "')/GetItems";
    var requestData = { "query" :
           {"__metadata": 
              { "type": "SP.CamlQuery" }
              , "ViewXml": caml
           }
        };
    return jQuery.ajax({
        url: endpoint,
        method: "POST",
        data: requestData,
        headers: {
            "X-RequestDigest": $("#__REQUESTDIGEST").val(),
            "Accept": "application/json; odata=verbose",
            "Content-Type": "application/json; odata=verbose"
        }
    });
}

This function is just an example. It has no error handling, and it takes for granted that your list is in the root site for on your (sub-)domain (“/”). So take it as an example only.

Here is how the function can be invoked

var caml = "<View><Query><Where><Or><Eq><FieldRef Name='AssignedTo' /><Value Type='Integer'><UserID/></Value></Eq><Membership Type='CurrentUserGroups'><FieldRef Name='AssignedTo' /> </Membership></Or></Where></Query></View>";
getDataWithCaml("Tasks", caml);

REST API: Add a plain text file as an attachment to a list item

plain-text-attachment
SharePoint 2013 REST API has been enhanced and extended. The old _vti_bin/listdata.svc is still there, but the new api for working with lists and list items is much more and obviously a part of a bigger api: _api/web/lists

Yesterday I saw an interesting question on SharePoint StackExchange:

The instructions in the MSDN resource are not so detailed, the cannot be. The guy who asked the question did as it stood in the examples. But sometimes solutions for SharePoint need some small adjustments 🙂

Here is the simplest code to create an attachment in plain text for a list item 1 in the list called List1 in the root web. That’s it. But it works:

var content = "Hello, this text is inside the file created with REST API";
var digest = $("#__REQUESTDIGEST").val();
var composedUrl = "/_api/web/lists/GetByTitle('List1')/items(1)/AttachmentFiles/add(FileName='readme.txt')";
$.ajax({
    url: composedUrl,
    type: "POST",
    data: content,
    headers: {        
        "X-RequestDigest": digest
    }
})

This example is of course just for demonstration. It uses only hard-coded values. But it shows how simple it is to create a list item attachment using SharePoint 2013 REST API and “upload” plain text asynchronously to the server.

Not only plain text (update 2013-03-05)

Of course, uploading only a plain text isn’t enough. The same person Fedor Shihantsov came with an additional question and solved it: Upload a non-text file. Somehow jQuery ajax didn’t work. SP.RequestExecutor worked:

$(document).ready( dofunc );

function dofunc() {
    var control = document.getElementById("ufile");
    control.addEventListener("change", fdocattach, false);
}

var file;
var contents;

function fdocattach(event) {
    var i = 0,
    files = event.srcElement.files,
    len = files.length;

    for (; i < len; i++) {
        console.log("Filename: " + files[i].name);
        console.log("Type: " + files[i].type);
        console.log("Size: " + files[i].size + " bytes");
    }
        

    if (files.length > 0) {
        file = files[0];
        fileName = file.name;

        var reader = new window.FileReader();
        reader.onload = fonload;

        reader.onerror = function(event) {
            console.error("File reading error " + event.target.error.code);
        };
        reader.readAsArrayBuffer(file);
    }       
    return false;
}

function _arrayBufferToBase64(buffer) {
    var binary = '';
    var bytes = new window.Uint8Array(buffer);
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
    }
    return binary;
}

function fonload(event) {
    contents = event.target.result;
    $.getScript("/_layouts/15/SP.RequestExecutor.js", fonload2);
}

function fonload2() {
    var contents2 = _arrayBufferToBase64(contents);

    var createitem = new SP.RequestExecutor("/");
    createitem.executeAsync({
        url: "/_api/web/lists/GetByTitle('List1')/items(1)/AttachmentFiles/add(FileName='" + file.name + "')",
        method: "POST",
        binaryStringRequestBody: true,
        body: contents2,
        success: fsucc,
        error: ferr,
        state: "Update"
    });

    function fsucc(data) {
        alert('success');
    }

    function ferr(data) {
        alert('error\n\n' + data.statusText + "\n\n" + data.responseText);
    }
}

I found another example of SP.RequestExecutor: Calling SharePoint search using REST (e.g. from JavaScript or an app)

javascript API i Sharepoint

Det är supersmidigt. Här är ett exempel:

 

function createAnnouncement(title, body) {
    var ctx = new SP.ClientContext.get_current();
    var list = ctx.get_web().get_lists().getByTitle('Meddelanden');
    var itemCreationInfo = new SP.ListItemCreationInformation();
    this.newListItem = list.addItem(itemCreationInfo);
    this.newListItem.set_item("Title", title);
    this.newListItem.set_item("Body", body);
    this.newListItem.update();
    ctx.executeQueryAsync(
    Function.createDelegate(this, this.onSucceededCallback), Function.createDelegate(this, this.onFailedCallback));
}

function onSucceededCallback(sender, args) {
    SP.UI.Status.addStatus("Info", "It worked!",true);
}
function onFailedCallback(sender, args) {
    SP.UI.Status.addStatus("Info", "It didn't work!",true);
}
Вула Чăвашла

VulaCV - Чăвашла вулаттаракан сайт

Discovering SharePoint

And going crazy doing it

Bram de Jager - Architect, Speaker, Author

Microsoft 365, SharePoint and Azure

SharePoint Dragons

Nikander & Margriet on SharePoint

Mai Omar Desouki

PFE @ Microsoft

Cameron Dwyer

Office 365, SharePoint, Azure, 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

Aryan Nava

DevOps, Cloud and Blockchain Consultant

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

Treacle tarts for great justice

... And All That JS

JavaScript, Web Apps and SharePoint

blksthl

Mostly what I know and share about...

SharePointDiver

SharePoint på ren svenska