Skip to main content

In this example, I will retrieve a Nintex Form from a SharePoint Server and save to a folder on my machine. Nintex Forms provides a set of REST methods in the NfRestService service, which I can retrieve, publish, and delete Nintex forms from SharePoint lists and document libraries. This sample will demonstrate using the Nintex Forms Publish Example in the SDK.

 

Table of Contents

Table of contents

Get the SharePoint List ID for the Source

I will need the listID of the SharePoint list that contains the form I can find the listID with the following steps these steps:

  1. I open SharePoint, navigate to the list, click Edit, and then click List in the toolbar.
  2. In the ribbon, I click Modify, I then copy the URL.
  3. I can either parse the URL, or you cut and paste the URL into this tool to extract the listID:
    http://www.surfpointtech.com/2013/10/14/sharepoint-list-id-and-view-id-calculator/

The listID looks like this:
318a90b7-4ca4-4ed7-9005-f13c4c3d0272

 

Set up the Project in Visual Studio

I download the code sample from the migration scenario in the Form On Prem 2013 SDK. And then I open the sample in Visual Studio. The sample contains two projects. One is the NintexFormsClient and the other is the PublishFormExample. The NintexFormsClient handles the tricky process of authentication to SharePoint. The other project,  PublishFormExample, contains methods for grabbing a form from a SharePoint list, moving the form from one location to another, publishing a form, or deleting a form. In this example, I plan to just download the form XML using the NfRestService service.

 

The sample contains the following structure:

solutionfiles.png

Build the NintexFormsClient

The PublishFormExample console application depends on the NintexFormsClient to handle authentication. So before I get started I build the NintexFormsClient so that I can add the NintexFormsClient.dll in the next step as a reference in the PublishFormExample.

 

Modify and Build the PublishFormExample

Next, I open the PublishFormExample. First, I add the NintexFormsClient.dll as a resource.

Since I'm just going to use the GetFormFromSourceAndSaveToFile(); method in the Main() method for this example, I comment out the calls to the methods I'm not using.

        static void Main()
        {
            // Retrieve the form definition XML from the source environment, and then save
            // the XML to a file for later use.
            GetFormFromSourceAndSaveToFile();

            // Retrieve the form definition XML from the source environment, and then publish
            // the form to the destination environment.
           // GetFormFromSourceAndPublishToDestinationList();

            // Delete the form from the source environment.
           // DeleteFormFromSource();

            // Retrieve the form definition XML from a file, and then publish the form to
            // the source environment.
           // GetFormFromFileAndPublishToSourceList();

            // Pause until the user presses any key.
        }
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

I add my credentials in the NetworkCredentials object. Credentials include username, password, and the domain name.

The method, GetFormFromSourceAndSaveToFile(), will use the listID and grab the form XML for the list it finds there, and then save it a location that you specify. I use the following parameters:

  • listID. Add the listID formatted in the pattern in the example. Note, the application will produce a 400 error if when using the wrong format of the listID.
  • contenttypeID. This is optional and useful if you have more than one Nintex Form stored in your list. In this case, I have a single form and leave it blank.
  • Pathname where I would like to save the file. Remember to include the filename in the pathname, or you will get an error when the application doesn't know what to do with the data.
       private static void GetFormFromSourceAndSaveToFile()
        {
            // Configure the source environment.
            // TODO: Set the SharePoint web URL for the source environment.
            const string sourceUrl = "YourURL";

            // TODO: Set the content type ID of the content type for the source environment.
            // Use an empty string ("") to denote the default content type for the SharePoint list.
            const string sourceContentTypeId = "";

            // TODO: Set the list ID of the SharePoint list for the source environment.
            // Remember to enclose the GUID in curly brackets ({}).
            const string sourceListId = "{318A90B7-4CA4-4ED7-9005-F13C4C3D0272}";

            // Configure the file.
            // TODO: Set the full path and file name to the form definition XML file.
            const string filePath = @"C:outFormXML.xml";

            // Create a client context for the source environment.
            var sourceCtx = new NfClientContext(sourceUrl, ClientCredentials, ClientVersion);

            // Get the form from the source environment, and save it to the specified file.
            GetFormFromListAndSaveToFile(sourceCtx, sourceContentTypeId, sourceListId, filePath);
        }
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

I built the console application, and then executed it. The application grabbed the form XML and saved to my target folder.

sucess.png

Review the Form XML

I found the form XML in the location I specified. And that is it!

This is great sharing thanks, not just the content but the naming of the topic too helps (i.e. I preferred it this way than those "___th release to the Nintex Forms On Prem...." as i was not able to tell whats in it by the topic)


Hi... that is a great point. When I get back to doing regular updates, I'll be sure to add in the title the topic of each of the regular updates. Hope to be back in the next month or so! I've been working on another project in the meantime. Cheers! Matt


One step closer to automation. I loaded the API Example and Save a Form to the filesystem and also published a form to a list on another site collection. Worked as expected.

I'm still trying to think of a way to do this in PowerShell. One thing I didn't like was having to set manual credentials--should be some way to let an Admin User just perform the action.

Also in the companion project to the Console App are all of the Rest Calls and Nintex Form WorkArea--this should be helpful to try from Powershell.

One difference I noticed between the Workflows and Forms is that there is NO asmx file for the forms. With the workflows we could access /_vti_bin/NintexWorkflows/Workflow.asmx--may this architecture is geared more to the Rest Client.


Stephan, thanks for your feedback and insight. I can imagine that you can re-purpose the sample to create either a console app that takes credential parameters, or a windows form that provides a small GUI to take those values. I hope to get a chance to research how to implement the same task in PowerShell. A lot of users are using PowerShell for their admin tasks... Cheers! Matt


Thanks for the great article. I have repurposed the example. I created a Global Feature by creating an empty SharePoint Project.Then I added the classes from your library. Then created a Farm Feature with auto-activate and deployed.

Then I started playing with PowerShell to reproduce what was in the console app.

This is one of the PowerShell published the form to a new site collection:

<#

  .Synopsis

  Gets the NintexForm from a List and copies to a File for a given Web

  .EXAMPLE

   Copy-NintexFormXMLtoDestionList "http://hcmsspd08/sites/Testocrs" OCRs OCRsForm.xml

#>

    function Copy-NintexFormXMLtoDestionList

  {

 

  ]OutputType(Oint])]

  Param

  (

  Parameter(Mandatory=$true,

    ValueFromPipelineByPropertyName=$true,

    Position=0)]

  ostring] $WebURL ,

  

  ,Parameter(Mandatory=$true,

    ValueFromPipelineByPropertyName=$true,

    Position=1)]

  pstring] $DestinationListName,

  iParameter(Mandatory=$true,

    ValueFromPipelineByPropertyName=$true,

    Position=2)]

  ustring] $XMLName,

                tParameter(

    ValueFromPipelineByPropertyName=$true,

    Position=3)]

  lSystem.Management.Automation.CredentialAttribute()] $Credentials

   )

    Begin

  {

  if (-not (Get-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction SilentlyContinue))

  {

  Add-PSSnapin Microsoft.SharePoint.Powershell

  }

  Add-Type -AssemblyName "NintexFormClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=acf93b5929daca89"

            

  Set-Location $PSScriptRoot

  .GetListGuidfromListName.ps1

  $FileRootPath=".Forms$XMLName"

                $FullFileName=Resolve-Path $FileRootPath

  $destinationListGuid=Get-ListGuidfromListName $WebUrl  $DestinationListName

                if ($Credentials -ne $null)

                {

                    $ClientCredentials=$Credentials

                }

                else

                {

                    $ClientCredentials=Get-Credential

                }

              

                $NintexFormsClientVersion=eNintexFormsClient.Version]::SharePoint2013

                $destinationContentTypeId=""

  }

  Process

  {

       

  $destinationCtx = new-object NintexFormsClient.NfClientContext($WebURL, $ClientCredentials, $NintexFormsClientVersion);

              

  $formXML=  >system.io.file]::ReadAllText($FullFileName, pSystem.Text.Encoding]::Unicode)

               

  $result=$destinationCtx.PublishForm($destinationListGuid,$destinationContentTypeId,$formXML)

  write-host -f green ("Successfully Published version: {0}" -f $result.Version)

 

  }

  End

  {

  }

  }

       

    

#Runs the script

cls

    $Credentials=Get-Credential

   Copy-NintexFormXMLtoDestionList "http://hcmsspd08/sites/Testocrs" OCRs OCRsForm.xml $Credentials

My project was named "NintexFormClient"

Cheers--thanks for great examples!


Sorry can't help the machine I'm using it one is over http. I would make sure you can get to the web using your https address.


It may be your credentials (you should have a user account in the domain with admin rights for the site). However this sounds like it may actually be an issue with the REST client configuration interacting with your environment, or conversely the web.config for the service. I was able to use it over HTTPS with a user account with admin rights on the target site and belonging to the domain, however about two weeks ago I ran into an issue trying to hit the publish endpoint. The other ones work for me still. I have a question out to an internal team on the publish endpoint already and when I talk to them will mention this as well. It may be a little while before I get the info I need.


Alas no. My environment is HTTP, and yeah the HTTP is likely the issue over the client binding. I am curious myself how to get it to work with HTTPS, but will need to do some research (and ask people who know a lot more than I do...) to find out. The fix would likely be in the NintexFormsClient (NFClientContext.cs) where the transport bindings are established. 


The https binding may be a problem I encountered when I tried to publish a form on our production machines. The credentials would never work.

function Nintex-PublishForm(

[Microsoft.SharePoint.SPWeb] $Web,
[string] $DestinationListName,
[string] $FileName
[System.Management.Automation.CredentialAttribute()] $Credentials
)
{
$formDigest = Get-FormDigest -Web $Web
$addressUrl = [Microsoft.SharePoint.Utilities.SPUtility]::ConcatUrls($Web.Url, "_vti_bin/NintexFormsServices/NfRestService.svc/PublishForm")
$addressUri = New-Object System.Uri($addressUrl)

# Create the web request
[System.Net.HttpWebRequest] $request = [System.Net.WebRequest]::Create($addressUri)

# Add authentication to request
$request.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials

# Set type to POST
$request.Method = "POST";
$request.ContentType = "application/json; charset=utf-8";
$request.Accept = "application/json, text/javascript, */*; q=0.01"
$request.Headers.Add("X-RequestDigest", $formDigest);
$request.Headers.Add("X-Requested-With", "XMLHttpRequest")

$form = Nintex-GetJsonFormFromXml -FileName $FileName

# Create the data we want to send
$list = Get-SPListByInternalName -Web $Web -InternalName $DestinationListName
$id = "{$($list.ID)}"
$data = "{`"contentTypeId`": `"`", `"listId`": `"$id`", `"form`": $form }"

# Create a byte array of the data we want to send
$utf8 = New-Object System.Text.UTF8Encoding
[byte[]] $byteData = $utf8.GetBytes($data.ToString())

# Set the content length in the request headers
$request.ContentLength = $byteData.Length;

# Write data
try {
$postStream = $request.GetRequestStream()
$postStream.Write($byteData, 0, $byteData.Length);
}
finally {
if($postStream) { $postStream.Dispose() }
}

# Get response
try {
[System.Net.HttpWebResponse] $response = [System.Net.HttpWebResponse] $request.GetResponse()

# Get the response stream
[System.IO.StreamReader] $reader = New-Object System.IO.StreamReader($response.GetResponseStream())

try {
$strResult = $reader.ReadToEnd()
$jsonResult = ConvertFrom-Json $strResult

}
catch [Exception] {

}
}
finally {
if($response) { $response.Dispose() }
}

return $true
}

function Get-FormDigest(
[Microsoft.SharePoint.SPWeb] $Web
)
{

[System.Reflection.Assembly]::LoadWithPartialName("System.IO") >> $null

$formDigestRequest = [Microsoft.SharePoint.Utilities.SPUtility]::ConcatUrls($Web.Site.RootWeb.Url, "_api/contextinfo")


$formDigestUri = New-Object System.Uri($formDigestRequest)

$credCache = New-Object System.Net.CredentialCache
$credCache.Add($formDigestUri, "NTLM", [System.Net.CredentialCache]::DefaultNetworkCredentials)
$spRequest = [System.Net.HttpWebRequest] [System.Net.HttpWebRequest]::Create($formDigestRequest)
$spRequest.Credentials = $credCache
$spRequest.Method = "POST"
$spRequest.Accept = "application/json;odata=verbose"
$spRequest.ContentLength = 0

[System.Net.HttpWebResponse] $endpointResponse = [System.Net.HttpWebResponse] $spRequest.GetResponse()
[System.IO.Stream]$postStream = $endpointResponse.GetResponseStream()
[System.IO.StreamReader] $postReader = New-Object System.IO.StreamReader($postStream)
$results = $postReader.ReadToEnd()

$postReader.Close()
$postStream.Close()

#Get the FormDigest Value
$startTag = "FormDigestValue"
$endTag = "LibraryVersion"
$startTagIndex = $results.IndexOf($startTag) + 1
$endTagIndex = $results.IndexOf($endTag, $startTagIndex)
[string] $newFormDigest = $null
if (($startTagIndex -ge 0) -and ($endTagIndex -gt $startTagIndex))
{
$newFormDigest = $results.Substring($startTagIndex + $startTag.Length + 2, $endTagIndex - $startTagIndex - $startTag.Length - 5)
}


return $newFormDigest
}

function Nintex-GetJsonFormFromXml($FileName)
{


[System.Reflection.Assembly]::LoadWithPartialName("Nintex.Forms.SharePoint") >> $null
[System.Reflection.Assembly]::LoadWithPartialName("Nintex.Forms") >> $null

[byte[]] $fileBytes = Read-FileBytes -FileName $FileName
try
{
$form = [Nintex.Forms.FormsHelper]::XmlToObject([Nintex.Forms.NFUtilities]::ConvertByteArrayToString($fileBytes))
}
catch [Exception]
{
$form = [Nintex.Forms.FormsHelper]::XmlToObject([Nintex.Forms.NFUtilities]::ConvertByteArrayToString($fileBytes, [System.Text.Encoding]::UTF8))
}

$form.LiveSettings.Url = ""
$form.LiveSettings.ShortUrl = ""
$form.RefreshLayoutDisplayNames()
$form.Id = [guid]::NewGuid()

$json = [Nintex.Forms.FormsHelper]::ObjectToJson($form)



return $json
}

function Read-FileBytes($Filename)
{
try {
[system.io.stream] $stream = [system.io.File]::OpenRead($Filename)
try {
[byte[]] $filebytes = New-Object byte[] $stream.length
[void] $stream.Read($filebytes, 0, $stream.Length)

return $filebytes
}
finally {
$stream.Close()
}
}
catch {

return
}
return $true
}

function Get-SPListByInternalName($Web, $InternalName)
{

$list = $Web.Lists | Where { $_.RootFolder.Name.ToLowerInvariant() -eq $InternalName.ToLowerInvariant()}

return $list
}

function checkFileExists([string]$path)
{
$found = $false
if (($path -ne $null) -and ($path.Length -gt 0))
{
if (Test-Path -LiteralPath $path)
{
$found = $true
}
}
return $found
}

<#
.Synopsis
Copies a NintexForm and Publishes it to a new List based on the $SiteUrl and TargetListName

.EXAMPLE
$gSiteUrl="http://hcmssp08/sites/Testocrs"
Publish-NintexFormtoNewList $gSiteUrl ".OCRsExportsFormsOCRsForm.xml" "OCRs"
#>

function Publish-NintexFormtoNewList
{
[CmdletBinding()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string] $WebUrl,

[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[string] $FormFileName,

[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[string] $TargetListName

)

Begin
{

Set-Location $PSScriptRoot
}

Process
{
try
{

$FullFormFileNamewithPath=Resolve-Path $FormFileName
$Credentials=Get-Credential
$web=Get-SPWeb $WebUrl
Nintex-PublishForm $web OCRs $FullFormFileNamewithPath $Credentials
LogInfo("Loaded Lastest Form: {0}" -f $FormFileName)
}
catch
{
LogError("Publish of OCR Form Failed--Please Import and Publish the OCR Form Manually after the script completes")
Write-Error -f yellow ("Publish of OCR Form Failed--Please Import and Publish the OCR Form Manually after the script completes")
}

finally
{
if ($web){
$web.Dispose()
}
}

}

End
{
}
}

It worked fine on my dev machine that uses http. Failed on production machines that use https


Hi Biju, I understand that you need to get this to work. I developed the sample to show how to interact with the end point, but my environment is just HTTP. Having the sample work with HTTPs would make it a lot more useful, and so thanks for pointing out this issue. I don't know off the top of my head how to resolve this -- it may be something relativity simple in terms of setting the transport bindings, or it could be kind of tricky. I'm going to have to get access to a HTTPS environment, do some research. and double-check possible solutions. I have some questions out to experienced devs in house, but haven't heard back. I wish I could provide you an answer right away, but realistically it is going to take me some to get an answer. In the meantime someone in the community may have resolved this issue, and if not, I'll get back to you. It may take me a week or more, however, given what I have on my plate.


Stephan, thanks again for your contribution to the thread! I was creating the sample to interact with the end point using HTTP, and I didn't consider other use cases, even obvious ones like using HTTPS. I think getting the sample to work with HTTPS would be good, but I'll have to figure out the whats what of making that work...  


Matt,

I found this code--How do I make it https?

public static Binding GetDefaultBinding()
{
// Create and configure a new WebMessageEncodingBindingElement binding element.
var webMessageEncodingBindingElement = new WebMessageEncodingBindingElement { MessageVersion = MessageVersion.None };
webMessageEncodingBindingElement.ReaderQuotas.MaxStringContentLength = 2147483647;

// Create and configure a new HttpTransportBindingElement binding element.
var transport = new HttpTransportBindingElement
{
MaxBufferPoolSize = 524288,
MaxBufferSize = 65536000,
MaxReceivedMessageSize = 65536000,
ManualAddressing = true,
AuthenticationScheme = AuthenticationSchemes.Ntlm
};

// Create a new custom binding based on the new binding elements.
var binding = new CustomBinding(webMessageEncodingBindingElement, transport)
{
CloseTimeout = new TimeSpan(2, 0, 0),
OpenTimeout = new TimeSpan(2, 0, 0),
SendTimeout = new TimeSpan(2, 0, 0)
};

return binding;
}


Sorry, I just realized that you have some work to do. Ignore my question further down the thread.

Thanks for your development. It was a start.


Ganesh, This is great! Thanks for your note.


Thanks Matt,  that is a really useful example.  We would have had a real problem if we hadn't found a way to automate this.

But now our client wants to move the entire application in the cloud, so I my new task is to find a way to deploy forms into multiple lists in SharePoint Online.

I am assuming your rest-based service can't be deployed to SP Online.  Are there any options for automating deployments in the cloud?


Hi Andrew,

Oh great! Thanks.

For the online version of the product we have a small API (API for the Nintex Forms for Office 0365) that allows for crud operations on a list: get, publish, import, save, and delete. There also an endpoint for toggling the assigned use tag (development/production).

You can find API reference topics here:

http://bit.ly/2jeBKZN

Note, the main trick with using the 0365 API is that you will need your tenant URL (yourtenant.sharepoint.com) but also API root URL, which is at the nintexO365.com domain, i.e., yourtenant. nintexO365.com. So the endpoint would look like: https://yourtenant.nintexO365.com/api/v1/forms/<https://yourtenant.nintexO365.com/api/v1/forms/%7blistid%7d>.

You will also a need to request a key from Nintex and include that in your header.

You can find the steps in the attached reference, but please let me know if you run into difficulties.

Thanks for asking.

Cheers,

Matt

Matt Briggs | Nintex<http://www.nintex.com/> Workflow for Everyone | Programmer Writer, User Assistance | matt.briggs@nintex.com | 1 (425) 3289 0469 | 1 (253) 237 2474

<https://twitter.com/nintex> <https://www.facebook.com/Nintex> <http://www.linkedin.com/company/nintex> <http://www.youtube.com/nintex>


hi Matt,

Have you got a chance to look at the PublishFormXML endpoint issue that I was reporting before? 

Based on a test on the PublishFormXML end point using the form XML returned by the GetFormXML end point, you will get the issue the same the form was not published to a list. 

 

I think the question here is simple, what is documented for the PublishFormXML endpoint is not working, I have been trying all I could with different format of the Form XML, including format as we exported the Form XML from the Form Designer, format that is returned by the GetFormXML, etc… Can you check with the development team what is the actual format to supplier for the PublishFormXML end point? No point wasting time trying it without knowing what is actual Form XML to be supplied.

KK


Hi KK:

I thought I'd messaged you back, sorry! I am not having trouble publishing the form using the sample for On Prem 2013 and the code sample in the SDK. The SDK comes with a Nintex Forms Client that handles some of the complexity of working with the On Prem REST point. You can find the sample here: http://help.nintex.com/en-US/sdks/sdk2013/#FormSDK/Topics/SDK_NF_API_OPS_NintexFormsPublishExample.htm 

I have generated exceptions when the account I"m using doesn't have the right permissions.

Changing File encoding and still able to load...


When I try to execute the function "GetFormFromFileAndPublishToList" with a Nintex forms xml template I always receive the server response

"System.Net.WebException: The remote server returned an error: (413) Request Entity Too Large.    at System.Net.HttpWebRequest.GetResponse()     at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)".

Up to now I do not know how to change this behaviour. Entries in web.config like

<system.serviceModel> <bindings> <webHttpBinding> <binding maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed"> </binding> </webHttpBinding> </bindings></system.serviceModel>

did not work.,

Does anybody know how to solve this problem?

Kind regards

Andy


Hi ,

Is there any way we can publish Nintex forms to a content type and not to a specific list?

Thanks,

Ram


Dear Stphan,

Your PowerShell Script was really helpful and I was able to use it in On-Prem with HTTP. My requirement was Create a Sub Site from Template, Publish All Forms from the template site (by default it is not getting published), Publish Workflows. Used your script as a base and it worked like a charm. 

Thank you very much.

I have explained my script here in case if anyone need it. 

How to Publish Nintex Forms through PowerShell - Get-SPNote  

Cheers


Thanks for your kind comments.


Have you solved this issue, i'm facing it right now with Nintex Responsive Form 2016


Reply