tag:blogger.com,1999:blog-28129105178356281912024-03-13T15:21:39.929+08:00The SharePoint Repair JointMaking the most of Microsoft Office 365, SharePoint, and NintexUnknownnoreply@blogger.comBlogger26125tag:blogger.com,1999:blog-2812910517835628191.post-52154686303180558212019-02-04T21:49:00.002+08:002021-08-25T14:06:09.658+08:00Add background colour to your Planner Cards - now available as a Chrome extension!<b>UPDATE:</b> Microsoft have changed the render model for Planner so unfortunately this approach doesn't work any more. This is no great surprise and my post was always disclaimed that this could happen at any time! <br/>
In the meantime, I've created another <a href="https://chrome.google.com/webstore/detail/planner-dark-mode/mnmohepacnhlohgdefiieeglgijicomo?hl=en-GB&gl=IL&pli=1&authuser=1">Chrome extension to make Planner render in Dark Mode</a> which is really cool!
<br/>
<br/>
One thing that bugs me about Planner is the way the Labels are presented on the Task Board. They are so small and don't really catch the eye - wouldn't it be better if the Task Card itself was given the colour of the label?<br />
<br />
Just like this:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUuOUlM_gtP2jYT8VwJ33osX917BVMRojfUaKCU6E8NrrsPJlKj9_FWFKEGhwEH6CSgXEbOVfX3ZwhB11kRwIVIhxy3xV7bbwb-n-ntM_OSis9RBQWVcCbURMP4UnL5I7Iojg3FSPvqKQ/s1600/Planner-Colours.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1101" data-original-width="1600" height="440" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUuOUlM_gtP2jYT8VwJ33osX917BVMRojfUaKCU6E8NrrsPJlKj9_FWFKEGhwEH6CSgXEbOVfX3ZwhB11kRwIVIhxy3xV7bbwb-n-ntM_OSis9RBQWVcCbURMP4UnL5I7Iojg3FSPvqKQ/s640/Planner-Colours.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Planner - with coloured tasks!</td></tr>
</tbody></table>
I think this makes a big Task Board much easier to visually scan, and I'm clearly not alone in wanting this based on <a href="https://microsoftteams.uservoice.com/forums/555103-public/suggestions/19086067-planner-card-background-label-color" target="_blank">this User Voice request</a>, and <a href="https://planner.uservoice.com/forums/330525-microsoft-planner-feedback-forum/suggestions/31096030-ability-to-change-background-color" target="_blank">this one</a>, and <a href="https://planner.uservoice.com/forums/330525-microsoft-planner-feedback-forum/suggestions/19312753-background-color-for-tasks" target="_blank">this one</a>, and <a href="https://planner.uservoice.com/forums/330525-microsoft-planner-feedback-forum/suggestions/11319927-support-individual-card-colors-in-board-view-to-al" target="_blank">this one</a>!<br />
<br />
Disclaimer time! Unfortunately Microsoft hasn't yet provided methods to customise Planner in an enterprise-ready, supportable manner. So this is a bit of a hack using client-initiated JavaScript injection. The approach is (by necessity) rather crude - it uses jQuery DOM examination to scan Task Cards to see if they any labels applied, and to force background colours accordingly. Cards can have multiple labels, but I chose in this implementation to simply use the first label applied - this will be the 'hottest' colour of the selected labels. I also chose to add a grey colour to unlabelled Cards and to give all cards a highlight colour down the left to match the Planner visual theming of labels.<br />
<br />
The approach relies heavily on specific mark-up structures and CSS class names which are liable to change at any time, so be aware that this will stop working at some point when Microsoft update Planner. I used an ugly approach to run the code every second - this ensures that the colours can be updated quickly as you change Cards labels, without requiring a page reload.<br />
<br />
So - without further ado, here's the code:<br />
<pre><code class="language-javascript">
// Script to colour code Planner tasks based on labels!
function colourisePlannerTaskCards() {
// Colourise task cards
$(".taskBoardCard").each( function(i) {
// Light theme works better for individual cards (otherwise we get contrast issues)
$(this).addClass("theme-light");
// Choose colour
if ($(this).find(".categoryLabelColor-0").length > 0)
{
$(this).find(".container").css("background",
"linear-gradient(to right,#e000f1 0,#e000f1 2%,#f777ff 2%,#f777ff 100%)");
}
else if($(this).find(".categoryLabelColor-1").length > 0)
{
$(this).find(".container").css("background",
"linear-gradient(to right,#e04e27 0,#e04e27 2%,#f9a286 2%,#f9a286 100%)");
}
else if($(this).find(".categoryLabelColor-2").length > 0)
{
$(this).find(".container").css("background",
"linear-gradient(to right,#e39e27 0,#e39e27 2%,#fbd18e 2%,#fbd18e 100%)");
}
else if($(this).find(".categoryLabelColor-3").length > 0)
{
$(this).find(".container").css("background",
"linear-gradient(to right,#aee01e 0,#aee01e 2%,#ddf48a 2%,#ddf48a 100%)");
}
else if($(this).find(".categoryLabelColor-4").length > 0)
{
$(this).find(".container").css("background",
"linear-gradient(to right,#46a08e 0,#46a08e 2%,#9cd5c7 2%,#9cd5c7 100%)");
}
else if($(this).find(".categoryLabelColor-5").length > 0)
{
$(this).find(".container").css("background",
"linear-gradient(to right,#62cef0 0,#62cef0 2%,#a7eeff 2%,#a7eeff 100%)");
}
else
{
$(this).find(".container").css("background",
"linear-gradient(to right,#a5a7a9 0,#a5a7a9 2%,#d5d7d9 2%,#d5d7d9 100%)");
}
$(this).find(".textContent").css("background", "none");
$(this).find(".bottomBar").css("background", "none").css("border-top", "none");
});
setTimeout(colourisePlannerTaskCards, 1000);
}
window.addEventListener('load', function(){
colourisePlannerTaskCards();
});
</code></pre>
<br />
Try it out and let me know what you think in the comments! And of course upvote the User Voice suggestions that I linked to at the top of the post.<br />
<br />
And as a final note, in creating this hack I noticed an interesting CSS class "theme-light" which is applied on the <body> element and heavily influences the CSS. If this is class changed (manually or through injected JavaScript) to "theme-dark" then suddenly we can see that <b>Microsoft has a partially implemented native dark theme for Planner!</b> It's ultra-high-contrast with bright green cards and it's clearly a work in development but I'm keen to see it fully implemented.Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-2812910517835628191.post-11439939857292256802018-03-04T23:16:00.002+08:002018-03-04T23:16:36.789+08:00Practical Nintex GovernanceFor those who asked for the slides, and for those who weren't fortunate enough to make it to San Diego for the amazing 2018 Nintex "xchange" conference, you can download the deck for my session "Practical Nintex Governance" from this page: <a href="http://nintex2018sessioncatalog.azurewebsites.net/SessionDetail.aspx?id=133432">http://nintex2018sessioncatalog.azurewebsites.net/SessionDetail.aspx?id=133432</a><br />
<br />
Hope to see you next year!Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-22185094955575666302017-05-10T11:47:00.001+08:002017-05-10T11:47:03.737+08:00Office 365 Groups in the Real WorldA massive shout out to all the organisers, sponsors, speakers and attendees for another very successful Office 365 Saturday Perth event over the weekend!<br />
<br />
As promised, here are the slides I presented on the day, I hope they are useful. Thanks to everyone for the positive feedback, it's clear that some of the key messages regarding Groups implementation really hit home for a few people!<br />
<br />
<iframe frameborder="0" height="288" scrolling="no" src="https://onedrive.live.com/embed?cid=A25594F409CC1A41&resid=A25594F409CC1A41%212715&authkey=ABgvSUY9PF7HxOA&em=2" width="476"></iframe>
<br />
Cheers,<br />
MartyUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-63802373850312062962016-04-05T10:58:00.001+08:002016-04-05T10:58:34.222+08:00Nintex InspireX Wrap UpYou couldn’t make it to Vegas? Don’t worry – here’s the low-down!<br />
<br />
<a href="http://www.empired.com/blog/Martin-Harris/dates/2016/4/Nintex-InspireX-wrap-up/">http://www.empired.com/blog/Martin-Harris/dates/2016/4/Nintex-InspireX-wrap-up/</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-32822598468638290142015-10-26T14:06:00.002+08:002015-10-26T14:14:17.419+08:00SharePoint Capacity Planning with Nintex (Part 1)<h4>
<span style="font-family: "Calibri",sans-serif; font-size: 11.0pt; line-height: 107%; mso-ansi-language: EN-AU; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">Using
Nintex Workflow to automatically manage thousands of Nintex Forms or other
SharePoint List Items</span></h4>
<h3>
SharePoint Capacity Planning</h3>
<div>
<div class="MsoNormal">
One of the great myths of SharePoint surrounds the List View
Threshold. The common story goes like this: someone creates a list or library
with the default configuration, then suddenly it starts getting some serious
use, and once it hits 5,001 items, people start seeing strange behaviour. People
then conclude that SharePoint can’t handle any more than 5,000 items, and negative
impressions of SharePoint are the result.</div>
<blockquote class="tr_bq">
Of course, <a href="https://technet.microsoft.com/en-us/library/cc262787.aspx#ListLibrary">SharePoint supports 30,000,000 items</a> in a list or library!</blockquote>
Effective use of large lists generally requires just a
little bit of capacity planning around your views and indexes. A simple
approach is to use folders and subfolders to ensure that there is a maximum of
5,000 child nodes (items and subfolders) at any given level. The best way to
ensure such a folder structure is maintained, is to completely automate it and remove
any need for human intervention – Nintex Workflow to the rescue!<br />
<h3>
The Business Problem</h3>
<div>
A client came to me recently and asked about implementation strategies for a Nintex Form that was going to receive <b><i>several hundred submissions every day</i></b>! Clearly some capacity planning would be required, otherwise the list would become unmanageable very quickly.</div>
<br />
So how can we construct a simple but clear Information Architecture? Ideally one that is reasonably generic so that it could be reused across multiple lists if required?<br />
<h3>
The Solution</h3>
<div>
The approach that I suggested was to build a subfolder structure that separates items based on a date. The date can be separated into year, month and day components, and the approach can use one, two or three levels of subfolders, depending on the expected capacity. Items would be stored at the leaf nodes in the structure.</div>
</div>
<div>
<br /></div>
<div>
The following table gives a sense of the capacities that would require second and/or third levels to be used, ensuring that we never exceed the 5,000 list view threshold.</div>
<div>
<br />
<table border="1" cellpadding="0" cellspacing="0" class="TableGrid1" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 1184; width: 557px;">
<tbody>
<tr>
<td style="background: #FCCE00; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 148.6pt;" valign="top" width="198"><div class="MsoNormal">
<b><span style="color: white; font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Number of Subfolder
Levels</span></b><b><span style="color: white; font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></b></div>
</td>
<td style="background: #FCCE00; border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 106.3pt;" valign="top" width="142"><div class="MsoNormal">
<b><span style="color: white; font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Subfolder Levels</span></b><b><span style="color: white; font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></b></div>
</td>
<td style="background: #FCCE00; border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 163.05pt;" valign="top" width="217"><div class="MsoNormal">
<b><span style="color: white; font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Expected items created
per day</span></b><b><span style="color: white; font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></b></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 148.6pt;" valign="top" width="198"><div class="MsoNormal">
<b><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">1</span></b><b><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 106.3pt;" valign="top" width="142"><div class="MsoNormal">
<span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Year</span><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 163.05pt;" valign="top" width="217"><div class="MsoNormal">
<span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Up
to 12</span><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="background: #505050; border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 148.6pt;" valign="top" width="198"><div class="MsoNormal">
<b><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">2</span></b><b><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></b></div>
</td>
<td style="background: #505050; border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 106.3pt;" valign="top" width="142"><div class="MsoNormal">
<span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Year
and Month</span><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></div>
</td>
<td style="background: #505050; border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 163.05pt;" valign="top" width="217"><div class="MsoNormal">
<span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Up
to 150</span><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 148.6pt;" valign="top" width="198"><div class="MsoNormal">
<b><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">3</span></b><b><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 106.3pt;" valign="top" width="142"><div class="MsoNormal">
<span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Year,
Month and Day</span><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 163.05pt;" valign="top" width="217"><div class="MsoNormal" style="page-break-after: avoid;">
<span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Up to 5000</span><span style="font-family: "Segoe UI",sans-serif; font-size: 10.0pt; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: Calibri;"><o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
</div>
<div>
<br /></div>
<div>
<div class="MsoNormal">
So for my client and their hundreds of forms every day, we
would need to use all three levels.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
Here’s a diagram of how this folder structure would be
constructed, and also a naming convention which aligns chronological ordering
with alphanumeric ordering:<br />
<div class="MsoNormal">
<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDref9R4hFpjfI1cL0gr-cpK5afqvajMVtWMFQyRcfZahC5-yG4T5436JnkhzWDyz3jk-PKQmyYU0XiJsY1ZyEkpVPywAlu_bFw474Sa41pHvfk7741hd62QvibrgnSaKBAti8ZAs1ue8/s1600/NintexCapacityPlanningFolderStructure.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDref9R4hFpjfI1cL0gr-cpK5afqvajMVtWMFQyRcfZahC5-yG4T5436JnkhzWDyz3jk-PKQmyYU0XiJsY1ZyEkpVPywAlu_bFw474Sa41pHvfk7741hd62QvibrgnSaKBAti8ZAs1ue8/s400/NintexCapacityPlanningFolderStructure.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Subfolder structure for automated filing and capacity management</td></tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
For each item to be filed into this structure, we need to nominate a specific date for the item. This date value could be the date of item creation, or in a Nintex Workflow context, it could be the date when the Workflow meets a milestone point such as process completion.</div>
<h3>
Managing Item URLs</h3>
<div>
Nintex Forms are managed within SharePoint as <b><i>List Items</i></b> rather than as Documents, and List Items have a very neat property whereby you can move them around the folder structure within a library, without changing their URLs! So we can move items into their subfolder structure at any time within their lifecycle, without impacting on end users or creating dead hyperlinks. Note that if you try this with documents, then you’ll see that the URL of each document will change to reflect its position within the folder structure, and this will lead to broken hyperlinks and frustrated end users!</div>
<blockquote class="tr_bq">
This approach will work with any List Items, including Nintex Forms, but is not as neat for Documents because of URL changes</blockquote>
<h3>
Implementation Considerations</h3>
This solution concept is very generic; it only requires the list items to be associated with a date. It is not coupled to the schema of a specific list or a Nintex Form schema, so we can implement the process within a User Defined Action (UDA). The UDA can then be quickly and reliably dragged and dropped into any Workflow across the SharePoint system, gaining huge reuse and management benefits. If you’re not familiar with UDAs, <a href="https://community.nintex.com/community/build-your-own/blog/2014/05/12/best-practice-for-workflow-design-user-defined-actions">check out this Nintex Community article</a>.<br />
<br />
There is always a trade-off in software development, and in this case, the selection to use a UDA increase reusability but introduces some build complexity because list item context is not available in the Nintex Workflow designer.<br />
<h3>
Build</h3>
<div>
Stay tuned for part 2 where we build the UDA which automatically files list items into the described subfolder structure, building out folders as required.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-69467773503963378942015-05-24T14:58:00.000+08:002015-05-24T14:58:17.836+08:00Slide Deck from Office 365 Satuday Perth #o365perMassive thanks to Haylee for organising another very successful Office 365 Saturday event in Perth, and thanks to the sponsors, presenters and attendees for contributing to the day!<br />
<br />
As promised, <a href="http://1drv.ms/1RdTM9w">here's the slide deck</a> from my presentation: "The evolving Office 365 landscape - Build and Ignite".<br />
<br />
I hope that everyone picked up something useful from the presentation and from the day.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-83003340687776487982015-05-02T20:26:00.001+08:002015-05-02T20:26:06.503+08:00SharePoint Explorer updated with the latest Office 365 CSOM APIsFor those that may have missed it, Microsoft recently <a href="http://blogs.msdn.com/b/vesku/archive/2015/04/10/new-sharepoint-csom-version-released-for-office-365.aspx">released a significant update</a> to the CSOM capabilities of Office 365.<br />
<br />
So that makes it a great time to update the SharePoint Explorer tool that I have blogged about previously (<a href="http://sharepointrepairjoint.blogspot.com.au/2012/07/sharepoint-2013-explorer.html">here </a>and <a href="http://sharepointrepairjoint.blogspot.com.au/2012/05/sharepoint-explorer-365.html">here</a>).<br />
<br />
The <a href="http://1drv.ms/1GQ3vAJ">updated download is available here</a>. Please read through the previous blog posts to understand the tool and its usage.<br />
<br />
Enjoy!Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-2812910517835628191.post-54203419740443810112015-02-19T17:59:00.003+08:002015-02-19T18:03:13.050+08:00Visual Studio intellisense for NWF$ - jQuery inside Nintex FormsThose who have written custom JavaScript to act within Nintex Forms are probably familiar with the <b>NWF$</b> construct which is the name that Nintex has given to the jQuery object - which by convention is usually called just <b>$</b>.<br />
<br />
This allows us to harness the power of jQuery but necessitates using a different naming convention that Visual Studio intellisense just doesn't understand. So, here's a quick tip on how you can get everything working nicely in your IDE.<br />
<br />
Firstly, work out the version of jQuery that is in use (I can see from tracing my browser session that Nintex Forms 365 is currently using version 1.10.2, from https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.10.2.min.js).<br />
<br />
In your Visual Studio project, open up the <b>Package Manager Console </b>(you can find it from the "View" menu under "Other Windows"), and type in the following command (note the version number is used to make sure intellisense knows exactly which commands should be available):<br />
<pre class="" name="code">Install-Package jQuery-vsdoc -Version 1.10.2</pre>
This will bring in the appropriate files for jQuery and intellisense, but intellisense will only work against the <b>$</b> or <b>jQuery </b>names, not against the <b>NWF$</b> name as used by Nintex.<br />
<br />
To allow intellisense to understand the <b>NWF$</b> name, we need to amke a small modification to one of the files added by the Package Installation process. In the Solution Explorer, find the file whose name ends with <b>vsdoc.js</b> - in my case, this is <b>jquery-1.10.2-vsdoc.js</b>. Open up this file and scroll right to the bottom, where you'll see this fragment:<br />
<pre class="brush: js" name="code">jQuery.fn = jQuery.prototype;
jQuery.fn.init.prototype = jQuery.fn;
window.jQuery = window.$ = jQuery;
})(window);
</pre>
Now add the following line:<br />
<pre class="brush: js" name="code">NWF$ = jQuery;
</pre>
so that the end of the file now looks like this:<br />
<pre class="brush: js" name="code">jQuery.fn = jQuery.prototype;
jQuery.fn.init.prototype = jQuery.fn;
window.jQuery = window.$ = jQuery;
NWF$ = jQuery;
})(window);
</pre>
Save the file, and that's it!<br />
<br />
Now, when you start using NWF$, Visual Studio will understand what you're doing and will help suggest jQuery functions for you:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyKZv68P4ixfGXRjaFLYbr6FizG6jt_WbIRsUZzQtjsg0vxlVl15Aj8KK-gaXhcDZE1cv2OZOv299eQGilCaK_HkwvhRHFTT0LaoSPSnv6ywFisuz8_U145k8PskaJsfl-yupNc-yhL6c/s1600/NWF_Intellisense1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyKZv68P4ixfGXRjaFLYbr6FizG6jt_WbIRsUZzQtjsg0vxlVl15Aj8KK-gaXhcDZE1cv2OZOv299eQGilCaK_HkwvhRHFTT0LaoSPSnv6ywFisuz8_U145k8PskaJsfl-yupNc-yhL6c/s1600/NWF_Intellisense1.png" height="228" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Visual Studio intellisense against the NWF$ object</td></tr>
</tbody></table>
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-27470793711192342282014-08-30T09:55:00.002+08:002014-08-30T09:56:55.288+08:00PowerShell cmdlet to Import Nintex User Defined Actions (UDAs)Anyone who is doing non-trivial Workflow development in Nintex should be aware of UDAs; Nintex has a great summary of them <a href="https://community.nintex.com/community/build-your-own/blog/2014/05/12/best-practice-for-workflow-design-user-defined-actions">here</a>, and I've already blogged about important considerations for automated importing of these <a href="http://sharepointrepairjoint.blogspot.com.au/2014/04/automated-publishing-of-nintex-workflow.html">here</a>.<br />
<br />
The next logical step from my last blog post then is to create a PowerShell cmdlet to make this process nice and neat - so here it is! As with <a href="http://sharepointrepairjoint.blogspot.com.au/2014/07/powershell-cmdlet-to-provision-nintex.html">my PowerShell cmdlet to provision Nintex Workflow Constants</a>, this needs to be run on a SharePoint server within the Farm - sorry to those who don't have server access! I'm always interested to hear about remote methods that can achieve these results, let me know in the comments in you find out how this can be done.<br />
<br />
You can <a href="http://1drv.ms/1qoJfvj">view and download the cmdlet here</a>. Note that the file has been renamed with a .ps1.txt file extension as some data transfer mechanisms block .ps1 files as a security concern - so you'll need to rename the file to have a .ps1 extension after you download it.<br />
<pre class="brush: powershell" name="code"><#
.SYNOPSIS
Publishes a Nintex Workflow UDA (User Defined Action), keeping it's original GUID intact!
.DESCRIPTION
Because this approach retains GUIDs, you should avoid deploying the same UDA multiple times
in an environment. If you want to reuse your UDA in a broader scope that where it is defined,
you should promote it to a higher level rather than duplicating it.
This script is designed for moving UDAs between farms.
.PARAMETER <Scope>
Mandatory - where the UDA is defined. Must be one of: Farm, SiteCollection, Web
.PARAMETER <Url>
Mandatory - the URL of the Site. Note that even for a Farm UDA you need to specify the URL of a valid Web for the publishing process to work.
.PARAMETER <UdaFilePath>
Mandatory - the full Path to the .uda file.
.PARAMETER <ChangeComments>
Optional - but allows comments to be added to the publish process.
.PARAMETER <Publish>
Optional - deafult value is $true. Using $false will allow it to be imported without publishing.
.EXAMPLE
#Here's an example that publishes a Farm level UDA:
.\Publish-NintexUda.ps1 `
-Scope "Farm" `
-Url "http://myfarm/sites/myweb" `
-UdaFilePath "C:\ExampleUda.uda" `
#>
Param(
[Parameter(Mandatory = $true, Position = 1)]
[string] $Scope,
[Parameter(Mandatory = $true, Position = 2)]
[string] $Url,
[Parameter(Mandatory = $true, Position = 3)]
[string] $UdaFilePath,
[Parameter(Mandatory = $false, Position = 4)]
[string] $ChangeComments = "",
[Parameter(Mandatory = $false, Position = 5)]
[bool] $Publish = $true
)
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SharePoint') | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName('Nintex.Workflow') | Out-Null
function global:ImportNintexWorkflowUDA($filePath, $web, $publish, $configScope, $publishScope, $comments)
{
$fs = New-Object System.IO.FileStream($filePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$ms = New-Object System.IO.MemoryStream
# This only works for .NET 4 and above, so it won't work in SP 2010
# $fs.CopyTo($ms)
# Here's the more compatible (and ugly) alternative
$buffer = New-Object Byte[] 4096
$read = $fs.Read($buffer, 0, $buffer.Length)
while ($read -gt 0)
{
$ms.Write($buffer, 0, $read)
$read = $fs.Read($buffer, 0, $buffer.Length)
}
$fs.Close()
$fs.Dispose()
$uda = [Nintex.Workflow.UserDefinedActions.UserDefinedAction]::Import($web, $ms, $configScope)
$uda.Update($web, $publish, $publishScope, $comments)
$ms.Close()
$ms.Dispose()
}
$ArgsValid = $true
if ($Scope -ne "Farm" -and $Scope -ne "SiteCollection" -and $Scope -ne "Web")
{
Write-Host "Error - Scope parameter must be one of: Farm, SiteCollection, Web" -ForegroundColor Red
$ArgsValid = $false
}
$configScope = $null
$publishScope = $null
if ($Scope -eq "Farm")
{
$configScope = [Nintex.Workflow.ConfigurationScope]::Farm
$publishScope = [Nintex.Workflow.Publishing.Scope]::Farm
}
if ($Scope -eq "SiteCollection")
{
$configScope = [Nintex.Workflow.ConfigurationScope]::Site
$publishScope = [Nintex.Workflow.Publishing.Scope]::SiteCollection
}
if ($Scope -eq "Web")
{
$configScope = [Nintex.Workflow.ConfigurationScope]::Web
$publishScope = [Nintex.Workflow.Publishing.Scope]::Web
}
if ($ArgsValid)
{
$web = $null
$web = Get-SPWeb $Url
if ($web -ne $null)
{
Write-Host ("Attempting to publish UDA... ") -NoNewline
ImportNintexWorkflowUDA $UdaFilePath $web $Publish $configScope $publishScope $ChangeComments
Write-Host "done"
}
}
</pre>
Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-2812910517835628191.post-27574939801203782512014-07-26T14:45:00.001+08:002014-08-30T09:27:18.814+08:00PowerShell cmdlet to provision Nintex Workflow ConstantsIf you are building Nintex Workflows, and especially if you are deploying them across multiple environments, then you should be considering using Nintex Workflow constants. These constants are remarkably useful to make your Nintex Workflows portable, so that they can easily be deployed into multiple environments without confusion or wasted effort. Any workflow parameters which are specific to the environment in which the workflow is running, or which are likely to be changed by the business at some stage, should be built into your workflows using these constants.<br />
<br />
Many of our clients are looking to improve their processes for deploying and managing SharePoint and Nintex based functionality, and the critical aspects tend to fall around governance and repeatability. So in the interests of repeatability, here's a PowerShell cmdlet to create a new Nintex Workflow constant.<br />
<br />
With this script you can specify any type of constant, including credentials which are useful for service accounts. You can also define the constant at a scope of Farm, Site Collection or Site.<br />
<br />
The cmdlet needs to be run on a server within the SharePoint farm where the constant is to be created. If anyone is aware of alternate methods that can be run remotely, please let me know in the comments!<br />
<br />
You can <a href="http://1drv.ms/1zetVoN">view and download the cmdlet here</a>. Note that the file has been renamed with a <b>.ps1.txt</b> file extension as some data transfer mechanisms block .ps1 files as a security concern - so you'll need to rename the file to have a <b>.ps1</b> extension after you download it.
<br />
<pre class="brush: powershell" name="code">
<#
.SYNOPSIS
Creates a Nintex Workflow Constant
.DESCRIPTION
.PARAMETER <Name>
Mandatory - the Name of the Constant. Keep these unique!
.PARAMETER <Description>
Mandatory - the Description of the Constant. Use this to help other developers understand what it's used for.
.PARAMETER <Type>
Mandatory - the Type of the Constant. Must be one of: Number, String, Date, SecureString, Credential
.PARAMETER <Scope>
Mandatory - where the Constant is defined. Must be one of: Farm, SiteCollection, Web
.PARAMETER <Value>
Optional - the value of the Constant. This isn't used for Credential type constants, but it's Mandatory for every other type.
.PARAMETER <Url>
Optional - but Mandatory is the Scope is SiteCollection or Web. Defines where the Constant should live.
.PARAMETER <Sensitive>
Optional - default value is $false.
.PARAMETER <AdminOnly>
Optional - default value is $false.
.PARAMETER <Username>
Optional - but Mandatory if Type is Credential.
.PARAMETER <Password>
Optional - but Mandatory if Type is Credential.
.EXAMPLE
#Here's an example that generates a Sensitive, Credential type constant at Web level:
.\Create-NintexWFConstant.ps1 `
-Name "test" `
-Description "Example only" `
-Scope "Web" `
-Type "Credential" `
-Sensitive $true `
-Username "DOMAIN\user" `
-Password "password123" `
-Url "http://myfarm/sites/myweb"
#Here's a second example that creates a Farm string type Constant:
.\Create-NintexWFConstant.ps1 `
-Name "test2" `
-Description "Example only" `
-Scope "Farm" `
-Type "String" `
-Value "example constant value"
#>
Param(
[Parameter(Mandatory = $true, Position = 1)]
[string] $Name,
[Parameter(Mandatory = $true, Position = 2)]
[string] $Description,
[Parameter(Mandatory = $true, Position = 3)]
[string] $Type,
[Parameter(Mandatory = $true, Position = 4)]
[string] $Scope,
[Parameter(Mandatory = $true, Position = 5)]
[string] $Value,
[Parameter(Mandatory = $false, Position = 6)]
[string] $Url,
[Parameter(Mandatory = $false, Position = 7)]
[bool] $Sensitive = $false,
[Parameter(Mandatory = $false, Position = 8)]
[bool] $AdminOnly = $false,
[Parameter(Mandatory = $false, Position = 9)]
[string] $Username = "",
[Parameter(Mandatory = $false, Position = 10)]
[string] $Password = ""
)
[System.Reflection.Assembly]::LoadWithPartialName('Nintex.Workflow') | Out-Null
$ArgsValid = $true
if ($Type -ne "Number" -and $Type -ne "String" -and $Type -ne "Date" -and $Type -ne "SecureString" -and $Type-ne "Credential")
{
Write-Host "Error - Type parameter must be one of: Number, String, Date, SecureString, Credential." -ForegroundColor Red
$ArgsValid = $false
}
if ($Type -eq "Credential")
{
if ($Username -eq $null -or $Username -eq "" -or $Password -eq $null -or $Password -eq "")
{
Write-Host "Credential Error - Username and Password combination not supplied." -ForegroundColor Red
$ArgsValid = $false
}
# Generate string for Credential
$cred = New-Object Nintex.Workflow.CredentialValue($Username, $Password)
$serialiser = New-Object System.Xml.Serialization.XmlSerializer($cred.GetType())
$sb = New-Object System.Text.StringBuilder
$sw = New-Object System.IO.StringWriter($sb)
$serialiser.Serialize($sw, $cred)
$Value = $sb.ToString()
}
else
{
if ($Value -eq $null -or $Value -eq "")
{
Write-Host "Error - Value must be supplied for Constants of Type other than Credential." -ForegroundColor Red
$ArgsValid = $false
}
}
$SiteId = [Guid]::Empty
$WebId = [Guid]::Empty
if ($Scope -eq "Farm")
{
#Use default SiteId and WebId values
}
else
{
if ($Scope -eq "SiteCollection")
{
$SiteId = (Get-SPSite $Url).Id
}
else
{
if ($Scope -eq "Web")
{
$Web = Get-SPWeb $Url
$WebId = $Web.Id
$SiteId = $Web.Site.Id
}
else
{
Write-Host "Error - Scope parameter not valid: must be one of Farm, SiteCollection, Web." -ForegroundColor Red
$ArgsValid = $false
}
}
}
if ($ArgsValid)
{
Write-Host ("Attempting to create Workflow Constant " + $Name + " ... ") -NoNewline
$constant = New-Object Nintex.Workflow.WorkflowConstant(`
$Name, $Description, $Value, $Sensitive, $SiteId, $WebId, $Type, $AdminOnly)
$constant.Update()
Write-Host "done"
}
</pre>Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-2812910517835628191.post-92103321023370157972014-06-22T20:25:00.000+08:002014-06-22T20:25:20.039+08:00Building a SharePoint Forms Platform: SharePoint Saturday Slide DeckSharePoint Saturday Perth 2014 was a huge success - we had more attendees than any other SharePoint Saturday in Australian history! Massive thanks to everyone who came along, to all the presenters, and of course to the sponsors and organisers.<br />
<br />
As promised, here's the slide deck that I presented on the day - Building a SharePoint Forms Platform: Real World Considerations and Lessons. Enjoy!<br />
<br />
<a href="http://1drv.ms/1pzksEZ">http://1drv.ms/1pzksEZ</a><br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-6190663202061602252014-04-04T08:00:00.003+08:002014-04-04T08:00:30.290+08:00Automated publishing of Nintex Workflow User Defined Actions, with workflow referencesOne of my absolute favourite features in Nintex Workflow is the User Defined Action (UDA). It lets you wrap up a commonly used piece of functionality with defined input and output parameters, into a neat, centrally managed object, which can be easily reused in workflows across the entire farm. A UDA can also easily be updated whereby Nintex Workflow automatically updates all workflows that reference the UDA.<br />
<br />
For a workflow project we are currently building, I was a little disappointed to find that there is no supported method to <a href="http://connect.nintex.com/forums/thread/26976.aspx">automate the import of a UDA</a>. This slows down our planned deployment process which is nearly entirely automated through PowerShell.<br />
<br />
What was even more troubling was that importing a UDA through the user interface did not work correctly for imported workflows that referenced the UDA. Each UDA referenced within a workflow appeared like this:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNbi89U6E8n_jmWHP4Lquu5FpjeNeQRxZGjVZZ0qzKdIvVtOPyhdOYtjQEXEThUxNwmsS7fGyU7bnmCYnZugGTin5WA9eLhsz_gijKQC4qHKpELr4U3z8Q0Y14uKeVIb7fiTPHPJaO_eY/s1600/BrokenUDA1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNbi89U6E8n_jmWHP4Lquu5FpjeNeQRxZGjVZZ0qzKdIvVtOPyhdOYtjQEXEThUxNwmsS7fGyU7bnmCYnZugGTin5WA9eLhsz_gijKQC4qHKpELr4U3z8Q0Y14uKeVIb7fiTPHPJaO_eY/s1600/BrokenUDA1.png" height="121" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This is how a UDA appears in a workflow if the reference is broken, for example through an import process</td></tr>
</tbody></table>
Attempting to configure the UDA only threw exceptions. The only way to resolve this was to manually delete the UDA references, replace them with new references, and update all the parameters in the references. This is very slow, error-prone and frustrating!<br />
<br />
With some investigation, it turns out that each UDA has an internal GUID identifier which is used by workflows to reference the UDA. This GUID can been seen in both the exported .uda and .nwf files. It seems that when importing a UDA through the user interface, a new GUID is assigned to the UDA. This is what was breaking the references.<br />
<br />
Warning: the solution I am presenting here is not technically part of the supported Nintex Workflow API, so it is not guaranteed to work for all future releases, but it works for my initial testing against Nintex Workflow 2013 version 3.0.6.0. This process is based on the suggestion from user <b>tburdin </b>on the excellent <a href="http://connect.nintex.com/">Nintex Connect Forums</a>, in <a href="http://connect.nintex.com/forums/thread/16402.aspx">this thread</a>. It uses the publicly exposed members of the Nintex Workflow assemblies to automate the import of UDAs. Here is the PowerShell snippet:<br />
<br />
<pre class="brush: powershell" name="code">[System.Reflection.Assembly]::LoadWithPartialName('Nintex.Workflow') | Out-Null
$fs = New-Object System.IO.FileStream($filePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$ms = New-Object System.IO.MemoryStream
$fs.CopyTo($ms)
$fs.Close()
$fs.Dispose()
$uda = [Nintex.Workflow.UserDefinedActions.UserDefinedAction]::Import($web, $ms, [Nintex.Workflow.ConfigurationScope]::Site)
$uda.Update($web, $publish, [Nintex.Workflow.Publishing.Scope]::SiteCollection, "")
$ms.Close()
$ms.Dispose()
</pre>
<br />
Note that the code assumes you've populated the following variables:<br />
<ul>
<li><b>$name</b>: the name of your UDA.</li>
<li><b>$filePath</b>: the full path to your exported .uda file.</li>
<li><b>$web</b>: the SPWeb object defining the context of where the UDA is going to be imported</li>
<li><b>$publish</b>: a Boolean value indicating whether to publish the UDA or simply import it</li>
</ul>
<div>
The above code publishes to the Site Collection level, but you can also publish to a single site or even to the entire Farm, by altering the values of the Nintex enumerations referenced in the code. To publish to a single site, use <b>[Nintex.Workflow.ConfigurationScope]::Web</b> and <b>[Nintex.Workflow.Publishing.Scope]::Web</b>, and to publish to a farm, use <b>[Nintex.Workflow.ConfigurationScope]::Farm</b> and <b>[Nintex.Workflow.Publishing.Scope]::Farm</b>.
<br />
<br />
The best aspect of this process is that it retains the original GUID reference of each UDA. So, when you import UDA using this method and then import workflows that reference the original UDAs, no re-wiring is required! You can fully automate the process and have a portable workflow deployment strategy.<br />
<br />
It's worth noting that Nintex probably updates those GUIDs during the import process to ensure that you can never get in a situation where you have multiple UDAs in a farm that use the same GUID. For example, you could import the same UDA into multiple sites (you wouldn't want to do this, but it would certainly be possible). In this scenario, having two or more UDAs with the same GUID would almost certainly cause conflicts. Use with caution!</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-72057845539036374542013-10-31T18:47:00.000+08:002013-10-31T18:47:06.122+08:00Help! I deleted my root site!Don't laugh! This happened to a colleague of mine quite recently, and in the past I have seen consultants lose contracts for making this mistake. The last thing you want to be doing is an unscheduled test of the restore process and explaining the finer details of <a href="http://en.wikipedia.org/wiki/Recovery_time_objective">RTO </a>and <a href="http://en.wikipedia.org/wiki/Recovery_point_objective">RPO </a>to your stakeholders... that's a scary thought for Halloween!<br />
<br />
Since SharePoint 2010 Service Pack 1, we have had the Site Recycle Bin available to restore accidentally deleted sites. However, to access this you need to go to the root site of the site collection containing the site you deleted. If you deleted the root site itself, this is not possible anymore.<br />
<br />
Although it may not be immediately obvious (especially to content owners who don't wade into Central Administration), deleting a root site is <b>essentially the same operation as deleting the entire site collection. The Site Collection Recycle Bin works in both cases.</b><br />
<br />
Using the Site Collection Recycle Bin is pretty easy but it does require PowerShell, and you'll need to either be on SharePoint 2013 or have 2010 with Service Pack 1 installed.<br />
<br />
Run <b><a href="http://technet.microsoft.com/en-us/library/hh286316.aspx">Get-SPDeletedSite</a></b> to get a list of all deleted site collections in the farm.<br />
<br />
Then, use the ID of your specific site collection with the <b><a href="http://technet.microsoft.com/en-us/library/hh286319.aspx">Restore-SPDeletedSite</a></b> command.<br />
<br />
Simple!<br />
<br />
Note to Microsoft: perhaps the "Delete this site" shouldn't be shown for a root web and we can leave the deletion of site collections to those who can access Central Admin or PowerShell. This would provide a symmetry with the creation of site collections.<br />
<br />
Note to SharePoint users: always be careful that you're actually in the site you think you're in before you delete a site!Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-2812910517835628191.post-90484476975454830272013-07-31T15:12:00.000+08:002013-08-06T20:44:56.005+08:00Why can't I create Community Sites in a Community Portal?The Communities workload is a fantastic addition to SharePoint 2013; check out <a href="http://technet.microsoft.com/en-us/library/jj219805.aspx">here</a> for an overview of the feature set.<br />
<br />
When creating a new Community Portal site collection, it's natural to immediately want to create Community Sites. If your planned Communities Information Architecture is very small – or you’re doing testing or development – then you might want to create Community Sites as sub-sites of the Community Portal.<br />
<br />
Unfortunately I've seen several SharePoint 2013 environments now where this is simply not possible out-of-the-box. Attempting to create a sub-site of a brand new Community Portal only offers a limited set of site templates which does not include Community Site:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLmLr3_pVz5R_DKPocdofDCLPCcwfwhcyC_bTVRYmSv1saw0hHDOcY1RPCWfLlMSL4b4TSmTdpKMSpF9Ke-AywTw8Q25boGT_oIRZwQeqbZf0p4vz6cLwNI4STeviQZMD6z4EJfFyflFs/s1600/CommunityPortal1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="341" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLmLr3_pVz5R_DKPocdofDCLPCcwfwhcyC_bTVRYmSv1saw0hHDOcY1RPCWfLlMSL4b4TSmTdpKMSpF9Ke-AywTw8Q25boGT_oIRZwQeqbZf0p4vz6cLwNI4STeviQZMD6z4EJfFyflFs/s400/CommunityPortal1.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">There's no Community Site option...</td></tr>
</tbody></table>
This is a little frustrating, but it is easily fixed!<br />
<br />
Go into <b>Site Settings</b> for your Community Portal, and select <b>Site Collection Features</b>. Make sure that <b>SharePoint Server Standard Site Collection Features</b> is activated - by default this may not be active:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi70fkHD-iiMO4rrW5V3E-wX-zavFFApVH4q-GQBulMoJ_PglQntPwmX8YfTAXVMZzuVTUXmlCTFJOliIrpg-BFnIQ8axltvAwmBdpNLJ_HuLy_GKvaNoKMxJIRqZIXGTHW8BT3GO7KDJM/s1600/CommunityPortal2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="21" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi70fkHD-iiMO4rrW5V3E-wX-zavFFApVH4q-GQBulMoJ_PglQntPwmX8YfTAXVMZzuVTUXmlCTFJOliIrpg-BFnIQ8axltvAwmBdpNLJ_HuLy_GKvaNoKMxJIRqZIXGTHW8BT3GO7KDJM/s400/CommunityPortal2.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Once this is done, you can create Community sites:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTB5jk0sldk0_-X772nqZTOwxYJZsir-H6HLhQ0_kj4YHMKunVDxZh9zSP5_uB1Q412hey1tN4pmH27NGHUxe55sUB5TKRRCC_nNxNjqtIfYflWeqrSI7hvglt_j8tf0CKU6yWbgHOB9w/s1600/CommunityPortal3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="380" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTB5jk0sldk0_-X772nqZTOwxYJZsir-H6HLhQ0_kj4YHMKunVDxZh9zSP5_uB1Q412hey1tN4pmH27NGHUxe55sUB5TKRRCC_nNxNjqtIfYflWeqrSI7hvglt_j8tf0CKU6yWbgHOB9w/s400/CommunityPortal3.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">That's better!</td></tr>
</tbody></table>
From here, you may find that you receive the following error when attempting to create a Community Site:<br />
<br />
Dependency feature 'Ratings' (id: 915c240e-a6cc-49b8-8b2c-0bff8b553ed3) for feature 'CommunitySite' (id: 961d6a9c-4388-4cf2-9733-38ee8c89afd4) is not activated at this scope.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQiUrM1MkoLobv23Tbl86wYW1D0QxBQwGCqXh8lGhEWGwmPDtsvpZShl6MNQ-P4v68ykugxgKmsGRwNq46MrBG2EbhmD1_8_U115a8bBHLdT8lKHjv7y9Cll2QxsT8uVBXHk-gP4T9zDE/s1600/CommunityPortal4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="55" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQiUrM1MkoLobv23Tbl86wYW1D0QxBQwGCqXh8lGhEWGwmPDtsvpZShl6MNQ-P4v68ykugxgKmsGRwNq46MrBG2EbhmD1_8_U115a8bBHLdT8lKHjv7y9Cll2QxsT8uVBXHk-gP4T9zDE/s400/CommunityPortal4.png" width="400" /></a></div>
<br />
This one is also pretty easy to solve; just run the following PowerShell command will activate the dependent hidden Feature referenced in the above message:<br />
<br />
<pre name="code">Enable-SPFeature –Identity Ratings –url [site collection URL]</pre>
<br />
Now you're good to go!Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-2812910517835628191.post-3530021042318961812013-05-28T21:30:00.000+08:002013-05-28T21:30:03.491+08:00SharePoint 2013 and Visio 2013: Visualise SuccessThanks to those who attended today's presentation on SharePoint 2013 and Visio 2013!<br />
<br />
As promised, <a href="http://sdrv.ms/18q5ZUu">here are the slides</a> from today's presentation. Thanks to William Cornwill from Microsoft for the material and the opportunity to present, it's always good to get people thinking about how they can use the broad Microsoft tool set to achieve business goals.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-42725450061095777052013-05-20T19:53:00.000+08:002013-05-21T08:38:12.136+08:00Synchronising Active Directory User Attributes into SharePoint Online User Profile Properties: Part 2I have received quite a bit of interest in the Active Directory / Office 365 User Profile synchronisation implementation that has been <a href="http://sharepointrepairjoint.blogspot.com.au/2013/01/synchronising-active-directory-user.html">mentioned previously in this blog</a>, as well as in some <a href="http://sharepointrepairjoint.blogspot.com.au/2013/02/perth-sharepoint-user-group.html">local SharePoint community presentations</a>, so I thought it would be a good time to write it up in a bit more detail.<br />
<br />
<b>Goal:</b><br />
Customise the Office 365 User Profile Syncronisation Service to synchronise additional attributes (e.g. Mobile phone number) from Active Directory into Office 365.<br />
<br />
<b>Constraint:</b><br />
SharePoint Online <a href="http://sharepointrepairjoint.blogspot.com.au/2013/01/synchronising-active-directory-user.html">does not allow us to change mappings</a> for the built-in User Profile Syncronisation service.<br />
<br />
<b>Solution:</b><br />
Build a custom automated connector that synchronises Active Directory and SharePoint Online User Profiles.<br />
<br />
<b>Approach:</b><br />
Out of the various APIs offered by SharePoint, the only method that we found we could update User Profile information programmatically was by using the <b>UserProfileService.asmx</b> web service. Note that our investigations were conducted against a SharePoint 2010 based tenancy; new 2013 based tenancies offer REST web services which will probably be able to achieve the same goal.<br />
<br />
The primary difficulty we found with using the web service was that many operations (including any updates to a SharePoint Online User Profile) would only succeed if the call to the web service was made whilst authenticated as the user who owns the profile being queried or updated! Not even when authenticated as a global tenant administrator and site collection administrator can you programmatically update someone else's User Profile, which is a bit strange given that SharePoint allows you to do exactly this through the tenancy administration interface.<br />
<br />
The way we got around this authentication problem was by performing the User Profile update operation from within JavaScript code which is embedded into the Master Page of the My Site Host site collection. This custom JavaScript code runs every time a user loads any page within the site collection, and because it runs in the user's browser, the Client OM operations within the code run in the context of the current user, who is authorised to update their own User Profile. But how does the JavaScript code know what values to write into the User Profile?<br />
<br />
This is where things get complicated! We set up a temporary data holding area (just a large custom SharePoint list) within the My Site Host. We built a custom on-premises Windows Service to query AD and push user data into the custom list on a periodic schedule. The data is then already sitting inside the My Site Host site collection and can be queried from our custom JavaScript code using the Client OM.<br />
<br />
The following diagram helps to illustrate the process (click to expand):<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDm5jlyALDoffOwToDXdxwOpLtFSInqn8lz-Rd0J6LQ3uTBVxh8qpC2b315mRbSN_cBh8DJCz4nYyMVNVwXKMFaskiFmhzjYCYscANEetMj41fnWUDa3yZ2h-Rfz_erFognVgaXo1tJtA/s1600/AD365ConnectorDiagram.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="209" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDm5jlyALDoffOwToDXdxwOpLtFSInqn8lz-Rd0J6LQ3uTBVxh8qpC2b315mRbSN_cBh8DJCz4nYyMVNVwXKMFaskiFmhzjYCYscANEetMj41fnWUDa3yZ2h-Rfz_erFognVgaXo1tJtA/s400/AD365ConnectorDiagram.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data flow of the custom AD / Office 365 connector</td></tr>
</tbody></table>
To follow this diagram, let's start with just the red arrows. On the left hand side of the brick wall (the corporate firewall) we have the on-premises elements of the solution: Active Directory (<b>AD</b>) and our <b>Custom Windows Service</b>. The Custom Windows Service initiates the transaction and uses the .NET <b>Client OM</b> to write data into the <b>Custom List</b> up in Office 365. This is as far as the data can travel whilst our automated processing is authenticating into Office using a shared service account.<br />
<br />
From here, everything happens in the cloud; let's look at the yellow lines. Whenever any user loads a <b>SharePoint Content Page</b> in the My Site Host site collection, the browser executes some custom JavaScript code in the context of the current user. This code first uses the JavaScript<b> Client OM</b> to query the data from the Custom List that was populated earlier in the process. The JavaScript code then calls the <b>SharePoint Web Service</b> (UserProfleService.asmx) to push the data into the <b>SharePoint User Profile</b>.<br />
<br />
The process of moving data from Office 365 User Profiles into Active Directory is basically the same, but in reverse. For those User Profile Properties that are marked has being able to be read by Everyone, the Custom Windows Service can read the data directly via the UserProfileService.asmx web service and we can short circuit a lot of the process.<br />
<br />
<b>Summary:</b><br />
Using the above approach, we built an automated process that is completely configurable regarding property mappings and synchronisation direction, that works for various data types, across both 2010 and 2013 versions of SharePoint Online. It's admittedly an awkward approach, but it appears to be the only way to achieve the desired outcome with the current limitations in SharePoint Online.<br />
<br />
As a final note, this is a great example of the type of solution that could be achieved using the new SharePoint 2013 Provider Hosted Application model - provided of course that 2010 tenancy support is not required.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-61668806266311098082013-03-03T10:18:00.001+08:002013-03-03T10:18:33.321+08:00Maximum of 10 fields in a Secure Store Target ApplicationThe blog post title pretty much says it all - in all variants of the Secure Store Service Application: both SharePoint 2010 and 2013; on-premises or Office 365; you can't have more than 10 fields in a Target Application.<br />
<br />
This seems a rather arbitrary and constrictive limitation - in the app I was working on we had a total of 11 fields that we wanted to secure so now we will have to create two Target Applications which is an annoying additional overhead.<br />
<br />
Trying to do this through the UI gives an error with "The maximum field number was reached.", here's a screenshot of it in the newly release SharePoint 2013 version of Office 365:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_2S8rh8-JA0trZaHNn6BYtOgxyL0FJ73DzO9wcu41lCwjDmyYwDRBAUh6z4m_AXr3kWinimrq_xaYnX-wl8rV2JltPbOk9zEoIfFeycljgJlCdhiXXojCoviVr0i70bpuRahuGq_LiN8/s1600/SecureStore11Fields.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_2S8rh8-JA0trZaHNn6BYtOgxyL0FJ73DzO9wcu41lCwjDmyYwDRBAUh6z4m_AXr3kWinimrq_xaYnX-wl8rV2JltPbOk9zEoIfFeycljgJlCdhiXXojCoviVr0i70bpuRahuGq_LiN8/s400/SecureStore11Fields.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This error dialog popus once when you hit "Add Field" if you already have 10 fields listed.</td></tr>
</tbody></table>
If you try via PowerShell, then you get this response:<br />
<br />
<br />
<span style="background-color: black; color: red; font-family: Courier New, Courier, monospace;">New-SPSecureStoreApplication : Specified argument was out of the range of valid</span><span style="background-color: black; color: red; font-family: 'Courier New', Courier, monospace;"> values.</span><br />
<span style="background-color: black; color: red; font-family: Courier New, Courier, monospace;">Parameter name: applicationFields</span><br />
<br />
<br />
I couldn't find this limitation documented anywhere other than in <a href="http://office.microsoft.com/en-in/office365-sharepoint-online-enterprise-help/manage-the-secure-store-service-HA102677932.aspx">this Office 365 article</a> - but of course, the limitation is broader than just SharePoint Online.<br />
<br />
It's not a blocking issue because you can always create more Target Applications, but hopefully being aware of this limitation will allow you to plan out your Target Applications without having to figure out why your PowerShell deployment scripts don't seem to behave as expected.<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-30460300127222049492013-02-28T09:41:00.002+08:002013-02-28T09:41:47.801+08:00Perth SharePoint User Group Presentation DeckI'm thrilled to be presenting later today at the Perth SharePoint User Group on <b>Cloud and Hybrid SharePoint Deployments: Enterprise User Profile Management</b>. Here's a download link to the slide deck in case anyone wants to follow up on any of the resources or information presented:<br />
<br />
<a href="http://sdrv.ms/YBbnfE">http://sdrv.ms/YBbnfE</a><br />
<br />
Thanks to the Perth SPUG team for the opportunity to present and to all the attendees!Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-2812910517835628191.post-56249075069549963902013-01-31T11:30:00.000+08:002013-01-31T11:30:23.909+08:00Synchronising Active Directory User Attributes into SharePoint Online User Profile PropertiesPicture an organisation that uses Active Directory for Identity Management, and their AD database contains a range of user properties. That shouldn't require too much imagination...<br />
<br />
Now imagine that, after previously having no real trouble synchronising these properties into SharePoint on-premises User Profiles in the past, they now want to synchronise the properties into Office 365 SharePoint Online User Profiles. It would be natural to assume that once ADFS and DirSync were correctly configured, it would be pretty basic to set up property mappings as needed. Unfortunately, things aren't quite so simple...<br />
<br />
The short story is that only the following properties get synchronised (here I'm ignoring internal reference properties that end users won't care about):<br />
<br />
<table class="table">
<thead>
<tr>
<th>AD Attribute</th>
<th>User Profile Property</th>
</tr>
</thead>
<tbody>
<tr>
<td>givenName</td>
<td>First Name</td>
</tr>
<tr>
<td>sn</td>
<td>Last Name</td>
</tr>
<tr>
<td>displayName</td>
<td>Name</td>
</tr>
<tr>
<td>telephoneNumber</td>
<td>Work Phone</td>
</tr>
<tr>
<td>department</td>
<td>Department</td>
</tr>
<tr>
<td>title</td>
<td>Title</td>
</tr>
<tr>
<td>title</td>
<td>Job Title</td>
</tr>
<tr>
<td>manager</td>
<td>Manager</td>
</tr>
<tr>
<td>wWWHomePage</td>
<td>Public Site Redirect</td>
</tr>
<tr>
<td>proxyAddresses</td>
<td>SIP Address</td>
</tr>
<tr>
<td>mail</td>
<td>Work e-mail</td>
</tr>
<tr>
<td>physicalDeliveryOfficeName</td>
<td>Office</td>
</tr>
</tbody>
</table>
<br />
This is a good start but many organisations will want more (Mobile Number is the first one that comes to mind). Unfortunately, it just isn't possible in the current version of SharePoint Online. You can't add any more properties to be synchronised or even change the mappings for the properties that are already being synchronised. If you try to modify a User Profile Property through the Office 365 Admin UI, the relevant options are presented but not usable:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj23E40QaB_wLDiMWWKeAX43lRPPmN5RxjvP9uSUi-oplejxREgvai1k0DlWHZdig8zKes4ui3CU5hH89e1l66JLjTWe-APNdZjFiZ0C-uRtuy3TADmo0gKg0LGvjGB2Wsv-oEeIT1kmtw/s1600/SPOnlineUserProfileMapping1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="90" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj23E40QaB_wLDiMWWKeAX43lRPPmN5RxjvP9uSUi-oplejxREgvai1k0DlWHZdig8zKes4ui3CU5hH89e1l66JLjTWe-APNdZjFiZ0C-uRtuy3TADmo0gKg0LGvjGB2Wsv-oEeIT1kmtw/s400/SPOnlineUserProfileMapping1.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Here's a property which is already being synchronised through ADFS that I'd like to modify but there are no Source Data Connections or Attributes to select.</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxDg_RWWF7pMEJMVSHFU4CRcC-qvs5PTrz9hS5jrvyqBRjzEAJ6_a2hYUdGVUh7pzLGYkczicxMXdgQ3j52i4ZCppTGyL3ELvyDoXCBmHlDcO1rFqPxcHai-wqaodJU3EmGcflO5-8zlE/s1600/SPOnlineUserProfileMapping2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxDg_RWWF7pMEJMVSHFU4CRcC-qvs5PTrz9hS5jrvyqBRjzEAJ6_a2hYUdGVUh7pzLGYkczicxMXdgQ3j52i4ZCppTGyL3ELvyDoXCBmHlDcO1rFqPxcHai-wqaodJU3EmGcflO5-8zlE/s400/SPOnlineUserProfileMapping2.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Here's the not so helpful dropdown when I click on Source Data Connection. It looks like this UI has been left in SharePoint Online but has no function at this point in time.</td></tr>
</tbody></table>
What is really frustrating is all that text on the left relating to BCS which would be a viable option in SharePoint on-premises (and was suggested to me by multiple people). Unfortunately, this process requires configuring the BCS service application which is not possible in SharePoint Online. <a href="http://community.office365.com/en-us/forums/152/t/50110.aspx">This Community forum post</a> reiterates that the approach is not available for Office 365.<br />
<br />
I've discussed this with a few people within Microsoft and the limitation has been acknowledged although it's not directly documented anywhere.<br />
<br />
One key fact to remember in understanding the cause of this limitation is that the synchronisation is a two step process. First, the properties are synchronised from your on-premises domain up into the Office 365 domain using ADFS and DirSync (I'm no expert on this process and I've probably oversimplified it). This process allows the data to become available to the Exchange and Lync components of Office 365. The properties that are synchronised in this process are listed by Microsoft <a href="http://support.microsoft.com/kb/2256198">here</a>, as far as I am aware this cannot be customised (but I'd welcome it if anyone can correct me here).<br />
<br />
Secondly, the properties are synchronised from the cloud domain into SharePoint Online User Profiles using a synchronisation process which is completely internal and hidden from Office 365 tenancy administrators. The documentation <a href="http://technet.microsoft.com/en-us/library/hh147510.aspx">here</a> shows the default property mappings for this process for SharePoint 2010 which as far as I can tell applies to both on-premises and Office 365 instances of SharePoint. The key difference is that on-premises SharePoint provides a friendly interface for customising these mappings whereas SharePoint Online offers no UI or administrative capacity at all.<br />
<br />
By combining the above documentation it's fairly simple to work out which properties make it all the way from start to finish. If you want more properties then you'll have to put together a completely custom process, but that's a topic for another post...<br />
<br />
Note that all of this discussion is based on the 2010 (Wave 14) version of SharePoint Online, I haven't seen ADFS hooked up to a Wave 15 version yet so I'm not sure whether the situation will improve in the upcoming release of Office 365. I'd love to hear if anyone can shed some light on this!<br />
<br />Unknownnoreply@blogger.com15tag:blogger.com,1999:blog-2812910517835628191.post-75590301808811692512012-07-29T17:50:00.001+08:002015-05-02T20:29:53.472+08:00SharePoint 2013 Explorer<h3>
UPDATE: <a href="http://sharepointrepairjoint.blogspot.com.au/2015/05/sharepoint-explorer-updated-with-latest.html">Newer version of the tool now available here</a>.</h3>
<br />
<br />
Here is one of the first developer utilities specifically built for SharePoint 2013. It will let you peek and poke at the internals of your SharePoint 2013 site collections, either on-premises or in the cloud.<br />
<br />
The tool is based on SharePoint Explorer 365, read <a href="http://sharepointrepairjoint.blogspot.com/2012/05/sharepoint-explorer-365.html">this post</a> for the full details of its origin, capabilities and usage instructions. The changes in this new version are as follows:<br />
<br />
<ul>
<li>Updated passive authentication code for Office 365 Preview as detailed in <a href="http://sharepointrepairjoint.blogspot.com.au/2012/07/how-to-passively-authenticate-into.html">this post</a>.</li>
<li>Compiled against SharePoint 2013 versions of Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll, which provide a range of additional objects, properties and methods compared to the 2010 versions (see below screenshots).<br />Because of this, this version of the tool <b>will not work</b> against SharePoint 2010 site collections.</li>
<li>Compiled against the .NET Framework 4.0, so this needs to be installed if you want to run the tool.</li>
</ul>
<br />
<b><a href="https://docs.google.com/open?id=0BwJLisoPwm6MdHY2cmdWd1R6dVU">Here is the download</a></b>, read my previous post on SharePoint Explorer 365 regarding disclaimers and such.<br />
<br />
You can see the expanded capacity of the 2013 version of the Client Object Model by comparing screenshots of the tool compiled with 2013 assemblies with screenshots of the same tool compiled with the 2010 assemblies.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBkBNcGCErxPCvVbxoG-HlunR3rg6pjmmIw8vcCLQkgX5drJA86bedWNwXofbojGmoDGz6bEyOReXWVoGSbSc4DIPBRkHlENmd6FoEf4TcyDhhsxy6OpyTS4P6oJlcSZFOuiylef_xD1M/s1600/SP13X_1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBkBNcGCErxPCvVbxoG-HlunR3rg6pjmmIw8vcCLQkgX5drJA86bedWNwXofbojGmoDGz6bEyOReXWVoGSbSc4DIPBRkHlENmd6FoEf4TcyDhhsxy6OpyTS4P6oJlcSZFOuiylef_xD1M/s400/SP13X_1.png" height="236" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Site Collection objects and properties in 2010 Client OM assemblies</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2vs2Hl0YeypS8Sa2PQJXzZEaBnFnASTwgtG5Xm4aKL7wBCTaQIUQ0cwH0iqN9mFItv62jpOy0suK43fq4Yk1qpG7C7CsMJukwNePTk0a_5dJuCocL6q76lHH8NCpuhuzh4le3TEzjxpA/s1600/SP13X_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2vs2Hl0YeypS8Sa2PQJXzZEaBnFnASTwgtG5Xm4aKL7wBCTaQIUQ0cwH0iqN9mFItv62jpOy0suK43fq4Yk1qpG7C7CsMJukwNePTk0a_5dJuCocL6q76lHH8NCpuhuzh4le3TEzjxpA/s400/SP13X_2.png" height="330" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Site Collection objects and properties in 2013 Client OM assemblies</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQF8rFVd4MngplvPmDbaMIqHKStPIB_XjbNuP4weiwKnnyRvoPeu5BU1yWnWPBlGVkJhxKjOam1dMkThbfp8kZLhId4LVOFjhmhHtkfhcaEY3UqIFu4sh2Bxsmf7mzbeqOjqIh5Ic0rmg/s1600/SP13X_3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQF8rFVd4MngplvPmDbaMIqHKStPIB_XjbNuP4weiwKnnyRvoPeu5BU1yWnWPBlGVkJhxKjOam1dMkThbfp8kZLhId4LVOFjhmhHtkfhcaEY3UqIFu4sh2Bxsmf7mzbeqOjqIh5Ic0rmg/s400/SP13X_3.png" height="196" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Methods available against the Site Collection in 2010 assemblies</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfhgNlhzoj76iHLG-PZt2zNeC0OYmCQDpHup-gkdmhcgp3L8jPedsdj75Uoq_ZuxxClhSlJixeW8M3nkeGXVViNcrJ4adY8qRpomNfocXyey4irSYK5RnmgxDfZQHJpNtK3HtWWX19krA/s1600/SP13X_4.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfhgNlhzoj76iHLG-PZt2zNeC0OYmCQDpHup-gkdmhcgp3L8jPedsdj75Uoq_ZuxxClhSlJixeW8M3nkeGXVViNcrJ4adY8qRpomNfocXyey4irSYK5RnmgxDfZQHJpNtK3HtWWX19krA/s400/SP13X_4.png" height="260" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Methods available against the Site Collection in 2013 assemblies</td></tr>
</tbody></table>
This expansion of Client OM capabilities in SharePoint 2013 is great news, especially for Office 365 developers. The screenshots above relate to site collections, but there are new capabilities for webs, lists, and other SharePoint objects as well. This tool, or a .NET reflection tool, provides great insights into these new capabilities.<br />
<br />
Note that SharePoint 2013 is in Preview and is liable to change as it matures (this is especially true of the Online version), so the tool may stop working at any time. In the meantime, have fun with it!<br />
<br />
Thanks again to Stefan Stanev for building such an easily extendible SharePoint utility and providing the source code to the SharePoint community!Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-17988220301068159352012-07-29T16:59:00.000+08:002012-07-29T17:00:30.447+08:00How to Passively authenticate into SharePoint 2013 Online using the .NET Client OMIn <a href="http://sharepointrepairjoint.blogspot.com.au/2012/07/sharepoint-online-2013-preview.html">my last post</a> I mentioned that the Passive authentication method for the .NET Client Object Model into SharePoint Online (Office 365) as outlined in <a href="http://code.msdn.microsoft.com/office/Remote-Authentication-in-b7b6f43c">this MSDN code sample</a> is not compatible with SharePoint Online Wave 15 preview.<br />
<br />
It turns out that there is a slight difference in the HTTP responses returned by the Wave 15 version of SharePoint Online compared with the 2010 version. Some of the URLs returned appear in triplicate, separated by commas. Discarding the multiple copies of the URLs brings the code back into working order.<br />
<br />
The MSDN sample code can work in the new version of SharePoint Online, once you edit the ExtraHeadersFromResponse method in the ClaimsWebAuth class like so:<br />
<br />
<pre class="brush: csharp" name="code"> private bool ExtraHeadersFromResponse(WebResponse response, out string loginUrl, out Uri navigationEndUrl)
{
loginUrl = null;
navigationEndUrl = null;
try
{
// For some reason, SharePoint Online Wave 15 Preview seems to return these responses in triplicate, separated by commas
// Let's just get the first one
string returnUrl = response.Headers[Constants.CLAIM_HEADER_RETURN_URL];
if (returnUrl != null && returnUrl.Contains(","))
{
returnUrl = returnUrl.Substring(0, returnUrl.IndexOf(",", StringComparison.InvariantCultureIgnoreCase));
}
navigationEndUrl = new Uri(returnUrl);
loginUrl = (response.Headers[Constants.CLAIM_HEADER_AUTH_REQUIRED]);
if (loginUrl != null && loginUrl.Contains(","))
{
loginUrl = loginUrl.Substring(0, loginUrl.IndexOf(",", StringComparison.InvariantCultureIgnoreCase));
}
return true;
}
catch
{
return false;
}
}
</pre>
Once this change is made, the code works in both the current and the next versions of SharePoint Online.Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-2812910517835628191.post-79545315329674555802012-07-26T22:20:00.001+08:002013-02-28T09:45:05.529+08:00SharePoint Online 2013 Preview: Programmatic Authentication<b>UPDATE</b>: There is a solution to this issue described below, see <a href="http://sharepointrepairjoint.blogspot.com.au/2012/07/how-to-passively-authenticate-into.html">this post</a>.<br />
<br />
As I'm sure you're all aware, SharePoint 2013 Preview (a.k.a. Wave 15)<a href="http://technet.microsoft.com/en-us/library/cc303422(v=office.15).aspx"> is now upon us</a>!<br />
<br />
I thought it would be a great time to confirm programmatic authentication into SharePoint Online, based on the Passive and Active authentication methods we have come to rely upon in the current 2010 based release of SharePoint Online (a component of Office 365).<br />
<br />
The Passive technique requires the user running the code to interactively log in (or to have authenticated within the last 8 hours and still have an unexpired cookie available). This method is outlined <a href="http://code.msdn.microsoft.com/office/Remote-Authentication-in-b7b6f43c">here</a> on MSDN and this was the basis of the <a href="http://sharepointrepairjoint.blogspot.com.au/2012/05/sharepoint-explorer-365.html">SharePoint Online capable version of SharePoint Explorer</a>.<br />
<br />
Unfortunately this authentication method doesn't appear to work against the new version of SharePoint Online from my initial testing. Once the user is authenticated, the WebBrowser window that is created as part of the process looks like this:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzwdDcFWLOxCk7tI9wSviOIR1Y5IVY7xSw7BJpQo9C5gEksE5mtbl_zAsdsW44TUxdjTIQd9-UNntQufeKKt_EHrlp3SUuCu7hAEjadYU1v8a5NkATyzdoO2b8lb7Bf77U4CzBq6SqtIU/s1600/PassiveWave15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzwdDcFWLOxCk7tI9wSviOIR1Y5IVY7xSw7BJpQo9C5gEksE5mtbl_zAsdsW44TUxdjTIQd9-UNntQufeKKt_EHrlp3SUuCu7hAEjadYU1v8a5NkATyzdoO2b8lb7Bf77U4CzBq6SqtIU/s1600/PassiveWave15.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
What is interesting is that clicking the "GO BACK TO SITE" link (what's with the sudden Microsoft Metro obsession with ALL-CAPS?) actually brings up the SharePoint Preview site in the temporary WebBrowser object window. This makes me think that the approach can potentially work with a bit of Fiddling (pun intended)...<br />
<br />
The Active authentication method described <a href="http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspx">here </a>appears to work just fine, thanks Wictor!<br />
<br />
Note that you can create your own Preview tenancy of the upcoming version of SharePoint Online <a href="https://portal.microsoftonline.com/Signup/MainSignUp.aspx?OfferId=OLS-BPO-000240,OLS-BPO-000260&dl=ENTERPRISEPACK&pc=1987ffe0-f4ed-4d79-9703-81283bba135c&ali=1&Country=AU">here</a>. You need to go with an Enterprise tenancy as the other options won't grant you SharePoint Online. Have fun with it!Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-2812910517835628191.post-21536959228656811072012-05-14T15:06:00.000+08:002015-05-02T20:30:41.659+08:00SharePoint Explorer 365<h3>
UPDATE: <a href="http://sharepointrepairjoint.blogspot.com.au/2015/05/sharepoint-explorer-updated-with-latest.html">Newer version of the tool now available here</a>.</h3>
<br />
<br />
Ever wanted to see what is happening under the UI in your SharePoint Online (Office 365) environment? Read on for a download link to a tool that may come in handy...<br />
<br />
I recently came across Stefan Stanev's very useful <a href="http://stefan-stanev-sharepoint-blog.blogspot.com.au/2010/05/sharepoint-2010-explorer-using-client.html">SharePoint Explorer</a>, which is a bit like the <a href="http://spm.codeplex.com/">SharePoint Manager</a> tool that many SharePoint developers would be familiar with. The key difference with SharePoint Explorer is that it uses the .NET Client Object Model to connect to SharePoint, so it can run on any machine with connectivity to your SharePoint environment!<br />
<br />
The Client OM is available in SharePoint Online, but one major difference is the authentication system which I have been playing around with recently for some project work. It's not too difficult to shoe-horn the <a href="http://code.msdn.microsoft.com/office/Remote-Authentication-in-b7b6f43c">MSDN sample code</a> for authenticating into SharePoint Online into the source code for SharePoint Explorer (which Stefan has graciously shared with the SharePoint community). Now we can get a quick and easy view of object properties which are generally hidden from view.<br />
<br />
<b><span style="font-size: large;">Disclaimer:</span></b><br />
This tool is best used for examining the state of SharePoint objects and making quick development changes in non-production environments. As always, <b>be careful</b>! Although it is restricted by the boundaries of the Client OM, this tool has enough power to turn your site collection into a nasty state of affairs (e.g. if you ask it to delete your root web, it will comply and then your site will be completely broken). With this in mind:<br />
<ul>
<li><b>Don't</b> log in with higher privileges than you absolutely need;</li>
<li><b>Don't </b>log in to production if you can avoid it;</li>
<li><b>Don't</b> make any updates (especially in production) if you can avoid it;</li>
<li><b>Don't</b> use it as a short cut for proper deployment methodologies; and</li>
<li><b>Use at your own risk!</b></li>
</ul>
OK, so now you've gotten past the disclaimer, here's the <a href="https://docs.google.com/open?id=0BwJLisoPwm6MbGk4QW1BekFTcnc"><b>download</b> </a>for the Office 365 version of SharePoint Explorer.<br />
<br />
When you connect (see below), there is an option to specify whether you are connecting to a SharePoint Online environment. If you are, the remaining authentication details are ignored and the code provides you with a login screen into Office 365. If the current user has an active cookies from recently logging in to Office 365 in Internet Explorer, then the tool will reuse the cookie so no additional login is required.<br />
<br />
See <a href="http://stefan-stanev-sharepoint-blog.blogspot.com.au/2010/05/sharepoint-2010-explorer-using-client.html">Stefan's blog post entry</a> for detail on how the tool works once you're connected. Massive thanks to him for making the SharePoint Explorer source code available!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8N0-7sawWt2Zwkt7AZs2HfP5sRcT-2HY5d6vjbqXJTH5bGS6l2NzoXtVHjgfo4skIrhXy_Easkl2DwLbXos1S1-SxOId_jsQbwbu8606fb4ev5zZtRYDtvbb4CfS2VRV-a2qC2238okE/s1600/SharePoint+Explorer+365+connect.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8N0-7sawWt2Zwkt7AZs2HfP5sRcT-2HY5d6vjbqXJTH5bGS6l2NzoXtVHjgfo4skIrhXy_Easkl2DwLbXos1S1-SxOId_jsQbwbu8606fb4ev5zZtRYDtvbb4CfS2VRV-a2qC2238okE/s400/SharePoint+Explorer+365+connect.png" height="330" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Specifying to connect to a SharePoint Online site on Office 365</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiesgDsiE9bvplLFrkrqtf7bC5PHRe-d9U8KTX3JJA61_K9OVX3sszdVTtuWVr5Lyd18erIDohwYS6A4VuYyB1nIWN2MGqAJSPNditaE5y8KTXQi-qp11eN6KVfhu6aZPmIeiL9C1fxYxs/s1600/SharePoint+Explorer+365+login.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiesgDsiE9bvplLFrkrqtf7bC5PHRe-d9U8KTX3JJA61_K9OVX3sszdVTtuWVr5Lyd18erIDohwYS6A4VuYyB1nIWN2MGqAJSPNditaE5y8KTXQi-qp11eN6KVfhu6aZPmIeiL9C1fxYxs/s400/SharePoint+Explorer+365+login.png" height="381" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The login form you will use if you don't already have an active cookie available for the tool to reuse</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcII0N1P33oAh7yBsvo9WlvFgUU2p8BRb67N2nZxO3LyBiP3TNpSkvZmLPtvlcblUcYbS8O1m5WTXInQnY90kBnDNCmpzKxfYsq9Hkcc5Z_r-N7_b0I0D5kOqxxO_Qvw6TXWnd5L86fIE/s1600/SharePoint+Explorer+365+action.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcII0N1P33oAh7yBsvo9WlvFgUU2p8BRb67N2nZxO3LyBiP3TNpSkvZmLPtvlcblUcYbS8O1m5WTXInQnY90kBnDNCmpzKxfYsq9Hkcc5Z_r-N7_b0I0D5kOqxxO_Qvw6TXWnd5L86fIE/s400/SharePoint+Explorer+365+action.png" height="352" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The tool in action</td></tr>
</tbody></table>
<br />
Let me know how you go with the tool, I've found it quite handy to track down and delete orphaned hidden Taxonomy columns created by SharePoint whilst testing my content type provisioning feature. Much faster than having to write sandbox code or custom Client OM code!Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-2812910517835628191.post-21345504064738826142012-04-21T00:25:00.000+08:002012-04-21T00:25:39.207+08:00SharePoint Saturday Perth - Customising SharePoint Online ResourcesHi all,<br />
<br />
Here are the resources referenced in my SharePoint Saturday Perth presentation on Customising SharePoint Online:<br />
<br />
SharePoint Online Restrictions:<br />
<a href="http://msdn.microsoft.com/en-us/library/gg615454.aspx">http://msdn.microsoft.com/en-us/library/gg615454.aspx</a><br /><br />
Sandbox Logging:<br />
<a href="http://spsl.codeplex.com%20/">http://spsl.codeplex.com </a><br />
<br />
<div>
Client Object Model Authentication:</div>
<div>
<div>
<a href="http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspx">http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspx</a></div>
</div>
<div>
<br /></div>
<div>
<div>
Free 30-day trial Office 365 tenancy:</div>
<div>
<a href="http://www.microsoft.com/en-us/office365/free-office365-trial.aspx">http://www.microsoft.com/en-us/office365/free-office365-trial.aspx</a></div>
<div>
<br /></div>
<div>
Office 365 Service Descriptions:</div>
<div>
<a href="http://www.microsoft.com/download/en/details.aspx?id=13602">http://www.microsoft.com/download/en/details.aspx?id=13602</a></div>
<div>
<br /></div>
<div>
Office 365 Developer Training Course :</div>
<div>
<a href="http://msdn.microsoft.com/en-us/hh181605">http://msdn.microsoft.com/en-us/hh181605</a></div>
<div>
<br /></div>
<div>
SharePoint Online Developer Resource Centre :</div>
<div>
<a href="http://msdn.microsoft.com/en-us/sharepoint/gg153540.aspx">http://msdn.microsoft.com/en-us/sharepoint/gg153540.aspx</a></div>
</div>
<div>
<br /></div>
<div>
Thanks to Brian and all the SharePoint Saturday Perth sponsors, presenters and attendees!</div>
<div>
<br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2812910517835628191.post-66321176961610178132012-03-22T22:15:00.001+08:002012-03-29T12:17:59.390+08:00Feature Stapling in SharePoint Online (Office 365)I've been working with sandbox solutions lately and I've come across something rather unexpected: it looks like you can't use feature stapling (the FeatureSiteTemplateAssociation element) in the cloud.<br />
<br />
I created a sandbox version of the branding solution I've used a few times in the past to apply a custom master page and some custom CSS to a site. The sandbox version of the solution contains a site collection scoped feature that staples a web scoped feature to a wide range of SharePoint site definitions. This works as expected in my on-premises development environment: when the site collection feature is active, newly created sites have the custom web feature already activated.<br />
<br />
However, when I apply the exact same sandbox solution to my SharePoint Online tenancy, the feature stapling doesn't seem to apply. Everything else works except for the stapling. The only information I have been able to find is <a href="http://community.office365.com/en-us/f/153/p/16460/76379.aspx">this link</a> on the Office 365 community site where a Microsoft support team member seems to indicate that feature stapling isn't available in SharePoint Online.<br />
<br />
So it seems that for now we'll need to find alternative ways to automatically customise newly created SharePoint Online sites. I'm interested to hear if anyone else has any more info on this or perhaps has found a way to get feature stapling working in Office 365.<br />
<br />
<b>Update:</b><br />
I've just checked the site definition being used for my SharePoint Online site - I had a suspicion that perhaps Online uses slightly different site definitions because this would explain why the feature stapling wasn't being applied. However, the WebTemplate and WebTemplateId properties are both identical in my SharePoint Online site and my on-premises site. So this doesn't explain the difference in behaviour between the two environments.<br />
<br />
I've also tried using the GLOBAL value for TemplateName which should staple to all site definitions (except where the <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spwebtemplate.allowglobalfeatureassociations.aspx">AllowGlobalFeatureAssociations </a>property is false), and I still don't see any feature stapling.Unknownnoreply@blogger.com2