Quantcast
Channel: SharePoint – SharePoint Rider
Viewing all 55 articles
Browse latest View live

Set Permission to List Items using PowerShell

$
0
0


Add-PSSnapin Microsoft.SharePoint.Powershell

$url = "http://weburl"
$listName = "List Name";
$permissionLevel = "Permission Level Name";
$groupName = "Enter Group Name";

#Grant permission on all uniquely secured list items to the specified group

$web = Get-SPWeb $url;
$list = $web.Lists[$listName];
$permission = $web.RoleDefinitions[$permissionLevel];
$principal = $web.SiteGroups[$groupName];

#Process each list item

foreach ($item in $list.Items) {
Write-Output ("Item #" + $item.ID.ToString());

#Check to see whether the item is uniquely secured

if ($item.HasUniqueRoleAssignments -eq $FALSE) {
Write-Output " No change, permissions are inherited.";
}

else {

#Find an existing role assignment for this principal

$assignments = $item.RoleAssignments;
$assignment = $assignments | where {$_.Member.Name -eq $principal.Name};
if ($assignment -eq $NULL) {

#Add a new role assignment for the principal

$assignment = new-object Microsoft.SharePoint.SPRoleAssignment($principal);
$assignment.RoleDefinitionBindings.Add($permission);
$assignments.Add($assignment);
Write-Output (" Granted " + $permissionLevel + " to " + $groupName);
}

elseif ($assignment.RoleDefinitionBindings.Contains($permission) -ne $TRUE) {

#Update the principal's role assignment to add the desired permission level

$assignment.RoleDefinitionBindings.Add($permission);
$assignment.Update();
Write-Output (" Updated " + $groupName + " permissions to " + $permissionLevel);
}
else {
Write-Output " No change.";
}
}

}
$web.Dispose();


Filed under: Powershell, SharePoint

Importing Best Bets as Query Rule in SharePoint 2013 using PowerShell

$
0
0

Use the below format for the CSVfile input

BestBet,UserContext,Keyword,Description,Url,StartDate,EndDate,Position
"IRS","","Income Tax;Tax;","Internal Revenue Service","http://irs.gov/","","",""


Sample PowerShell Script

Add-PSSnapin AdminSnapIn -erroraction SilentlyContinue
Add-PsSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue

$sa = "Search Service App Name"
$ssa = Get-SPEnterpriseSearchServiceApplication $sa
$siteurl = "http://siteurl/"
$ruleManager = New-Object Microsoft.Office.Server.Search.Query.Rules.QueryRuleManager($ssa)
$isVisualBB = "false"
$bestBetCSVFile = import-csv "E:\Path\BestBet.csv" -erroraction SilentlyContinue

Write-Host "File Imported"

foreach($row in $bestBetCSVFile)
{

$bestBetName = $row.BestBet
$rulename = $bestBetName
$contextName = $row.UserContext
$keywordName = $row.Keyword
$description = $row.Description
$url = $row.Url
$startDate = $row.StartDate
$endDate = $row.EndDate
$position = $row.Position

Write-Host $bestBetName $rulename $contextName $keywordName $description $url $startDate $endDate $row.Position

if($keywordName)
{
createBestBetQueryRule -rulename $rulename -keyword $keywordName -ruleManager $ruleManager -bestBetName $bestBetName -contextName $contextName -description $description -url $url -startDate $startDate -endDate $endDate -position $position -isVisualBB $isVisualBB

Write-Host "Added BestBet '$bestBetName' to Keyword '$keywordName'"
}
}


Filed under: SharePoint

How to read SharePoint Managed Metadata Look-up (Taxonomy Field) value using Client Object Model?

$
0
0

The below Console Application code explains you how to read SharePoint Managed Metadata Look-up (Taxonomy Field) value using Client Object Model.

using System;
using System.Text;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Taxonomy;

namespace CSOMRnD
{
class Program
{
static void Main(string[] args)
{

using (ClientContext context = new ClientContext("SiteURL"))
{
context.ExecutingWebRequest += new EventHandler(clientContext_ExecutingWebRequest);
context.AuthenticationMode = ClientAuthenticationMode.Default;
context.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

List list = context.Web.Lists.GetByTitle("ListName");

CamlQuery query = new CamlQuery();

query.ViewXml = "pass your query";

ListItemCollection items = list.GetItems(query);
context.Load(items);
context.ExecuteQuery();

foreach (ListItem item in items)
{
StringBuilder sb_ProductFieldValue = new StringBuilder();

TaxonomyFieldValueCollection taxProductFieldValueColl = item["Product"] as TaxonomyFieldValueCollection;

if (taxProductFieldValueColl != null)
{
foreach (TaxonomyFieldValue taxProductFieldValue in taxProductFieldValueColl)
{
if (taxProductFieldValue.Label.Trim() != null)
sb_ProductFieldValue.Append(taxProductFieldValue.Label + "|");
else
sb_ProductFieldValue.Append("Empty");
}
}
Console.WriteLine(sb_ProductFieldValue.ToString());
}
Console.ReadLine();
}
}

static void clientContext_ExecutingWebRequest(object sender, WebRequestEventArgs e)
{
e.WebRequestExecutor.WebRequest.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
}

}
}


Filed under: Client Object Model, SharePoint

How to use taxonomy hidden field?

$
0
0

Problem:

In one of our SharePoint list we have more than 10 look-up columns with managed metadata type. One fine day our UAT SharePoint site went very low and the CPU utilization in DB Servers associated with the UAT farm started increasing up to 80%. At this point of time the total number of UAT users involved in testing are only 4 to 7. We have around 25k+ terms stored under different terms sets.

Cause:
When we started investigating we found that below key points

1) CAML query calls coming from the custom pages to get managed metadata column values are the most expensive queries on the DB server side.

2) This behavior is happening only when we access those particular custom pages for the first time after an IIS reset.

We all know SharePoint will take more time when we load anything after IIS Reset. But it should not consume more CPU and get into deadlock situation.

Imagine the situation if we move this code to production with 10 to 15 concurrent users? The whole UAT SharePoint farm users and shared resources will be affected because of the CAML Query Issue after any IIS reset.

Solution:

When we approached MS, they suggested “Every taxonomy field of the item should have a hidden field together; e.g. with the Category (taxonomy) field, there should also be a hidden field named something like Category_0 (in my farm), try to use this field in the view fields instead and see if it will improve the results. The reason is that the hidden field is not a lookup field that it shouldn’t need to do any follow up queries to SQL but 1 single query should do the job. Note that the hidden field doesn’t just contain the value that it will also contain the Taxonomy ID, so after getting the value of the hidden field, you will need to parse it to extract the field value. But this should minimize the queries sending to SQL.”

When we modified our CAML queries with the hidden column, we found that the CPU utilization is not increasing and the site performance also very decent.

I am not sure is there any better way to improve this. If you have any ideas / feedback please let me know.

Important Note:
The timer job which updates the taxonomy look-up column will not update this hidden column until there is a change in the item where it is looked-up. We were informed by MS that they are working on this issue.

To validate the hidden column names, I am using SharePoint 2013 Client Browser tool

https://spcb.codeplex.com/releases/view/119035

Sample JavaScript Code

var siteUrl = ‘/';

var listfld_Product;
var listfld_Release;

var listfld_Product_str;
var listfld_Release_str;

var Inputstr = ‘Product A';

function retrieveInternalNames()
{
try
{
var clientContext = new SP.ClientContext(siteUrl);
var oList = clientContext.get_web().get_lists().getByTitle(‘CA_Product_Master_List’);
clientContext.load(oList);

listfld_Product = oList.get_fields().getByTitle(“Product_0″);
listfld_Release = oList.get_fields().getByTitle(“Release_0″);

clientContext.load(listfld_Product);
clientContext.load(listfld_Release);

clientContext.executeQueryAsync(function ()
{
listfld_Product_str = listfld_Product.get_internalName();
listfld_Release_str = listfld_Release.get_internalName();
retrieveListItems();

},
function (sender, args)
{
alert(‘Request failed. ‘ + args.get_message() + ‘\n’ + args.get_stackTrace());
});
}
catch (err)
{
alert(err.message);
}
}

function retrieveListItems()
{
try
{
var clientContext = new SP.ClientContext(siteUrl);
var oList = clientContext.get_web().get_lists().getByTitle(‘CA_Product_Master_List’);

var camlQuery = new SP.CamlQuery();

camlQuery.set_viewXml(“<View><ViewFields><FieldRef Name='” + listfld_Product_str + “‘ Type=’Notes’/><FieldRef Name='” + listfld_Release_str + “‘ Type=’Notes’/></ViewFields><Query> <Where> <BeginsWith> <FieldRef Name='” + listfld_Product_str + “‘ /><Value Type=’Notes’>” + Inputstr + “|” + “</Value> </BeginsWith> </Where> </Query></View>”)

this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
catch (err)
{
alert(err.message);
}
}

function onQuerySucceeded(sender, args)
{
var listItemInfo = ”;
var listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext())
{
var oListItem = listItemEnumerator.get_current();

var releaseArray = oListItem.get_item(listfld_Release.get_internalName()).split(‘;’);
var rleaseInfo = ”;
for (var i = 0; i < releaseArray.length; i++)
{
rleaseInfo += releaseArray[i].split(“|”)[0] + “;”
}

listItemInfo += oListItem.get_item(listfld_Product.get_internalName()).split(“|”)[0] + ‘
‘ + rleaseInfo + ‘

‘;
}
document.getElementById(‘div_Prod_Data’).innerHTML = listItemInfo;
}

function onQueryFailed(sender, args)
{
alert(‘Request failed. ‘ + args.get_message() + ‘\n’ + args.get_stackTrace());
}

_spBodyOnLoadFunctionNames.push(“retrieveInternalNames”);


Filed under: SharePoint

Call Page button click event using PowerShell

$
0
0

Using the below PowerShell commands we can open a page and trigger the click event written inside the page. I am using ListItemCollectionPosition to run the while based on the ROW Limit configured in the CAML query.

Please customize this as per your requirements.

Add-PSSnapin Microsoft.SharePoint.Powershell
$pageURL = "http://server/sites/rnd/_layouts/15/SPTest/Pages/gridtest.aspx"
$url = "http://server/sites/rnd"
$listName = "List Name";

$web = Get-SPWeb $url
$list = $web.Lists[$listName]

$spQuery = New-Object Microsoft.SharePoint.SPQuery
$spQuery.ViewAttributes = "Scope='Recursive'";
$spQuery.RowLimit = 2
$caml = '<OrderBy Override="TRUE"><FieldRef Name="ID"/></OrderBy>'
$spQuery.Query = $caml
$ie = New-Object -com internetexplorer.application;
$ie.visible = $true;
$ie.navigate($pageURL);

while ($ie.Busy -eq $true)
{
Start-Sleep -Milliseconds 1000;
}

Start-Sleep -Milliseconds 5000;

$doc = $ie.document

$viewmoreCNTRL = $doc.getElementByID("ctrlclick")

Start-Sleep -Milliseconds 5000;

do
{
$listItems = $list.GetItems($spQuery)
$spQuery.ListItemCollectionPosition = $listItems.ListItemCollectionPosition

foreach($item in $listItems)
{
Write-Output ("Item #" + $item.ID.ToString());
}

$viewmoreCNTRL.click()
Start-Sleep -Milliseconds 60000;
}
while ($spQuery.ListItemCollectionPosition -ne $null)

$web.Dispose();

 


Filed under: Powershell

How to update taxonomy hidden field using PowerShell?

$
0
0

Continuation to How to use taxonomy hidden field? – (http://sprider.org/2014/09/18/894/) Article

Example PowerShell script to update taxonomy(MMD) hidden field

Add-PSSnapin Microsoft.Sharepoint.Powershell

$sourceWebURL = “http://<Site URL>
$sourceListName = “<List Name>“

[Microsoft.SharePoint.SPSecurity]::RunWithElevatedPrivileges({

$spSourceWeb = Get-SPWeb $sourceWebURL
$spSourceList = $spSourceWeb.Lists[$sourceListName]

$spQuery = New-Object Microsoft.SharePoint.SPQuery
$caml = ‘<Where><Geq><FieldRef Name=”ID” /><Value Type=”Text”>0</Value></Geq></Where>’
$spQuery.Query = $caml
$spSourceItems = $spSourceList.GetItems($spQuery)

$spSourceWeb.AllowUnsafeUpdates = “true”;

foreach($item in $spSourceItems)
{
$item[taxonomyFieldObject.TextField] = “Term Value1|GUID1”; # Based on how you have configured the MMD column, supply the input here. To check the hidden value, we can use sharepoint manager complex tool
$item.Update()
}
$spSourceWeb.AllowUnsafeUpdates = “false”;
$spSourceWeb.Dispose();

});


Filed under: Powershell

Office 365 – Loading SharePoint List Items using AngualrJS and Napa Code Editor

$
0
0

Pre-Requisites

  • Office 365 Developer Site (Take 1 month free subscription from Microsoft Site / use your own site)
  • Napa tool installed on the Office 365 Developer Site (instructions given in Microsoft site)
  • Create a SharePoint list with name “Customers” and feed-in some records
  • Have angular.js and jquery-1.9.1.min.js files handy to upload

Steps

  • Go to Office 365 Developer Site à Click on Settings (Gear Icon) and select Site Contents.
  • Click on “Napa” Office 365 Development Tools
  • Click on Add New Project

projecttype

  • Select App for SharePoint and provide the name for the Project à Click on Create button
  • Set full permission to site collection by clicking permission tab under settings

permission

    • Upload the angular.js and jquery-1.9.1.js files under Scripts folder
    • Open the Default.aspx and Replace the contents inside the Default.aspx with the following:

Capture

    • Replace the contents inside the App.js with the following:

appjs

    • Click on Run Project button
    • The app will be packaged, deployed and launched.
    • Click on Trust it.
    • See output.

Filed under: AngularJS, SharePoint

O365 – SharePoint Hosted App – Custom Global Navigation using Term Store

$
0
0

Hope you are all aware of the limitations of Managed Navigation in SharePoint. If not go through this article http://nikpatel.net/2014/06/09/limitations-of-managed-navigation-in-sharepoint-2013

As explained in the above article, each term set can be associated with only one site collection at given time. If you have 5 site collections, you must have 5 copies of same term set to use for 5 site collections navigation data.

To overcome this issue I have created a SharePoint Hosted app which can read the term store and dynamically build the navigation. This app can be embedded in to webpart zone or master page based on your requirement.

O365 Patterns and Practice code helped me a lot to build this app – (Path – PnP-master\PnP-master\Samples\Core.TaxonomyPicker\Core.TaxonomyPickerWeb\Scripts\taxonomypickercontrol.js)

Step 1 – Create Term Set with your desired menu items and a custom property to configure the redirect url as shown below :

termstore

Step 2 – Create a SharePoint Hosted App using Napa / Visual Studio

Step 3 – Configure Permission as per your requirement

Permission

Step 4 – Add the necessary script files and a DIV tag to load the dynamic html from App.js file as shown below

Default Aspx

Step 5 – Build the dynamic menu list and push the html inside the DIV from App.js as shown below:

Note: Replace the term store and termset Guid with your environment values.

‘use strict';

var terms;
var sb = “”;

var tree = {
term: terms,
children: []
};

$(document).ready(function() {
fn_Build_Navigation();

});

function fn_Build_Navigation() {
var start = new Date().getTime();
var context = SP.ClientContext.get_current();
var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
var termStores = taxSession.get_termStores();
//Name of the Term Store from which to get the Terms.
var termStore = termStores.getByName(“Taxonomy_kFyvauM0tqfeNGG7M0bRmw==“);
//GUID of Term Set from which to get the Terms.
var termSet = termStore.getTermSet(“fa6a6655-4db6-4568-aa41-588b9420aec9“);
terms = termSet.getAllTerms();
context.load(terms);

context.executeQueryAsync(function() {
var termEnumerator = terms.getEnumerator();

while (termEnumerator.moveNext()) {
var currentTerm = termEnumerator.get_current();

var currentTermPath = currentTerm.get_pathOfTerm().split(‘;’);
var children = tree.children;

// Loop through each part of the path
for (var i = 0; i < currentTermPath.length; i++) {
var foundNode = false;
for (var j = 0; j < children.length; j++) {
if (children[j].name === currentTermPath[i]) {
foundNode = true;
break;
}
}

// Select the node, otherwise create a new one
var term = foundNode ? children[j] : {
name: currentTermPath[i],
children: []
};

// If we’re a child element, add the term properties
if (i === currentTermPath.length – 1) {

var navurl = currentTerm.get_customProperties().redirectTo;
if (!navurl) {
navurl = “#”;
}

term.term = currentTerm;
term.title = currentTerm.get_name();
term.guid = currentTerm.get_id().toString();
term.url = navurl;
}

// If the node did exist, let’s look there next iteration
if (foundNode) {
children = term.children;
}
// If the segment of path does not exist, create it
else {
children.push(term);

// Reset the children pointer to add there next iteration
if (i !== currentTermPath.length – 1) {
children = term.children;
}
}
}
}

if (tree.children.length > 0) {
sb = “<ul id=’globalMenu’ class=’menu’>”;

for (var prarentindex = 0; prarentindex < tree.children.length; prarentindex++) {
if (tree.children[prarentindex].children.length > 0) {
buildTermSetTreeLevel(tree.children[prarentindex].children, tree.children[prarentindex].name, tree.children[prarentindex].url);

} else {
sb += “<li><a href='” + tree.children[prarentindex].url + “‘>” + tree.children[prarentindex].name + “</a></li>”;
}
}

sb += “</ul>”;

$(“#message”).html(sb);
}

var end = new Date().getTime();
var time = end – start;
console.log(‘Execution time: ‘ + time);
}, function(sender, args) {
console.log(args.get_message());
});
}

function buildTermSetTreeLevel(termList, name, url) {

sb += “<li>”;
sb += “<a href='” + url + “‘>” + name + “</a>”;
sb += “<ul>”;

for (var i = 0; i < termList.length; i++) {
var term = termList[i];

if (term.children.length > 0) {
buildTermSetTreeLevel(term.children, term.name, term.url);
} else {
sb += ” <li><a href='” + term.url + “‘>” + term.name + “</a></li>”;
}
}

sb += “</ul>”;
sb += “</li>”;
}

Hope you liked this post. If you have any questions on this topic, please let me know…


Filed under: SharePoint

O365 / SharePoint Online – Import Term Store Terms using CSOM & PowerShell

$
0
0

Looking for a solution to import Term Store Terms using CSOM & PowerShell in O365 / SharePoint Online?

Here you go….

Note: Modify the XML term attributes and PS script logic as per your requirement

XML Config File Structure

config xml

PowerShell Script

cls

try
{
Write-Host “Load XML config file” -foregroundcolor black -backgroundcolor yellow Set-Location

$xdoc = [xml] (get-content “C:\Joseph\Code\SPRIDER\PS\TermStore\config.xml”)

$Url = $xdoc.Tenant.Admin.site
$Admin = $xdoc.Tenant.Admin.username
$Pwd = $xdoc.Tenant.Admin.password

$SecurePwd = $Pwd |ConvertTo-SecureString -AsPlainText -force

Write-Host “Global variables loaded succeefully” -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host “Error : $_.Exception.Message” -foregroundcolor black -backgroundcolor Red
return
}

try
{
Write-Host “Load CSOM DLLs” -foregroundcolor black -backgroundcolor yellow Set-Location

Add-Type -Path “c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll”
Add-Type -Path “c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll”
Add-Type -Path “c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll”

Write-Host “CSOM DLLs loaded succeefully” -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host “Error : $_.Exception.Message” -foregroundcolor black -backgroundcolor Red
return
}

function Recursive($inputerm,$inputNode)
{

Foreach ($InnerTermNode in $inputNode.term)
{
$childterms = $inputerm.Terms
$Ctx.Load($childterms)
$Ctx.ExecuteQuery()
$childterm = $childterms | Where-Object {$_.Name -eq $InnerTermNode.name}
if($childterm)
{
Write-Host “Term” $InnerTermNode.name “already exists.” -foregroundcolor black -backgroundcolor yellow
}
else
{
Write-Host “Creating term ” $InnerTermNode.name -foregroundcolor black -backgroundcolor yellow

$childterm = $inputerm.CreateTerm($InnerTermNode.name, 1033, [System.Guid]::NewGuid())
try
{
$Ctx.ExecuteQuery()

Write-Host “Term” $childterm.name “Created successfully” -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host “Error while creating Term” $InnerTermNode.name $_.Exception.Message -foregroundcolor black -backgroundcolor Red
return
}
}
if($InnerTermNode.ChildNodes.Count -gt 0)
{
Recursive $childterm $InnerTermNode
}
}
}
try
{
Write-Host “Authenticate tenant site $url and get ClientContext object” -foregroundcolor black -backgroundcolor yellow

$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($Url)
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Admin, $SecurePwd)
$Ctx.Credentials = $Credentials
if (!$Ctx.ServerObjectIsNull.Value)
{
Write-Host “Connected to SharePoint Online site: ” $Ctx.Url “” -foregroundcolor black -backgroundcolor Green

$TaxonomySession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($Ctx)
$TaxonomySession.UpdateCache()
$Ctx.Load($TaxonomySession)
$Ctx.ExecuteQuery()

Write-Host “Taxonomy session initiated: ” $TaxonomySession.Path.Identity “” -foregroundcolor black -backgroundcolor Green

$termStore = $TaxonomySession.GetDefaultSiteCollectionTermStore()
$Ctx.Load($termStore)
$Ctx.ExecuteQuery()
Foreach ($GroupName in $xdoc.Tenant.TermStore.group)
{
Write-Host “Getting list of groups from term store” -foregroundcolor black -backgroundcolor yellow

$groups = $termStore.Groups
$Ctx.Load($groups)
$Ctx.ExecuteQuery()

try
{
$Ctx.ExecuteQuery()

Write-Host “List of groups from term store loaded successfully” -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host “Error while getting list of groups from term store” $_.Exception.Message -foregroundcolor black -backgroundcolor Red
return
}

Write-Host “Check whether the group is exist in the term store” -foregroundcolor black -backgroundcolor yellow

$group = $groups | Where-Object {$_.Name -eq $GroupName.name}

if ($group)
{
Write-Host “Group” $GroupName.name “already exists.” -foregroundcolor black -backgroundcolor yellow

$group = $termStore.Groups.GetByName($GroupName.name)
$Ctx.Load($group)
$Ctx.ExecuteQuery()
}
else
{
Write-Host “Creating group” $GroupName.name -foregroundcolor black -backgroundcolor yellow

$group = $termStore.CreateGroup($GroupName.name,[System.Guid]::NewGuid().toString())

try
{
$Ctx.ExecuteQuery()

Write-Host “Group” $GroupName.name “Created successfully” -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host “Error while creating Group” $GroupName.name $_.Exception.Message -foregroundcolor black -backgroundcolor Red
return
}
}

Foreach ($TermSetNode in $GroupName.termset)
{
$termSets = $group.TermSets
$Ctx.Load($termSets)
$Ctx.ExecuteQuery()

$termSet = $termSets | Where-Object {$_.Name -eq $TermSetNode.name}

if($termSet)
{
Write-Host “Termset” $TermSetNode.name “already exists.” -foregroundcolor black -backgroundcolor yellow

$termSet = $group.TermSets.GetByName($TermSetNode.name)
$Ctx.Load($termSet)
$Ctx.ExecuteQuery()
}
else
{
Write-Host “Creating term set” $TermSetNode.name -foregroundcolor black -backgroundcolor yellow

$termSet = $group.CreateTermSet($TermSetNode.name,[System.Guid]::NewGuid().toString(),1033)

try
{
$Ctx.ExecuteQuery()

Write-Host “Term set ” $TermSetNode.name “Created successfully” -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host “Error while creating Term set” $TermSetNode.name $_.Exception.Message -foregroundcolor black -backgroundcolor Red
return
}
}

Foreach ($TermNode in $TermSetNode.term)
{
$terms = $termSet.Terms
$Ctx.Load($terms)
$Ctx.ExecuteQuery()
$term = $terms | Where-Object {$_.Name -eq $TermNode.name}

if($term)
{
Write-Host “Term” $TermNode.name “already exists.” -foregroundcolor black -backgroundcolor yellow
}
else
{
Write-Host “Creating term ” $TermNode.name -foregroundcolor black -backgroundcolor yellow

$term = $termSet.CreateTerm($TermNode.name, 1033, [System.Guid]::NewGuid())

try
{
$Ctx.ExecuteQuery()

Write-Host “Term” $TermNode.name “Created successfully” -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host “Error while creating Term” $TermNode.name $_.Exception.Message -foregroundcolor black -backgroundcolor Red
return
}
}

if($TermNode.ChildNodes.Count -gt 0)
{

Recursive $term $TermNode
}
}
}
}
}
}
catch
{
Write-Host “Error : $_.Exception.Message” -foregroundcolor black -backgroundcolor Red
return
}


Filed under: O365, Powershell

O365 / SharePoint Online – Apply Theme – CSOM & Powershell

$
0
0

As you know, Web.ApplyTheme method applies a theme with the specified components to this site.

For more information refer – https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.web.applytheme.aspx

Here fontSchemeUrl and backgroundImageUrl parameters can accept null values. But when I tried to pass $null or null or Empty String to these two parameters via PowerShell, I got the following error:

“Exception calling “ApplyTheme” with “4” argument(s): “The ‘fontSchemeUrl’ argument is invalid.”.Exception.Message”

Then i tried with Out-Null instead of $null or null or Empty String. Trust me it worked like a charm.

Actually the Out-Null cmdlet deletes output instead of sending it down the pipeline.

This is my final code.

Hope it helps :)

Fixed

 

 


Filed under: Client Object Model, O365, Powershell, SharePoint

O365 Custom JavaScript Injection using PowerShell

$
0
0

What is Custom Action?

Custom action fetches an external script and includes it in the page. So at run time the script will self execute as an anonymous function.

Following are few scenarios you may need this functionality in your SharePoint Projects:

1) Override the new sub site link (https://<tenant&gt;.sharepoint.com/sites/dev/_layouts/15/newsbweb.aspx) under Site Contents  with your site provisioning app URL

2) Redirect the user to specific page

3) Inject third-party JavaScript libraries such as Jquery, Knockout, AngularJs, etc.,

4) Add dynamic html (global navigation / company copy rights information on the bottom of your page) content on your sharepoint page at run time without even modifying the actual master page.

In the below example, I have explained how to inject Jquery file to one of my web. The source files can be placed in CDN / File Share / Common Location such as App Catalog.

Please feel free to change the logic as per your requirement.

Note: The logic remains same for JSOM code also.

Inject_Action

 


Filed under: O365, Powershell, SharePoint

O365 – How to deploy Provider Hosted App without ACS

$
0
0

Last week, I got an interesting requirement from the Architect to check the possibility to host the provider hosted app in the on-premise server and use the same in SharePoint Online. I hope many of you interested to do the same setup without Azure. If you are one among them, please go through the very detailed article written by Eric Shupps.

http://www.binarywave.com/blogs/eshupps/Lists/Posts/Post.aspx?ID=267

I have the STS trust setup for the hybrid search in my environment. So i used the same certificate to host my sample app in O365. Please feel free to get in touch with me if you have any queries on this.

To troubleshoot different issues related to certificate, the following article helped me a lot

http://www.justanothertechnologyguy.com/2014/03/problems-with-sharepoint-provider.html

Thank you Eric Shupps and Rainier van Slingerlandt for sharing your experience.


Filed under: O365, SharePoint Tagged: Microsoft Azure

Hide Webpart – SharePoint Online by PowerShell

$
0
0

I came across a scenario where I need to hide the OOTB list form WebPart from the SharePoint List “NewForm.aspx” page by PowerShell. I have written a script to perform the same in SharePoint online.

In the below script, I am getting the list of WebParts in the NewForm.aspx page and setting the hidden property. If you have more than one WebPart in a page, you can find the specific WebPart and set the required properties to that.

Note:

  • Update the url, username and password with your tenant details.
  • Keep the Microsoft.SharePoint.Client and Microsoft.SharePoint.Client.Runtime DLLs in the place where you saved the PowerShell script file or change the location as per your location.

Script

cls

$scriptBase = split-path $SCRIPT:MyInvocation.MyCommand.Path -parent
Set-Location $scriptBase

Add-Type -Path $scriptBase”\Microsoft.SharePoint.Client.dll”
Add-Type -Path $scriptBase”\Microsoft.SharePoint.Client.Runtime.dll”

$url = “https://xyz.sharepoint.com/sites/dev&#8221;
$username = “admin@xyz.onmicrosoft.com”
$password = “Password”

$Password = $password |ConvertTo-SecureString -AsPlainText -force
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$Context.Credentials = $credentials

$List = $Context.Web.Lists.GetByTitle(“Test List”)
$Context.Load($List)
$Context.ExecuteQuery()

$Pages = $List.RootFolder.Files
$Context.Load($Pages)
$Context.ExecuteQuery()

$Page = $List.RootFolder.Files | Where {$_.Name -eq “NewForm.aspx”}
$Context.Load($Page)
$Context.ExecuteQuery()

$WPM = $Page.GetLimitedWebPartManager(“Shared”)
$Context.Load($WPM)
$Context.ExecuteQuery()

$WebParts = $WPM.WebParts
$Context.Load($WebParts)
$Context.ExecuteQuery()

$WebPart = $WebParts[0]
$Context.Load($WebPart)
$Context.ExecuteQuery()

$WebPart.WebPart.Hidden = $true
$WebPart.SaveWebPartChanges()
$Context.ExecuteQuery()


Filed under: O365, Powershell

Execute C# code from PowerShell Script – SharePoint Online

$
0
0

Are you looking for an example code to exeucte C# code from PS?

Hope you can get started with the below sample. As per your requirement change the DLL path, Site URL, UserName and Password parameters in the below example.

cls

# C# Source Code
$SourceCode = @”
using System;
using System.Management.Automation;
using System.Security;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Utilities;

namespace SPOperations
{
public class SPHelper
{
public static string getWebTitle(string siteUrl, string userName, string sitePassword)
{
using (ClientContext clientContext = new ClientContext(siteUrl))
{
SecureString passWord = new SecureString();
foreach (char c in sitePassword.ToCharArray()) passWord.AppendChar(c);
clientContext.Credentials = new SharePointOnlineCredentials(userName, passWord);
Web web = clientContext.Web;
clientContext.Load(web);
clientContext.ExecuteQuery();
return web.Title;
}
}
}
}
“@

try
{
$scriptBase = split-path $SCRIPT:MyInvocation.MyCommand.Path -parent
Set-Location $scriptBase

$TenantConfig = $scriptBase + “\” + “Configs\settings.xml”
$TenantConfigXML = [xml](Get-Content($TenantConfig));

$url = $TenantConfigXML.ConnectionString.Key.URL
$username = $TenantConfigXML.ConnectionString.Key.UserName
$password = $TenantConfigXML.ConnectionString.Key.Password

$assemblies = @(
“$scriptBase\DLL\Microsoft.SharePoint.Client.dll”,
“$scriptBase\DLL\Microsoft.SharePoint.Client.Runtime.dll”
“System.Core”
)
}
catch
{
Write-host “Error while loading the input parameters ” $_.Exception.Message -ForegroundColor Red
exit 1
}

try
{
#Add the Assembly
Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $SourceCode -Language CSharp
}
catch
{
Write-host “Error while loading the Referenced Assemblies and Type Definition ” $_.Exception.Message -ForegroundColor Red
exit 1
}

try
{
$siteTitle = [SPOperations.SPHelper]::getWebTitle($url, $username, $password)
Write-Host $siteTitle
}
catch
{
Write-host “Error : ” $_.Exception.Message -ForegroundColor Red
exit 1
}


Filed under: C#, O365, Powershell, SharePoint

Provider Hosted App Deployment to Azure Website’s (One Azure site for multiple apps)

$
0
0

Deployment Steps

  • Create an Azure Website in Azure Portal. In this example, I am going to create an azure website with name “cloud-demo-providerapps”
  • I wish to use one azure website to host multiple provider hosted apps. So I am going to create separate folders to deploy my provider hosted app files as shown below: (In this example, I am going to deploy my provider hosted app files under “AzureDeployTest” folder.)

Note: It is mandatory to check the application checkbox

  • To prepare the build, create a new folder in your system(laptop/server). In this example the folder name is “SPOL_Stage_Build_09252015V01
  • Download the azure website profile from azure portal and paste it inside the “SPOL_Stage_Build_09252015V01” folder. In this example my azure profile name is “cloud-demo-providerapps.azurewebsites.net.PublishSettings

         Note: This will be done by admin team. So include this in the deployment instruction.

  • Create a XML file inside the “SPOL_Stage_Build_09252015V01” folder with name “xml” and configure the XML file in the below format

<?xml version=”1.0″ encoding=”utf-8″?>
<parameters>
<setParameter name=”IIS Web Application Name” value=”cloud-demo-providerapps/AzureDeployTest” />
</parameters>

Here cloud-demo-providerapps is the azure website name and AzureDeployTest is the folder where I wanted             to place my provider app files.

  • Download the below PowerShell script from my one drive and paste it inside the “SPOL_Stage_Build_09252015V01” folder

        Publish-AzureWebApp.ps1

  • Package the provider hosted web project and paste the zip file inside the “SPOL_Stage_Build_09252015V01” folder. In this example my package file name is “AzureDeployTestWeb.zip

Note: This will be done by development team.

  • At this point my build should be ready as shown below
  • Open the Windows PowerShell IDE and navigate to the “SPOL_Stage_Build_09252015V01” folder location
  • Execute the following command

.\Publish-AzureWebApp.ps1 -WebDeployFile AzureDeployTestWeb.zip –SetParametersFile config.xml -PublishSettingsFile cloud-demo-providerapps.azurewebsites.net.PublishSettings

  • If everything works fine, deployment artifacts should be deployed to the target folder and you should see the success message in the powershell IDE.

Filed under: SharePoint

Responsive Kanban Board – SharePoint Hosted App

$
0
0

Do you have a requirement to create a SharePoint Hosted Kanban Board App in O365? If so, I have created a very basic prototype which you can use and get started.

Steps to get this work in your O365 Tenant

  • Download the List Template(Product Backlog.stp) and import the same in your site
  • Create a new Custom List from the List you have imported and name it as “Product Backlog”
  • Go to “Product Backlog” List and update the “Assigned To” column with the users.

Note: This is a mandatory field for this prototype. Enter only one SharePoint user per record.

  • Download the app file(Kanban Board.app) and upload the same in app catalog
  • Install the “Kanban Board” app in the site where you created the “Product Backlog” List.
  • If everything works fine, you should get the following board when you launch the “Kanban Board” app

kanbanboard

kanbanboard_newcard

Disclaimer and confession
This is not a drop in solution and you have to adapt it to suit your needs: your mileage may vary. I wasn’t born a JS developer and actually learned most of what I know on this subject the past few years. I am not following best practices (SPOL/AngularJS), but this post should get you started.


Filed under: SharePoint

O365 – Install / Upgrade App from App Catalog OOTB

$
0
0
  • Upload the first version(example: 1.0.0.5) of your app in the app catalog site.
  • Install the first version of your app in the app catalog site.
  • Go to Site Contents Page and select “Deployment” from App options

App_deployment1

  • Now you will be redirected to the “Manage App Deployments” page where in you can configure where you can install the app. App can be installed with Site Collections, Managed Paths and Site Templates based scopes.

App_deployment2

  • Configure the setting as per your requirement and click Ok to trust the app

App_deployment3

  • In this example, I wanted to install my app in https://cacloud.sharepoint.com/sites/dev site collection under sites managed path with Developer Site templates only.
  • Now the app should be installed in the above said sites

App_deployment4

  • Now upload the next version(1.0.0.6) of your app in the app catalog site
  • Upgrade the app from app catalog and trust it again in the app catalog site

App_deployment6

  • Now your app should get upgraded automatically in the sites you configured in step # 4.

App_deployment7


Filed under: SharePoint

Hook up Google Analytics or Azure Application Insights to track SharePoint Usage

$
0
0

Knowing how people use your application lets you focus your development work on the scenarios that are most important to them, and gain insights into the goals that they find easier or more difficult to achieve. Google Analytics or Azure Application Insights will take you to the next level of analyzing the SharePoint Usage.

In the below example, I am going to show you how to hook up Google Analytics or Azure Application Insights tracker file to track SharePoint Usage in the site collection level using the famous Pnp Provision Engine Template.

Steps to implement

  • Extract the PnpCustomAction.zip file and Paste the PnpCustomAction folder on your laptop/server
  • Install PnPPowerShellCommands16.msi on your laptop/server (download here – https://github.com/OfficeDev/PnP-PowerShell/tree/master/Binaries). To know more about Pnp Provision Engine click here
  • Open the tracking.js(Custom JS action) file and update the script you have copied from Google Analytics or Azure Application Insights
  • Upload the tracking.js(Custom JS action) file in your CDN/SharePoint Library. In this example, I have uploaded the tracking.js file in a document library
  • Open the Template_Apply_WebCustomActions.xml file and update the URL(the place where you have uploaded the tracking.js file) mentioned in the ScriptBlock attribute under pnp:CustomAction node
  • Update the site collection URL in Deploy.ps1 file and execute
  • Navigate to different sub-sites under the site collection against where you have executed this script and make sure the tracking data are captured.

Google Report

google

Azure Report

azure

Let me know if you have any queries on this.


Filed under: Azure, O365, SharePoint

Hiding SharePoint Apps/Add-ins from users

$
0
0

Problem Statement
Users who have full control are able to delete the mandatory apps from site.

Question
Is it possible to hide an installed/added app (in a site collection) from users with specific permissions or from a user group?

Answer
We can hide an app by embedding a JQuery custom action (jQuery(‘img[alt=”YourAppTitle”]’).closest(‘div[class^=”ms-vl-apptile”]’).hide();) but cannot hide an app from the view all site content page with a direct app permission.

How can I control/govern?
We can control the apps from app catalog site. If you have a mandatory app that should not be removed by site users with full control then follow the below steps:

  • Install the mandatory app in the app catalog site
  • Select the deployment option from the app properties as shown below

hideapp1

  • You will be redirected to the Manage App Deployment page
  • Specify what site collections/managed paths/site templates should have this app available and click OK.
  • Go to a site where you configured to install the app. You should be able to see the app installed.
  • Now if you look at the options in the app, you will not see the remove option. This is because the app is now controlled from the central place (app catalog).

hideapp2

  • Based on the configuration changes from the app catalog SharePoint will propagate the changes to the respective sites.

Filed under: O365, SharePoint

Isolating RER code logic from Provider Hosted Apps

$
0
0

Problem Statement

Users who have full permission on the SharePoint site can delete the mandatory provider hosted apps developed to handle remote events such as List Added, Item Added, etc.,

If the user removes this app by mistake/intentional then the logic written to handle the remote events will not get executed so it’s an overhead for the governance/monitoring job.

Workaround

Deploy the mandatory apps from app catalog as explained here

Optimal Workaround

rer

  • Remove the RER code from the List Settings App (Samples.RER.App) and configure full tenant permissions so that we can attach the RER to any Web or List across the tenant.
  • Instead of installing the List Settings app (Samples.RER.App) in all the sites, install the app only in App Store site so that we have an app principle (app id and secret) that is trusted in our tenant.
  • Don’t deploy the remote web (Samples.RER.AppWeb) that gets created with the List Settings App project (provider hosted).

         Note: I assume you do not have any functionality written on the remote web that gets created with the List Settings App.

  • Create a web project(Samples.RER.Service) that implements the IRemoteEventService interface. This essentially means it must override the methods ProcessEvent and ProcessOneWayEvent methods. Make sure that your project now has the TokenHelper.cs class also. The clientcontext object is retrieved as an app only access token. This code is different from the code that is used normally for a RER.
  • Go back to our web project(Samples.RER.Service) and plug in the App id and secret for the List Settings App in the web.config file.
  • Deploy the app web project(Samples.RER.Service) to azure.
  • Use PowerShell/C# to add/remove receivers to different sites and for different events.
  • When the event occurs, SharePoint will reach out to the WCF Service URL with the event properties object (SPRemoteEventProperties).

The advantage with this setup is that you can keep updating your web project(Samples.RER.Service) and deploy to Azure and then use PowerShell/C# to add/remove receivers to different sites and for different events. There is no need to deploy, remove, redeployment of the app to attach the receivers.

Thank you Srinivas(MS PFE) for this idea.


Filed under: Azure, O365, SharePoint
Viewing all 55 articles
Browse latest View live