Thursday, February 28, 2013

SharePoint ModalDialog and Refreshing the page upon close

Recently I've been working on a project where we're creating a number of custom pages in a SharePoint 2010 solution, some of which need to be opened in a SharePoint dialog box. I've written a couple of openDialog functions before and this time was focused on the different ways to refresh the parent page after the dialog is closed. Here's the base function I was using:

function showDialog(title, url) {
 function showDialogCallback(dialogResult, returnValue) {
  if (dialogResult == SP.UI.DialogResult.OK) {
   SP.UI.Notify.addNotification(returnValue, false);
  }
  else{
   SP.UI.Notify.addNotification(title + " Cancelled", false);
  }
  setTimeout("SP.UI.ModalDialog.RefreshPage(dialogResult);", 1000);
 } 
 var dialogOptions = {
  url: url,
  title: title,
  dialogReturnValueCallback: showDialogCallback
 };
 SP.UI.ModalDialog.showModalDialog(dialogOptions); 
}

This simply allows me to pass in my title and url and the dialog opens with the dynamic size I need.

In my showDialogCallback function I like to use the SP.UI.Notify functionality (causes the yellow box to animate in on the top right with some information) to let the user know what happened.

The last line in this function has a setTimeout calling the ModalDialog.RefreshPage function, as when this function is called it refreshes the page and clears my Notify from the screen. Setting a timeout allows my notification to show for one second before the page refreshes.

There are a few different refresh calls that I've used:

SP.UI.ModalDialog.RefreshPage(dialogResult); 

This will only refresh if the dialogResult == SP.UI.DialogResult.OK. It has the same effect as putting it in the if statement directly above. I read some where that this kind of refresh isn't a complete reload of the page, instead it does some ajax calls to reload the content of the page you're on, though I haven't confirmed that to be true, and can't say from a user prospective that I see any difference with the next method.
location.reload(true);

This is pretty straight forward. It's just going to relaod the entire page grabbing all information from the server again.

Depending on what I'm trying to accomplish I find I use a combination of the setTimeout with either of these reloads.

A few helpful sites I found in my research:
Collabware SharePoint 2010 ModalDialog Tips & Tricks
Antonio Lanaro Blog Post

Monday, January 14, 2013

Document Sets in a SharePoint 2010 Library Template

Recently I needed to create a SharePoint Library template w/ content for a client. They had over 300 document sets with 3 metadata fields that they wanted inside the template. Each year they needed to create a new library with this exact same layout, so saving a document library as a template seemed like the perfect fit.

I created the library, created all the document sets and setup all the metadata for each one and then saved that library as a template.

Unfortunatey when I created a new library based on my shiny new template, all the document sets were generated as Folders and errored out when I tried to access them. Once I manually changed the content type from Folder to my Document Set content type, all worked fine and all metadata fields had the proper values.

So this lead me to research how I could quickly modify over 300 folders content types to the Document Set type.

I then stumbled on this great article by Phil Childs on Changing the Content Type Set on Files in SharePoint.

This PowerShell didn't quite do what I needed it to do however, as it was just looking at the Items and not the Folders, so I modified it slightly to produce what I wanted. My change required creating an array of the Folders IDs as updating a folder changes the collection and would error out of a ForEachObject loop.

Here's what I came up with:
function Reset-SPFolderContentType ($WebUrl, $ListName, $OldCTName, $NewCTName)
{
    #Get web, list and content type objects
    $web = Get-SPWeb $WebUrl
    $list = $web.Lists[$ListName]
    $oldCT = $list.ContentTypes[$OldCTName]
    $newCT = $list.ContentTypes[$NewCTName]
    $newCTID = $newCT.ID
    
    #Check if the values specified for the content types actually exist on the list
    if (($oldCT -ne $null) -and ($newCT -ne $null))
    {
        #Go through each item in the list
	$folderIds = @()
	$list.Folders | ForEach-Object {
		$folderIds = $folderIds + $_.ID
	}
	ForEach ($folderId in $folderIds) {
            #Check if the item content type currently equals the old content type specified
	    $item = $list.GetItemById($folderId)
            if ($item.ContentType.Name -eq $oldCT.Name)
            {
                    #Change the content type association for the item
                    write-host "Resetting content type for file" $item.Name "from" $oldCT.Name "to" $newCT.Name
                    $item["ContentTypeId"] = $newCTID
                    $item.Update()
            }
            else
            {
                write-host "File" $item.Name "is associated with the content type" $item.ContentType.Name "and shall not be modified"
            }
        }
    }
    else
    {
        write-host "One of the content types specified has not been attached to the list"$list.Title
    }
    $web.Dispose()
}

To use it, you copy the entire function, open a SharePoint PowerShell command prompt and paste it in. Hit enter until the >> is no longer you prompt. Then you can use the function like so:

Reset-SPFolderContentType –WebUrl “http://sharepoint/sites/audit” –ListName “2002” –OldCTName “Folder” –NewCTName “Audit Document Set”

Thanks Phil!
- Owen Runnals
SharePoint Practice Manager @ General Networks Corp

Saturday, January 5, 2013

The future of custom forms in SharePoint 2013

I've been doing quite a bit of research on SharePoint 2013 and the future of custom forms. Back in SharePoint 2010 the push seemed to be toward InfoPath Form Services and using IP to create your forms (items, workflow initiation, tasks, etc...).

At the SharePoint 2012 Conference there seemed to be a big push toward Business Users using Access 2013 to create their custom forms, but after I got my environment setup for this I quickly found out that this certainly doesn't replace InfoPath. An Access Web App is very powerful, however it doesn't really integrate with SharePoint other than being hosted there. You can't have workflow run on your items, and you don't even access SharePoint lists or libraries (the data is stored in SQL by the app).

The lack of attention to InfoPath at the conference as well as a few other things (listed below) have made me wonder... What is going to be the InfoPath replacement?

Reasons I believe InfoPath is going away:
  • InfoPath forms services doesn't work with Forms Based Authentication or SAML Tokens. I've been told by Microsoft that this isn't going to change, which leads me to believe they are not putting a focus on it. (See "Features that do not work with forms-based authentication or SAML security tokens" here: )
  • SharePoint 2013 removes InfoPath Forms for Workflow Initiation or Tasks.
  • The complete lack of attention at the conference to InfoPath along with a focus on CSOM and custom ASPX pages.
  • The fact that they haven't fixed things like mapping People Selector fields to actual people columns in Form Libraries, and the ability to access Managed Metadata in custom InfoPath forms. This was frustrating in SharePoint 2010 and is the same in 2013...

So, where does this leave us? Here are the options as I see it:
  • Access Web App - If it's business users and they don't need workflow (like a LOB solution) this could be a great solution.
  • Custom ASPX forms - At the time of writing this seems like the way everything is moving. Strangely this moves form design out of the businesses hands (the push was the opposite way with 2010 release) and into the developers hands.
  • InfoPath - Still fully supported in SharePoint 2013, however as I mentioned above, reading between the lines tells me this may be the last release that "fully" supports IP, so it might be time to start new projects with one of the above two options.

In the end I feel custom ASPX pages are the safest bet since they've worked since SharePoint 2007. Who knows where Access web apps will go in the future. Only time will tell.

As I learn more I'll update this post.

- Owen Runnals
SharePoint Practice Manager @ General Networks Corp

Thursday, December 20, 2012

PowerShell Script to Create Site Collections for SharePoint 2013

After setting up my SharePoint 2013 farm with Host Name Site Collections I wanted a quick easy way to create a new Site Collection, since you can't do it properly through Central Admin.

So I sat down and wrote this PowerShell script that will prompt the user for all necessary information to create a new SC with an option of creating a new Database.

To run you can copy the below script and paste it into a ps1 file.


Add-PSSnapin Microsoft.SharePoint.Powershell
Write-Host "This script can be used to create Site Collections for SharePoint 2013"
$webApp = Get-SPWebApplication | Where-Object {$_.DisplayName -eq "SharePoint HNSC Host - 80"}
IF ($webApp){
 $ans = Read-Host "I found a HNSC Host Web App, would you like me to use it?. Y or N"
 
}
ELSE {
 $ans = 'N'
}
IF ($ans -eq 'N' -or $ans -eq 'n') {
 $webApp = $null
    Write-Host "Here are the web applications I see on your farm"
    Get-SPWebApplication
 while (!$webApp) {
  $webAppName = Read-Host "What is the DisplayName of the Web Application you'd like to use? "
  $webApp = Get-SPWebApplication | Where-Object {$_.DisplayName -eq $webAppName}
  IF (!$webApp) {Write-Host "I didn't find a Web Application with that name. Be sure to enter the full name exactly as it's listed above."}
 }
}
$siteName = Read-Host "Site Name"
$siteDescription = Read-Host "Site Description"
$siteUrl = Read-Host "Site Url (ie http://site.sp2013.com)"
$seeTemplates = Read-Host "Would you like to see a list of templates codes? Y or N"
IF ($seeTemplates -eq 'y' -or $seeTemplates -eq 'Y') {Get-SPWebTemplate}
$siteTemplate = Read-Host "Site Template (ie Blank - STS#0, Team STS#1, etc)"
$siteAdmin = Read-Host "Site Admin (ie ms\devspadmin)"
$createDB = Read-Host "Finally would you like to create a new Content Database for this Site Collection?"
$db = $null
IF($createDB -eq 'Y' -or $createDB -eq 'y') {
    $dbName = Read-Host "Database Name"
    Write-Host "Creating Database..."
    $db = New-SPContentDatabase -name $dbName -webApplication $webApp
}
ELSE {
    Get-SPContentDatabase -webapplication $webApp
    while(!$db) {
        $dbName = Read-Host "What Content Database would you like to use?"
        $db = Get-SPContentDatabase -Identity $dbName
        IF (!$db) {Write-Host "I didn't find a Content Database with that name. Be sure to enter the full name exactly as it's listed above." }
    }
}
Write-Host "Creating Site Collection..."
New-SPSite -Name $siteName -Url $siteUrl –HostHeaderWebApplication $webApp -Template $siteTemplate -OwnerAlias $siteAdmin -ContentDatabase $db -Description $siteDescription
Write-Host "Script Complete"

 
- Owen Runnals
SharePoint Practice Manager @ General Networks Corp

Tuesday, December 18, 2012

SharePoint 2013 Workflow Not Available w/ Blank Site Template

When setting up Workflow Manager 1.0 with your SharePoint 2013 farm it's important to note that a site that is created with the Blank Template (STS#0 if created w/ PowerShell) doesn't have a critical feature enabled that allows you to create SharePoint 2013 workflows in that site.

Update: It seems other templates are also missing this, like the Document Center template.

The feature is called "WorkflowServiceStore" and is enabled by default on the Team Site (and most likely all the other). The only way (that I've found) that you can activate this feature is through PowerShell as there are no related Features in the Site Features section on the site.

You can use the following PowerShell:

Enable-SPFeature -Identity WorkflowServiceStore -Url http://yoursiteurl

Otherwise you'll see this screen when you try to create a workflow, even though your server may be configured properly.


Message text: "The option for the SharePoint 2013 Workflow platform is not available because the workflow service is not configured on the server. Please contact your server administrator"

- Owen Runnals
SharePoint Practice Manager @ General Networks Corp