Powershell Script to move documents between sitecollections with version history

##see https://shannonbray.wordpress.com/2010/06/26/moving-sharepoint-2007-sites-to-another-environment-with-powershell/

Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue

[void][System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint.Deployment”)

$fileName = “exportedWeb.cmp”

$fileLocation = “c:export”

$SourceSiteURL = http://edmsqa.kznsands.local/sites/CP”

$docid=“CPDOC-46-30”

$DestinationSiteURL = http://edmsqa.kznsands.local/sites/cpccold/”

$DestinationWebName = “MPPProd” # need to add logic to use rootweb if this is null

$DestinationLibraryName=‘Documents’

##############################################The Export Script

$SourceSite = get-spsite $SourceSiteURL

$provider = [Microsoft.Office.DocumentManagement.DocumentId]::GetProvider($SourceSite)

$result = $provider.GetDocumentUrlsById($SourceSite, $docid)

$sourceWeb = $SourceSite.RootWeb

$file = $sourceWeb.GetFile($result[0])

$item=$file.Item

# Create a new SPExportObject

$exportObject = new-object Microsoft.SharePoint.Deployment.SPExportObject

# Populate the SPExportObject properties

$exportObject.Id = $item.UniqueId;

#$exportObject.IncludeDescendants = [Microsoft.SharePoint.Deployment.SPIncludeDescendants]::All

$exportObject.Type = [Microsoft.SharePoint.Deployment.SPDeploymentObjectType]::File

# Create a new object that holds all of the settings

$settings = new-object Microsoft.SharePoint.Deployment.SPExportSettings

$settings.SiteUrl = $SourceSiteURL

$settings.ExportMethod = [Microsoft.SharePoint.Deployment.SPExportMethodType]::ExportAll

$settings.FileLocation = $fileLocation

$settings.FileCompression = $false

$settings.BaseFileName = $fileName

$settings.ExcludeDependencies = $false

$settings.ExportObjects.Add($exportObject)

$settings.OverwriteExistingDataFile = $true

$settings.IncludeVersions = [Microsoft.SharePoint.Deployment.SPIncludeVersions]::All

# Create a new SPExport object based off the the settings of the SPExportSettings object

$export = new-object Microsoft.SharePoint.Deployment.SPExport($settings)

# Start the export

$export.Run()

# Dispose of the site object to release it from memory

$site.Dispose

#######################################################IMPORT

# Create a new object that holds all of the settings

$settings = new-object Microsoft.SharePoint.Deployment.SPImportSettings

$settings.SiteUrl = $DestinationSiteURL

$settings.FileLocation = $fileLocation

$settings.FileCompression = $false

$settings.RetainObjectIdentity = $false

$settings.UserInfoDateTime = [Microsoft.SharePoint.Deployment.SPImportUserInfoDateTimeOption]::ImportAll

$settings.BaseFileName = $fileName

$settings.CommandLineVerbose=$true

$import = new-object Microsoft.SharePoint.Deployment.SPImport($settings)

$destinationSite = Get-SPSite $destinationSiteURL

$destinationWeb=$destinationSite.OpenWeb($DestinationWebName)

$destinationList= $destinationWeb.Lists[$DestinationLibraryName]

$import.add_Started({ # change the ParentUrl to the root folder of the Targhet LIst

param($Source, $EventArgs)

$rootObject = $EventArgs.RootObjects

ForEach ($importObject in $rootObject) {

if ($importObject.Type -eq [Microsoft.SharePoint.Deployment.SPDeploymentObjectType]::File -or $importObject.Type -eq [Microsoft.SharePoint.Deployment.SPDeploymentObjectType]::ListItem) {

$importObject.TargetParentUrl = $destinationList.RootFolder.ServerRelativeUrl

}

}

})

$import.Run()

 

Posted in Uncategorized | Leave a comment

An AngularJS directive for SharePoint Lookup Columns

Recently I’ve been researching how I can use AngularJS in my SharePoint 2010 environment. Specifically I’ve been working on using the Angular UI-Grid to edit SharePoint lists. I was able to edit most of the columns of  a standard Task list without too much effort, but the ‘Predecessors’ column which is a Lookup column that allows multiple selections was troublesome. I ended up needing to create an AngularJS directive that allows me to work with SharePoint lookup columns (which I am documenting here).  Having gone through that exercise, I’m now envisioning directives to work with all the different column types(sp-lookup, spdate,sp-choice…), directives that display SharePoint views and forms(sp-view,spform,sp-nav), etc.  These directives could even be driven off of the site metadata.

The file spLookup.js defines a module that contains my ‘spLookup directive and a supportingspFieldsDataService Service (spLookup.js can be downloaded from my onedrive here).

The directive is designed to render a Lookup column from a list that was retrieved by calling listdata.svc. If the lookup is a multi-select, you must expand the lookup column when you make your original rest call  to listdata.svc (otherwise the spLookup directive would need to go get the values of the lookup column for each row rendered).It does not work with CSOM. I haven’t tested yet using the SharePoint 2013 _Api endpoint, but it should work.

Here’s how it’s used:

<sp-lookup

controlMode=”edit|new|display”

ng-model=”FieldInTheScope”

multiple

lookupListUrl=”urlOfLookupList”

lookupField=”ColumnToDisplayInTheUI”

modelField=”TheIDColumn”

loadAll=”true”>

</sp-lookup>

The controlMode attribute states whether the control should display in edit, new, or display mode, like it does on the server side. In display mode, the control will just display the values(s) of the lookupField. In edit or new mode the control will display a select control.

The ng-Model attribute names a field on the scope to bind to.

The multiple attribute, if present, allows the user to select multiple values.

The lookupListUrl attribute is the url of the list that is used to display the select box (I also need to add an alternative attribute ‘lookupList’ which could be used if you already have the lookup list in your model, or maybe you want to narrow down the selections).

The lookupField attribute is the name of the field to display in the select control.

The modelField attribute is the name of the field to store in the model for item(s) that are selected. (I should probably just default this to ‘Id’)

The loadAll attribute states whether the sp-lookup control should load all values from the lookupListUrl when it is initialized. If you have no intention of editing any list items, and therefor will not need to render a select control, you can set this to false (I should probably just default this to true!).

To see the control in action create a standard Task list on one of your sites, and add a few tasks to it. Be sure to add a few Predecessors and an Assigned To to each task .In Sharepoint OnLine/Sharepoint 2013  you may need to click the Show more link at the botom of the  form to see the Predecessors column. Also In Sharepoint OnLine/Sharepoint 2013  change the Assigned To column to not Allow multiple selections for this demo.

Upload spLookup.js, spLookupDemo.js,  and spLookupDemo.html into your Site Assets library from here. Also Download angular.js and add it to your Site Assets Library.

For SharePoint 2010:

Create a web-part page to use to test the control. (Site Actions–>More Options–>Page–>Web Part Page )

Add the following scripts to the ContentPlaceholderAdditionalPageHead:

<script type=’text/javascript’ src=’/SiteAssets/angular-1.2.23/angular.js’></script>

<script  src=”/SiteAssets/splookup.js” type=”text/javascript”></script>

<script  src=”/SiteAssets/splookupdemo.js” type=”text/javascript”></script>

You’ll need to adjust the urls based on your environment.

And replace the contents of the ContentPlaceholderMain with this:

<div data-ng-app=”app1″ data-ng-controller=”spLookupDemoCtrl”>

<select size=”5″  ng-options=”Task as Task.Title for Task in tasks”  data-ng-model=”selectedTask”>  </select>

<div ng-show=”selectedTask”>

<table>

<caption>{{selectedTask.Title}}</caption>

<tr>

<td>Predecessors (multi-select) with controlMode display:</td>

<td>

<div data-sp-lookup controlMode=”display” ng-model=”selectedTask.Predecessors.results” multiplelookupListUrl=”../../_vti_bin/listdata.svc/Tasks”

lookupField=”Title” modelField=”Id” loadAll=”true”/>

</td>

.

</tr>

<tr>

<td>Predecessors (multi-select) with controlMode edit:</td>

<td>

<div data-sp-lookup controlMode=”edit” ng-model=”selectedTask.Predecessors.results” multiplelookupListUrl=”../../_vti_bin/listdata.svc/Tasks”

lookupField=”Title” modelField=”Id” loadAll=”true”/>

</td>

</tr>

<tr>

<td>Assigned To (single-select) with controlMode display:</td>

<td>

<div data-sp-lookup controlMode=”display” ng-model=”selectedTask.AssignedToId”lookupListUrl=”../../_vti_bin/listdata.svc/UserInformationList”

lookupField=”Name” modelField=”Id” loadAll=”true”/>

</td>

</tr>

<tr>

<td>Assigned To (single-select) with controlMode edit:</td>

<td>

<div data-sp-lookup controlMode=”edit” ng-model=”selectedTask.AssignedToId” lookupListUrl=”../../_vti_bin/listdata.svc/UserInformationList”

lookupField=”Name” modelField=”Id” loadAll=”true”/>

</td>

</tr>

</table>

<a href=”” ng-click=”saveTask()”>save</a>

</div>

</div>

This html can be copied from the spLookupDemo.html file in the download directory above.

For  Office 365:

Click the Site Actions Gear in the upper right and select Add a Page. Edit the Page, the click the Insert tab, and select ‘Embed Code’

Add the following:

<script src=’../SiteAssets/angular.js’ type=’text/javascript’></script>
<script src=’../SiteAssets/splookup.js’ type=’text/javascript’></script>
<script src=’../SiteAssets/splookupDemo.js’ type=’text/javascript’></script>

Then,  add a Content Editor webpart and point it to ‘SiteAssets/splookupDemo.html’

If all works well, the results will be a sample page demonstrating the use of this directive with both Single and Multi-select columns in both Edit and display mode:

Sosplookupdemo

Some features I need to add to this are pulling templates from the templateCache and allowing them to be overridden,  a lot of error checking, and the ability to handle lookups with fill-in choices.

Posted in Uncategorized | Tagged , , , , , | 4 Comments

AngularJS displaying ng-grid group information inside the grid as in a treeGrid

I had a need to group information in an ng-grid by more than one column (cname, maturity, Buy/Sell and Price), and to display summary data for each group within the grid(not in the ‘label’ format that ng-grid normally uses for aggregate information).

The data coming from my back-end (after my transformResponse) was an array of items that looked like this:

{
“identid”: “100001”,
“cname”: “BA”,

“maturity”: “2014-11-05T05:00:00Z”,

“bs”: “B”,

“price”: “121.19”,

“lots”: 1,

“buylots”: 1,

“selllots”: 0

}

So, in order to aggregate by those multiple fields, i first needed to create a computed field to group by , and then sort the array by that field(in this case using underscore):

_.each(tradelist, function(trade) {
trade.groupCol = trade.cname + trade.maturity + trade.bs + trade.price;
});

$scope.griddata =_.sortBy(tradelist, function(row) {
return row.groupCol;
});

Then I set my gridoptions to group by the newly created groupCol, but not show it:

    $scope
data: griddata
showFilter: false,
width: ‘572px’,
showGroupPanel: false,
groups: [‘groupCol’],
enableRowSelection: true,
multiSelect: false,
showSelectionCheckbox: true,
columnDefs: [
{ field: ‘groupCol’, visible: false },
{ field: ‘cname’, displayName: ‘Contract’, width: ‘150px’ },
{ field: ‘maturity’, displayName: ‘Maturity’, width: ‘112px’, cellFilter: ‘date:\’dd-MMM-yy\” },
{ field: ‘bs’, displayName: ‘B/S’, width: ’50px’ },
{ field: ‘price’, displayName: ‘Price’, width: ‘100px’ },
{ field: ‘identid’, displayName: ‘Trades’, width: ‘100px’ },
{ field: ‘lots’, displayName: ‘Lots’, width: ’60px’ }
]

};

Now the grid was grouping by my combined column, but was displaying the aggregate info in the standard ng-grid format( just a <span> tahg) , not in the grid. What I needed was to display the group information within  the grid, displaying the total of all Lots in the Lots columns and a count of the trades in the trade column.

I first created the function to aggregate the Lots:

$scope.aggregateLots = function(row) {

var lots = 0;

angular.forEach(row.children, function(subrow) {

lots += subrow.entity.lots;

});

return lots;

}

Then I changed the gridOptions.aggregateTemplate to display the data from the first row for each of the grouped columns, and summary data for the Lots and Trade columns:

$scope.gridOptions.aggregateTemplate:
“<div ng-click=\”debugger;customExpand(row,gridId)\” ng-style=\”rowStyle(row)\” class=\”ngAggregate\”>\r” +

“\n” +
“<div class=’ngCell col3 col3t’><div class=’ngCellText col3 col3t’>{{row.children[0].entity.cname}}</div></div>\r\n” +

“<div class=’ngCell col4 col4t’><div class=’ngCellText col4 col4t’>{{row.children[0].entity.maturity | date:\’dd-MMM-yy\’ }}</div></div>\r\n” +

“<div class=’ngCell col5 col5t’><div class=’ngCellText col5 col5t’>{{row.children[0].entity.bs}}</div></div>\r\n” +

“<div class=’ngCell col6 col6t’><div class=’ngCellText col6 col6t’>{{row.children[0].entity.price}}</div></div>\r\n” +

“<div class=’ngCell col7 col7t’><div class=’ngCellText col7 col7t’>{{row.totalChildren()}}</div></div>\r\n” +

“<div class=’ngCell col8 col8t’><div class=’ngCellText col8 col8t’>{{aggregateLots(row)}}</div></div>\r\n” +

“\n” +

“<div class=\”{{row.aggClass()}}\”></div>\r” +
“\n” +
“</div>\r” +
“\n”;

The aggregateTemplate  displays the summary data using the same classes as the detailed rows so that the summary data appears as if it were in the grid:

ng-gridSummarized

A working version with complete code can be found at http://plnkr.co/edit/FQepdgFKtYqAVilvEwXZ?p=preview

Posted in angular, ng-grid | Tagged , , , , , , , | 1 Comment

Making Angular ng-grid expand only one group

I had an ng-grid set up with a single ‘group’ column set in the gridOptions. I needed to make it so that only a single group is expanded at any time (i.e. when a user clicked to expand a group,the other groups got automatically collapsed) and that the expanded group was automatically scrolled to the Top of the view.

I created a custom aggregateTemplate in my gridoptions and changed the ng-click to call a custom function to collapse all the other groups before expanding the one just clicked:

$scope.gridOptions = {

aggregateTemplate: “<div ng-click=”customExpand(row)” ng-style=”{‘left’: row.offsetleft}” class=”ngAggregate”><span class=”ngAggregateText”>{{row.label CUSTOM_FILTERS}} ({{row.totalChildren()}} {{AggItemsLabel}})</span><div class=”{{row.aggClass()}}”></div></div>”,
showGroupPanel: false,
groups: [‘groupCol’],….

The customExpand function looks like this:

$scope.customExpand = function (row) {
// first collapse all others
angular.forEach($scope.gridOptions.ngGrid.rowFactory.aggCache, function (aggRow, key) {
if (aggRow.isAggRow && aggRow.collapsed == false) {
aggRow.toggleExpand();
}
});
// then scroll to row for this group
var rowNum = 0;
angular.forEach($scope.gridOptions.ngGrid.rowFactory.aggCache, function (aggRow, key) {
if (aggRow.label == row.label) {
rowNum = key;
}
});
$scope.gridOptions.ngGrid.$viewport.scrollTop(rowNum * $scope.gridOptions.ngGrid.config.rowHeight);
// then expand the row
row.toggleExpand();
}

Now, only a single group is expanded at one time. and the expanded group scrolls to the top of the view.

Posted in angular, ng-grid | Tagged , , | Leave a comment

Rendering JSON from an XSLTListViewWebPart

I recently built a site on SharePoint 2010 that used lots of JavaScript for custom form validations.  The JavaScript made ajax calls back to listdata.svc to get the data to perform the validations. Things worked fine locally, but when a user from the other side of the globe accessed the site, things were slow.  A quick test using Fiddler’s ‘TimeLine’ tab showed me that after the initial page load, seconds were being spent making  multiple  ajax calls to get the validation data.

My first thought was to switch from rest to csom so that I could batch all the requests together and get the validation data in a single call. But then I began to think ‘Why not just send it down with the initial page?’ I thought about writing a custom webpart that could get data from an SPDataSource and serialize it to JSON and write it to the output stream.

Then it occurred to me that this could probably be done using an XSLTListViewWebPart and some custom XSL.  I found several pages that discussed serializing XML to JSON (Most notably http://controlfreak.net/xml-to-json-in-xslt-a-toolkit/ ).  Tweaking one of the samples in that article gave me the following XSLT which renders an XSLTListViewWebPart’s data into the browser:

<xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform&#8221;
version=”1.0″ xmlns:ddwrt2=”urn:frontpage:internal”>
<xsl:param name=”webpartTitle”></xsl:param><!– need to add parameter binding <ParameterBinding Name=”webpartTitle” Location=”WPProperty(Title)” /> –>
<!– Turn off auto-insertion of <?xml> tag and set indenting on –>
<xsl:output method=”text” encoding=”utf-8″ indent=”yes”/>

<!– strip whitespace from whitespace-only nodes –>
<!–CAUSES ERROR Error while executing web part: System.Xml.Xsl.XslTransformException: White space cannot be stripped from input documents that have already been loaded. Provide the input document as an XmlReader instead. –>
<!– <xsl:strip-space elements=”*”/> –>

<xsl:template match=”/dsQueryResponse”>
<xsl:value-of select=”$webpartTitle” />
<xsl:text>&lt;script type=&quot;text/javascript&quot; &gt; debugger;</xsl:text>
<xsl:value-of select=”$webpartTitle” />
<xsl:text>=</xsl:text>

<xsl:apply-templates></xsl:apply-templates>
<xsl:text>&lt;/script&gt;</xsl:text>
</xsl:template>

<!– handles elements –>
<xsl:template match=”*”>
<!– element name –>
<xsl:text>{ &quot;e&quot; : &quot;</xsl:text>
<xsl:value-of select=”name()”/>
<xsl:text>&quot;</xsl:text>
<xsl:variable name=”ctr” select=”count(*)”/>
<xsl:variable name=”actr” select=”count(@*)”/>
<xsl:variable name=”tctr” select=”count(text())”/>
<!– there will be contents so start an object –>
<xsl:if test=”$actr > 0″>
<xsl:text>, &quot;values&quot; : { </xsl:text>
<xsl:apply-templates select=”@*”/>
<xsl:text>}</xsl:text>
</xsl:if>
<!– handle element nodes –>
<xsl:choose>
<xsl:when test=”$ctr = 1″>
<xsl:text>, &quot;data&quot; : </xsl:text>
<xsl:apply-templates select=”*”/>
</xsl:when>
<xsl:when test=”$ctr > 1″>
<xsl:text>, &quot;rows&quot; : [ </xsl:text>
<xsl:apply-templates select=”*”/>
<xsl:text> ]</xsl:text>
</xsl:when>
</xsl:choose>
<!– handle text nodes –>
<xsl:choose>
<xsl:when test=”$tctr = 1″>
<xsl:text>, &quot;$&quot; : </xsl:text>
<xsl:apply-templates select=”text()” />
</xsl:when>
<xsl:when test=”$tctr > 1″>
<xsl:text>, &quot;$&quot; : [ </xsl:text>
<xsl:apply-templates select=”text()” />
<xsl:text> ]</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:text> }</xsl:text>
<xsl:if test=”position() != last()”>
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>

<!– this template handle text nodes –>
<xsl:template match=”text()”>
<xsl:variable name=”t” select=”.” />
<xsl:choose>
<!– test to see if it is a number –>
<xsl:when test=”string(number($t)) != ‘NaN'”>
<xsl:value-of select=”$t”/>
</xsl:when>
<!– deal with any case booleans –>
<xsl:when test=”translate($t, ‘TRUE’, ‘true’) = ‘true'”>
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:when test=”translate($t, ‘FALSE’, ‘false’) = ‘false'”>
<xsl:text>false</xsl:text>
</xsl:when>
<!– must be text –>
<xsl:otherwise>
<xsl:text>&quot;</xsl:text>
<xsl:value-of select=”$t”/>
<xsl:text>&quot;</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test=”position() != last()”>
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>

<!– this template handles attribute nodes –>
<xsl:template match=”@*”>
<!– attach prefix to attribute names –>
<xsl:text>&quot;</xsl:text>
<xsl:value-of select=”name()”/>
<xsl:text>&quot; : </xsl:text>
<xsl:variable name=”t” select=”.” />
<xsl:choose>
<xsl:when test=”string(number($t)) != ‘NaN'”>
<xsl:value-of select=”$t”/>
</xsl:when>
<xsl:when test=”translate($t, ‘TRUE’, ‘true’) = ‘true'”>
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:when test=”translate($t, ‘FALSE’, ‘false’) = ‘false'”>
<xsl:text>false</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>&quot;</xsl:text>
<xsl:value-of select=”$t”/>
<xsl:text>&quot;</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test=”position() != last()”>
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

The XSLT creates a JavaScript global variable with the same name as the webpart and writes the json data into that variable. Note that I needed to add an additional Parameter Binding:

<ParameterBinding Name=”webpartTitle” Location=”WPProperty(Title)” />

to the webpart so that the JavaScript variable could be named the same thing as the Webpart Title.  Also note that after the webpart is added to the page the ‘Enable Asynchronous Load’ option must be turned off, otherwise the JSON object will be written into an IFrame, and not easily accessible by the scripts on the main page.

Now I can just place these modified XSLTListViewWebParts on my forms page and the validation data I was previously retrieving via ajax calls is delivered with the initial page load and can be accessed using my custom JavaScript. No more ajax callbacks!

As an added benefit I can now filter the data send to the browser by editing the XSLTListViewWebParts, adding/removing columns, setting filter criteria etc.

Other possible uses of this technique could be to create views completely in JavaScript or the XSLT could easily be modified to write out Knockout observables. Also, if you Group the data in the Webpart, group data is even written to the JSON so you could render the groups on the client!

Below is the full source code for a webpart that serializes its data to JSON (Note that you should probably store the XSL in a library rather than inline)

<WebPartPages:XsltListViewWebPart runat=”server” Description=”mapping for contracts” PartOrder=”2″ HelpLink=”” AllowRemove=”True” IsVisible=”True” AllowHide=”True” UseSQLDataSourcePaging=”True” ExportControlledProperties=”False” IsIncludedFilter=”” DataSourceID=”” Title=”MAP_Contracts” ViewFlag=”8388613″ AllowConnect=”True” DisplayName=”JSON” FrameState=”Normal” PageSize=”-1″ PartImageLarge=”” AsyncRefresh=”False” ExportMode=”NonSensitiveData” Dir=”Default” DetailLink=”/sites/testing/sitenamehere/Lists/MAP_Contracts” ShowWithSampleData=”False” ListId=”7f481096-9449-48bd-b02d-e3b8dc62ef95″ ListName=”{7F481096-9449-48BD-B02D-E3B8DC62EF95}” FrameType=”Default” PartImageSmall=”” IsIncluded=”True” SuppressWebPartChrome=”False” AllowEdit=”True” ViewGuid=”{A3EE0A01-B7EB-407E-9FC3-4572CB34B207}” AutoRefresh=”False” AutoRefreshInterval=”60″ AllowMinimize=”True” WebId=”00000000-0000-0000-0000-000000000000″ ViewContentTypeId=”0x” InitialAsyncDataFetch=”False” GhostedXslLink=”main.xsl” MissingAssembly=”Cannot import this Web Part.” HelpMode=”Modeless” ID=”g_a3ee0a01_b7eb_407e_9fc3_4572cb34b207″ ConnectionID=”00000000-0000-0000-0000-000000000000″ AllowZoneChange=”True” TitleUrl=”/sites/testing/sitenamehere/Lists/MAP_Contracts” ManualRefresh=”False” __MarkupType=”vsattributemarkup” __WebPartId=”{A3EE0A01-B7EB-407E-9FC3-4572CB34B207}” __AllowXSLTEditing=”true” __designer:CustomXsl=”fldtypes_Ratings.xsl” WebPart=”true” Height=”” Width=””><ParameterBindings>
<ParameterBinding Name=”webpartTitle” Location=”WPProperty(Title)” />
<ParameterBinding Name=”dvt_sortdir” Location=”Postback;Connection” />
<ParameterBinding Name=”dvt_sortfield” Location=”Postback;Connection” />
<ParameterBinding Name=”dvt_startposition” Location=”Postback” DefaultValue=”” />
<ParameterBinding Name=”dvt_firstrow” Location=”Postback;Connection” />
<ParameterBinding Name=”OpenMenuKeyAccessible” Location=”Resource(wss,OpenMenuKeyAccessible)” />
<ParameterBinding Name=”open_menu” Location=”Resource(wss,open_menu)” />
<ParameterBinding Name=”select_deselect_all” Location=”Resource(wss,select_deselect_all)” />
<ParameterBinding Name=”idPresEnabled” Location=”Resource(wss,idPresEnabled)” />
<ParameterBinding Name=”NoAnnouncements” Location=”Resource(wss,noXinviewofY_LIST)” />
<ParameterBinding Name=”NoAnnouncementsHowTo” Location=”Resource(wss,noXinviewofY_DEFAULT)” />
</ParameterBindings>
<XmlDefinition>
<View Name=”{A3EE0A01-B7EB-407E-9FC3-4572CB34B207}” MobileView=”TRUE” Type=”HTML” DisplayName=”JSON” Url=”/sites/testing/GeraldFixPortal/Lists/MAP_Contracts/JSON.aspx” Level=”1″ BaseViewID=”1″ ContentTypeID=”0x” ImageUrl=”/_layouts/images/generic.png”>
<Method Name=”Read List”/>
<Query>
<GroupBy Collapse=”TRUE” GroupLimit=”30″>
<FieldRef Name=”Exchange”/>
</GroupBy>
<Where>
<Eq>
<FieldRef Name=”Category”/>
<Value Type=”Text”>CME_Futures</Value>
</Eq>
</Where>
</Query>
<ViewFields>
<FieldRef Name=”ID”/>
<FieldRef Name=”Category”/>
<FieldRef Name=”Cname”/>
</ViewFields>
<RowLimit Paged=”TRUE”>2000000</RowLimit>
<Aggregations Value=”Off”/>
<Toolbar Type=”Standard”/>
</View>
</XmlDefinition>
<DataFields>
</DataFields>
<Xsl>
<xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform&#8221;
version=”1.0″ xmlns:ddwrt2=”urn:frontpage:internal”>
<xsl:param name=”webpartTitle”></xsl:param><!– need to add parameter binding <ParameterBinding Name=”webpartTitle” Location=”WPProperty(Title)” /> –>
<!– Turn off auto-insertion of <?xml> tag and set indenting on –>
<xsl:output method=”text” encoding=”utf-8″ indent=”yes”/>

<!– strip whitespace from whitespace-only nodes –>
<!–CAUSES ERROR Error while executing web part: System.Xml.Xsl.XslTransformException: White space cannot be stripped from input documents that have already been loaded. Provide the input document as an XmlReader instead. –>
<!– <xsl:strip-space elements=”*”/> –>

<xsl:template match=”/dsQueryResponse”>

<xsl:text>&lt;script type=&quot;text/javascript&quot; &gt; debugger;</xsl:text>
<xsl:value-of select=”$webpartTitle” />
<xsl:text>=</xsl:text>

<xsl:apply-templates></xsl:apply-templates>
<xsl:text>&lt;/script&gt;</xsl:text>
</xsl:template>

<!– handles elements –>
<xsl:template match=”*”>
<!– element name –>
<xsl:text>{ &quot;e&quot; : &quot;</xsl:text>
<xsl:value-of select=”name()”/>
<xsl:text>&quot;</xsl:text>
<xsl:variable name=”ctr” select=”count(*)”/>
<xsl:variable name=”actr” select=”count(@*)”/>
<xsl:variable name=”tctr” select=”count(text())”/>
<!– there will be contents so start an object –>
<xsl:if test=”$actr > 0″>
<xsl:text>, &quot;values&quot; : { </xsl:text>
<xsl:apply-templates select=”@*”/>
<xsl:text>}</xsl:text>
</xsl:if>
<!– handle element nodes –>
<xsl:choose>
<xsl:when test=”$ctr > 1″>
<xsl:text>, &quot;rows&quot; : [ </xsl:text>
<xsl:apply-templates select=”*”/>
<xsl:text> ]</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:text> }</xsl:text>
<xsl:if test=”position() != last()”>
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>

<!– this template handle text nodes –>
<xsl:template match=”text()”>
<xsl:variable name=”t” select=”.” />
<xsl:choose>
<!– test to see if it is a number –>
<xsl:when test=”string(number($t)) != ‘NaN'”>
<xsl:value-of select=”$t”/>
</xsl:when>
<!– deal with any case booleans –>
<xsl:when test=”translate($t, ‘TRUE’, ‘true’) = ‘true'”>
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:when test=”translate($t, ‘FALSE’, ‘false’) = ‘false'”>
<xsl:text>false</xsl:text>
</xsl:when>
<!– must be text –>
<xsl:otherwise>
<xsl:text>&quot;</xsl:text>
<xsl:value-of select=”$t”/>
<xsl:text>&quot;</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test=”position() != last()”>
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>

<!– this template handles attribute nodes –>
<xsl:template match=”@*”>
<!– attach prefix to attribute names –>
<xsl:text>&quot;</xsl:text>
<xsl:value-of select=”name()”/>
<xsl:text>&quot; : </xsl:text>
<xsl:variable name=”t” select=”.” />
<xsl:choose>
<xsl:when test=”string(number($t)) != ‘NaN'”>
<xsl:value-of select=”$t”/>
</xsl:when>
<xsl:when test=”translate($t, ‘TRUE’, ‘true’) = ‘true'”>
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:when test=”translate($t, ‘FALSE’, ‘false’) = ‘false'”>
<xsl:text>false</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>&quot;</xsl:text>
<xsl:value-of select=”$t”/>
<xsl:text>&quot;</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test=”position() != last()”>
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>

</xsl:stylesheet></Xsl>
</WebPartPages:XsltListViewWebPart>

The Image below shows a sample JSON object called MAP_Contracts that was generated using this XSLT. Note that the generated object has an array called rows that contains field called values that contains the data. In this example I have grouped the view on Exchange so the fields Exchange.COUNT.group, Exchange.groupindex, Exchange.newGroup and exchange.urlencoded were added by the webpart and could be used to do grouping on the client side.

jaonvariable

Posted in ajax, javascript, sharepoint | Leave a comment

Automatically retry jquery ajax calls to listdata.svc after HTTP 500 Errors

I had an issue with a SharePoint page that was making  jQuery ajax calls to get the valid values of a Choice Column on a list. It worked fine  usually but once in a while the ajax calls would return an HTTP 500 Internal Server Error, and the user would see this:

error500

This was usually first thing in the morning, so I assume it happens when SharePoint is warming up.  The ULS Logs gave me no clues.   If the user refreshed the page, the error disappeared.

I found a nice jQuery plugin that will automatically retry  an ajax request after an error  here: https://github.com/johnkpaul/jquery-ajax-retry.

After adding that plugin, I just needed to change one line of code:

return $.ajax(ajaxOptions);

to

return $.ajax(ajaxOptions).retry({ times: 3, statusCodes: [500] });

and that fixed the problem.

Posted in ajax, javascript, jquery | Tagged , | 1 Comment

Getting started with Durandal on SharePoint

I recently saw a presentation on using Durandal to build Single Page Applications within a SharePoint-hosted app. You can download the Sildes from the presentation on Andrew Connels blog here). It looked promising, so I wanted to give it a go. The instructions here show how to create a Durandal SPA within a SharePoint-hosted app.

Open Visual Studio 2012 and select File/New/Project/SharePoint 2013 App

Make it app named SharepointDurandalSample

d1

Next, add Durandal to the project

Go to Tools/Library Package Manger/Package Manager Console

Within the Package Manager Console, enter the command:

Get-Package -ListAvailable Durandal

d2

This will display the packages available containing the text ‘durandal’:

We want the starter kit, so enter the command:

install-package Durandal.starterkit

This added a lot of stuff to the project as you can see:

d3

If we build the project now, we get an error on the DurandalController.cs. We don’t need it, since we’re using SharePoint as the backend, so we can just delete the Controllers Folder.

The pages/Default.aspx is the starting page for the SharePoint-hosted app that Visual-studio created for us.  It wants to start the app by calling /Scripts/App.js.  We’re going to change this below so we can delete the following line from Default.aspx:

<script type=”text/javascript” src=”../Scripts/App.js”></script>

We can also delete the file /Scripts/App.js (DO NOT MISTAKENLY DELETE SCRIPTS/DURANDAL/APPS.JS)

Replace the contents of the contentsPaceholderMain inside of Defaut.aspx with

<div id=”applicationHost”>

<div>

<div>

Durandal Starter Kit

</div>

<i></i>

</div>

</div>

<script type=”text/javascript” src=”../Scripts/require.js” data-main=”../App/main”></script>

The <div> whose id is applicationHost is where Durandal will display its output. The <Script> tag tells the browser to load require.js and the start App/Main.js. (I’m not sure about the majic that makes that happen.

If we try to run the app now, we get an error because Durandal wants knockout to be loaded on the page, so we need to add knockout to default.aspx. Add the following to paceholderadditionalpagehead within default.aspx:

<script type=”text/javascript” src=”../Scripts/knockout-2.3.0.js”></script>

Now if we run the app, we get an error that jquery is undefined:

d4

Durandal seems to want jquery 1.9.1, so in the contentplaceholderadditionalpagehead of Default.aspx,replace the tag:

<script type=”text/javascript” src=”../Scripts/jquery-1.8.2.min.js”></script>

with this one:

<script type=”text/javascript” src=”../Scripts/jquery-1.9.1.js”></script>

Running the app now, We see the Durandal sample starter page:

d6

In my case, clicking on the flicker link the first time gave me an exception. But the second time its worked. I’m not sure what’s happening, but I don’t care, I just want to get at some SharePoint data for now.

So let’s create a SharePoint list we can query . in Visual Studio select

Add/New Item/List

Make the list based on the Contacts template and name it My Contacts:

d7

Edit My Contacts/My Contacts Instance/Elements.xml to add some sample data

<?xml version=”1.0″ encoding=”utf-8″?>

<Elements xmlns=”http://schemas.microsoft.com/sharepoint/”&gt;

<ListInstance Title=”My Contacts”

OnQuickLaunch=”TRUE”

TemplateType=”10000″

Url=”Lists/My Contacts”

Description=”My List Instance”>

<Data>

<Rows>

<Row>

<Field Name=”FirstName”>Bill</Field>

<Field Name=”Title”>Gates</Field>

<Field Name=”Email”>bgates@microsoft.com</Field>

</Row>

<Row>

<Field Name=”FirstName”>Steve</Field>

<Field Name=”Title”>Ballmeer</Field>

<Field Name=”Email”>sbalmeer@yahoo.com</Field>

</Row>

</Rows>

</Data>

</ListInstance>

</Elements>

If you run  the app now you should be able to navigate to

https://yourappweb/SharepointDurandalSample/Lists/My%20Contacts/AllItems.aspx

To see the sample data, or go to

https:// yourappweb /SharepointDurandalSample/Lists/My%20Contacts/NewForm.aspx

To add new data.

Now we want to make our Durandal app display this list.

First, we need to modify the app object to remember the appUrl and the webUrl. Add the following function to the App/Main.js to get qyerystring parameters:

function getQueryStringParameter( param )

{

var params = document.URL.split( “?” )[1].split( “&” );

//var strParams = “”;

for ( var i = 0; i < params.length; i = i + 1 )

{

var singleParam = params[i].split( “=” );

if ( singleParam[0] == param )

{

return singleParam[1];

}

}

}

Then, just before appStart add the following code:

app.hostWebUrl = decodeURIComponent( getQueryStringParameter( ‘SPHostUrl’ ) );

app.appWebUrl = decodeURIComponent( getQueryStringParameter( ‘SPAppWebUrl’ ) );

app.requestDigest = $( ‘#__REQUESTDIGEST’ ).val();

(Please note that I am new to Durandal and no doubt this is not the best way to do this)

This will save these properties on the app object so we can use them later.

Next we need to create the ViewModel (or module in Durandal Teminology). In Visual Studio, within the App/viewmodels folder, Add/New Item/Web/Javascript. Name the file MyContacts.js and set the content as follows:

define( [‘plugins/http’, ‘durandal/app’, ‘knockout’], function ( http, app, ko )

{

debugger;

return {

displayName: ‘My Contacts’,

myContacts: ko.observableArray( [] ),

activate: function ()

{

//the router’s activator calls this function and waits for it to complete before proceding

var success = function ( data, status, jqXHR )

{

self.myContacts(data.d.results)

};

var options = {

dataType: “json”,

url: app.appWebUrl + “/_api/lists/getByTitle(‘My Contacts’)/Items”,

headers: {

Accept: “application/json;odata=verbose”

},

success: success

};

var self = this;

return $.ajax(options);

},

};

} );

Then create the view. Within the App/views folder, Add/New Item/Web/HTML File. Name the file MyContacts.html and set the content as follows:

<div>

<h2>Customers</h2>

<table>

<tbody data-bind=”foreach: myContacts”>

<tr>

<td data-bind=”    text: Title”></td>

<td data-bind=”    text: FirstName”></td>

<td data-bind=”    text: Email”></td>

</tr>

</tbody>

</table>

</div>

Finally, Add a route to the new  module inside of the activate function in App/viewmodels/shell.js

activate: function ()

{

debugger;

router.map([

{ route: ”, title:’Welcome’, moduleId: ‘viewmodels/welcome’, nav: true },

{ route: ‘contacts’, title: ‘contacts’, moduleId: ‘viewmodels/MyContacts’, nav: true },

{ route: ‘flickr’, moduleId: ‘viewmodels/flickr’, nav: true }

]).buildNavigationModel();

return router.activate();

}

Now if we run the app, the Contacts link works, and displays the contacts stored in the appweb,

The sourcecode can be downloaded here:http://code.msdn.microsoft.com/Sample-Sharepoint-Hosted-723d7a44

Additional info can be found  at the Durandal site, at  SPServices Stories #13: Durandal SP3: Developing SharePoint SPAs Made Easy, and at at  Durandal SP3: Developing SharePoint SPAs made easy

Posted in Durandal, sharepoint | Tagged , | Leave a comment