Creating High Trust Apps – Part 1

This post will detail how to create and test a high trust SharePoint App. A High Trust app is an app that is installed in an On premise SharePoint Farm. High Trust app do not work in Office 365 – which only support Low Trust apps.

Before we can create a High Trust app, the SharePoint Farm has to be configured to support them. The first part of this two part post will detail how to do this for a development farm. It will contain pointers on how to take this into a Production farm where needed.

This blog assumes you already have a working SharePoint 2013 development farm, likely running on one server. The instructions cover this use case: Either

  • SharePoint, SQL Server and Active Directory all on one server, or
  • SharePoint on one Server and SQL Server and Active Directory either sharing or on separate servers.

At a high level this are the steps necessary:

  1. Create a either new isolated domain or subdomain to host your apps in
  2. Create a new User Profile Service Application, has at least the your account as a profile.
  3. Ensure the App Management and Subscription Settings services are running
  4. Create a new Subscription Settings Service Application using PowerShell
  5. Create a new App Management Service Application (Either via Central Admin or PowerShell)
  6. Set the App Domain and App Site Subscription Name (Either via Central Admin or via PowerShell)

Optional:

  1. Create the App Catalog Site Collection – not required for creating and testing apps using Visual Studio. Required for publishing you apps.

Important Note:

  1. If you are using host headers with you web applications, you will need to create one additional non header web application on either port 80 or 443 and one root collections using any site template. If you are using host header site collections this step is not required.

And now for the details:

1. Create the isolated app domain or sub domain. On the DNS Server (typically the same server running active directory) open up the DNS Manager

  1. Search for “DNS” and open the default app selected. (Assuming you are running Windows Server 2012 or higher)
  2. Create a “New Zone” – right click on the Forward Lookup Zones of your Server name
  3. Click next three times until you get the to “Zone Name” section
  4. Enter a new Zone Name. If you domain was “develop.local” then you could make the name “developapps.local”
  5. Click next twice and click Finish.
  6. Create a new CName for the zone – Click on the new Zone created and right click “New Alias (CNAME)”
  7. Enter “*” for the alias name.
  8. Click the :”Browse…” button and double click on your server name, then on the “Forward Lookup Zones” and finally the domain of your SharePoint farm – in our example “develop.local”. Click OK to complete.
    1. Note: if you have more than one SharePoint server you should double click on the domain and either select the DNS A record of a Farm Web server or the DNS record for the primary cluster address for NLB if used.

2. Next you need to create a User Profile Service Application if not previously created.

  1. It is best to just create this via Central Administration.
    1. First in System Settings > Manage services on server and starting:
      1. User Profile Service
    2. Next in Application Management > Manage Service Applications
      1. Create a new User Profile Service Application
  2. Create a new Profile for the account(s) you use in SharePoint. Alternatively if you can synchronize your user profile service to AD to get multiple accounts. See Synchronize user and group profiles in SharePoint Server 2013 one how to do this.

3. Ensure the App Management and Subscription Settings services are running. This can be verified either:

  1. In Central Administration > System Settings > Manage services on server and starting:
    1. App Management Server
    2. Microsoft SharePoint Foundation Subscription Settings Service
  2. Using Power Shell
    Get-SPServiceInstance | where{$_.GetType().Name -eq "AppManagementServiceInstance" -or $_.GetType().Name -eq "SPSubscriptionSettingsServiceInstance"} | Start-SPServiceInstance
    Get-SPServiceInstance | where{$_.GetType().Name -eq "AppManagementServiceInstance" -or $_.GetType().Name -eq "SPSubscriptionSettingsServiceInstance"}
     

4. Next the App Management and Subscription Setting service application need to be created. As the latter application can only be created using PowerShell, both will so created:

$account = Get-SPManagedAccount "[Name of Service Account]" 
$appPoolSubSvc = New-SPServiceApplicationPool -Name SettingsServiceAppPool -Account $account
$appPoolAppSvc = New-SPServiceApplicationPool -Name AppServiceAppPool -Account $account

$appSubSvc = New-SPSubscriptionSettingsServiceApplication –ApplicationPool $appPoolSubSvc –Name SettingsServiceApp –DatabaseName SettingsServiceDB 
$proxySubSvc = New-SPSubscriptionSettingsServiceApplicationProxy –ServiceApplication $appSubSvc

$appAppSvc = New-SPAppManagementServiceApplication -ApplicationPool $appPoolAppSvc -Name AppServiceApp -DatabaseName AppServiceDB
$proxyAppSvc = New-SPAppManagementServiceApplicationProxy -ServiceApplication $appAppSvc 

5. Next we need to register the domain name that was created in step 1. This can be set either from the new “App” Section created in Central Administration:

  1. Apps > Configure App URLs
    1. Set the App Domain to the domain created. e.g. “developapps.local”, and
    2. Set the App prefix. e.g. “app”
  2. Use PowerShell:
    Set-SPAppDomain "developapps.local"
    Set-SPAppSiteSubscriptionName -Name "app" -Confirm:$false
    

 

 And that’s the end of part one. Note remember to create your app catalog if you want to test publishing apps.

Part two will cover wants required to create a High Trust App, including creating certificates and creating a simple High Trust app using Visual Studio 2013.

Remote Event Receivers debugging and Lists and asset creation

Quick Pattern to follow to debug Remote Event Receivers for List Events for lists in the Host Web. So far I have not been able to debug these successfully. I have been able to when the list and the RER’s are created in the App Web Project and attached to App Web Lists. So it seems to me we could create them in the App web to develop and test them and when working move them into the Host Web.

Also remember any object you what created in the Host web has to be created using code and of course will need the right permissions to do so. These assets can be created either when the app is first run, from a App install event (which makes the app minimally partly a Provider-Hosted App or provisioned from a non app client side application – eg a console application using SCOM.

Promoting Code and Sites from Development to QA to Production using PowerShell

Below is an example of a way to re-create Sites, Libraries, deploy custom code from a Development environment to QA to Staging and finally Production, in a repeatable manner without having to keep multiple versions of PowerShell scripts. It reduces the possiblity of introducing errors.

It consists on one powershell script (which could call on multiple function scripts), which pulls environment varables from a xml file. you would have a separate xml file for each environment.

Add-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction "SilentlyContinue"

# use the following the determine location of this script file
$scriptPath = Split-Path -parent $MyInvocation.MyCommand.Path
$deploymentXml = $scriptPath + "\Xml\Deploy.xml"

# now load the deployment configuration data
[xml]$Data = get-content $deploymentXml
$iisRootPath = $Data.Deploy.Settings.IISRootPath
$Url = $Data.Deploy.Settings.Url
$Port = $Data.Deploy.Settings.Port
$AppPoolAccount = $Data.Deploy.Settings.AppPoolAccount
$Owner = $Data.Deploy.Settings.Owner
$WebAppName = $Data.Deploy.Settings.WebAppName
$SiteName = $Data.Deploy.Settings.SiteName
$SiteTemplate = $Data.Deploy.Settings.SiteTemplate

# Below is an example of Creating a Site Collection

if ($Port -ne "80")
{
	$Url = $Url + ":" + $port
}

Write-Host "`n Create Site Collection" -ForegroundColor Blue

New-SPSite $url -Template $SiteTemplate  -Name  $SiteName -OwnerAlias $Owner -Confirm:$false

Here is the sample XML file:

<?xml version="1.0"?>
<Deploy>
  <Settings>
    <IISRootPath>C:\inetpub\wwwroot\wss\VirtualDirectories\</IISRootPath>
    <Url>http://siteurl</Url>
    <Port>80</Port>
    <AppPoolAccount>AD\SVCACCOUNT</AppPoolAccount>
    <Owner>AD\SITEOWNER</Owner>
    <SiteName>Site Name</SiteName>
    <SiteTemplate>BICENTERSITE#0</SiteTemplate>
  </Settings>
</Deploy>

The folder / file stucture for each environment (DEV, QA, PROD etc) would look like this:

Deployment Folder Structure

Where the Code Solution (WSP’s) and other deployment files would be placed in the DeployFiles folder, PowerShell Function scripts in the Functions folder and the configuration Deploy.xml file in the the Xml folder. The Deployment.ps1 script (and any functions) would remain the same for each environment.

Web Config entries using PowerShell

The powershell script and xml below  can be used to make modifications to a Web Applications web config file across all SharePoint Servers.

It can add multiple sections / notes / attributes to the web config file using an XML file as a template to define what needs to be added / changed.

The script first cleans up any existing data in the web config matching an unique identifier that will be recorded for each modification.

Next the XML file is loaded and loops through each section of the xml, checking wither to add a new node (ie like an AppSettings node, or a change to an existing node attribute (ie say the Custom Error mode value).

Finally the changes at applied to the web config file.

Note: Remember to change the location and url variables to your environment and site url.

XML data file:

<?xml version="1.0" encoding="utf-8"?> 
<sections> 
  <section> 
    <skip>false</skip> 
    <path>configuration/system.web/customErrors</path> 
    <modifications> 
      <modification> 
        <type>EnsureAttribute</type> 
        <name>mode</name> 
        <value>Off</value> 
      </modification> 
    </modifications> 
  </section> 
  <section> 
    <skip>false</skip> 
    <path>configuration/appSettings</path> 
    <modifications> 
      <modification> 
        <type>EnsureChildNode</type> 
        <name>add[@key="SomeKeyName"][@value="SomeValueName"]</name> 
        <value>add key="SomeKeyName" value="SomeValueName"</value> 
      </modification> 
    </modifications> 
  </section> 
</sections>

PowerShell Script:


#=================================================================== 
# Web Config Modifications Script 
#=================================================================== 
 
Add-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction "SilentlyContinue" 
 
#connect to the function library for this script 
$functionLocation = "C:\PowerShell\WebConfigModifications" 
. $functionLocation\Web_Config_Modifications_Functions.ps1 
 
#define the SPWebConfigModification constants 
$modificationOwner = "SomeUniqueIdentifier" 
$EnsureChildNode = 0 
$EnsureAttribute = 1 
 
#get the web configuration modifications xml file 
$webconfigLocation = "C:\PowerShell\WebConfigModifications" 
$webconfigData = $webconfigLocation + "\Web_Config_Modifications.xml" 
 
# get the Web Application for the given Url 
$url = "http://YOUR-WEB-APP-URL" 
$webapp = Get-SPWebApplication $url 
$webapp 
#=============================================================================================================== 
 
#Write-Host "`nCleaning up existing Nodes" 
 
#use this statement below to correct for any errors  
#when initially adding new sections / nodes / attributes  
#etc that may cause exceptions 
#$webapp.WebConfigModifications.Clear() 
 
DeleteSections $webapp $modificationOwner $false 
 
#=============================================================================================================== 
Write-Host "`nAdding Web Config Nodes" 
 
#load the xml data 
[xml]$Data = get-content $webconfigData 
 
foreach ($Section in $Data.Sections.Section) 
{  
    #Ignore sections marked to be skipped 
    if ($Section.Skip -eq "false") 
    { 
        $path = $Section.Path 
        foreach ($modification in $Section.modifications.ChildNodes) 
        { 
            if ($modification.type -eq "EnsureAttribute") 
            { 
                $type = $EnsureAttribute 
                $name = $modification.name 
                  $value =  $modification.value  
                 
                Write-Host "`nChanging $path -> $name to $value" 
            }             
            else 
            { 
                $type = $EnsureChildNode 
                $name = $modification.name 
                $value = "<" + $modification.value + "/>" 
                 
                Write-Host "`nAdding Modifications -> $path : $name, $value" 
            }         
             
            CreateConfigChildNode $modificationOwner $type $path $name $value 
        } 
    } 
} 
 
#=============================================================================================================== 
Write-Host "`nApplying Modifications to the Web.Config"         
$webapp.Update() 
$webapp.Parent.ApplyWebConfigModifications() 
Write-Host "`nCompleted Web.Config Modifications" 
 
#----- END OF FILE  -----# 
 
#----- START of FUNCTION FILE ----# 
 
#=================================================================== 
# Web Config Modifications Script Functions 
#=================================================================== 
 
#=================================================================== 
# function to Create Web Config nodes and or change attributes 
#=================================================================== 
function CreateConfigChildNode($Owner, $Type, $Path, $Name, $Value) 
{ 
    $childNode = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification  
    $childNode.Owner = $Owner 
    $childNode.Path = $Path 
    $childNode.Name = $Name 
    $childNode.Value = $Value 
    $childNode.Type = $Type 
 
    $webapp.WebConfigModifications.Add($childNode) 
} 
 
#=================================================================== 
# function to remove all existing node and changes to attributes matching the Owner name 
#=================================================================== 
function DeleteSections($webapp, $Owner, $removeOnly) 
{ 
    $count =  $webapp.WebConfigModifications.Count 
    $foundNodes = $false 
    for ($i=$count ;$i -gt -1; $i--) 
    { 
        if ($webapp.WebConfigModifications[$i].Owner -eq $Owner) 
        { 
            $foundNodes = $true 
            Write-Host "`n$i" 
            $webapp.WebConfigModifications.Remove($webapp.WebConfigModifications[$i]) 
        } 
    } 
 
    if ($foundNodes -and $removeOnly) 
    { 
        $webapp.Parent.ApplyWebConfigModifications() 
        $webapp.Update() 
    } 
} 
 
#----- END OF FILE  -----#

 

Entering Formulas for Calculated Fields in Lists

A few pointers to those creating calculated columns/fields in SharePoint 2010.

  1. When entering a formula when creating the field initially, it has to have no syntax errors otherwise you will get a nasty error page! If you get this error clicking the back button will take you back to where you were.
  2. Another way to to create the field with a dummy formula and edit the formula by displaying the list in the data sheet view mode. In SharePoint 2010 this is greatly improved! Its also a great way to debug your formula if it is complex.
  3. If you have a very complex formula – below is one I created – you could construct it in say NotePad in parts to help reduce errors while creating your formula.

=IF(ISERROR(SEARCH(” hrs”,Duration,1)), IF(ISERROR(SEARCH(” mins”,Duration,1)), TIME(HOUR(Duration),MINUTE(Duration),0), TIME(HOUR(0),MINUTE(“0:”&REPLACE(Duration, SEARCH(” mins”,Duration,1),5,””)),0)), TIME(HOUR(REPLACE(Duration, SEARCH(” hrs”,Duration,1),4,””)),MINUTE(REPLACE(Duration, SEARCH(” hrs”,Duration,1),4,””)),0))*24

PerformancePoint KPI’s from SharePoint Lists

So recently I started working on a new DashBoard project in SharePoint 2010. One of the requirements was to have KPI’s with trends driven of data stored in SharePoint lists.

While SharePoint provides some nice of the box KPI’s for data stored in Lists, it is not possible to create complex trend based metrics. fortunately PerformancePoint enables you to create KPI’s using SharePoint List data.

Below is an example of how this can be accomplished. This post assumes you have access to the enterprise license and have PerformancePoint and publishing features enabled, plus the PerformancePoint Service application has been created and setup.

  1. The first step is the create the lists with the required columns and some data. In order to have a trend like metric this means you will need two lists – one for the current data and one with older data to trend against.
  2. Next you need to have a Business Intelligence site created – so you can get to the DashBoard designer for PerformancePoint – I’ve not found a way yet to start this app from outside of  this site.  UPDATE: You can get to the designer from the Start Menu. It’s in the SharePoint folder.  A BI site is still has to be created so there is a place to store all the PerformancePoint Content created by the designer.
  3. When the designer is running the following steps are required:
  1. Create a new Data Connection, selecting a Tabular List and the SharePoint List template:

  2. Next you have provide the Url of the site containing your list, select “All Lists” and then the list name itself. NOTE: PerformancePoint will only pull data from the default (All Items) view of the list. Any data filtered on that view will not be available.
  3. Next select the “Properites” tab – give you new dataconnection a meaniful name!
  4. Now go to the “View” tab. Here you will see all of the available columns part of the view of the list. By default all non date fields are Fact Columns and all dates fields are Time Dimension. Data in the fact type columns are by default summed together; you can change this by selecting a new value from the Aggregation dropdown box to the right, to eg. Average.
  5. Save you chnages – click to little save button on the top left of the application – and you have your first SharePoint List Data Connection.

In my next post I will cover creating a KPI from this Data Connection.