Visual Studio debugging and the Avast pop-up


Whenever I do programming on my own laptop, because I have Avast installed, every time I try to debug a program I get the above pop-up appear in the bottom right of my screen. The debugger doesn’t attach, and the program attempts to run for up to 15 seconds, before Avast decides it’s actually OK to run, cancels the program, and then restarts it attaching the debugger. This is very annoying.

How to fix

Open Avast and click on Settings found at the bottom of the left menu.

In the settings menu, under General, there is an Exclusions section.

Click browse and navigate to the folder where you store your Visual Studio Projects and select the tiny tick box next to the folder. Then click OK.


Now click OK on the Avast Settings.

When you debug your Visual Studio projects now, you will not get that pop-up that is scanning the .exe file, and the debugger will attach without any issues.

TypeScript error in Visual Studio – Cannot find module, problem with the tsconfig.json file


As much as I like to write blogs, I also like to follow and work through other people’s blogs, especially if they are step by step instructions similar to the way I think. This one particular blog was showing how to create a simple Angular Hello World app. I followed the blog to the letter and when I tried to build the app I kept getting the following error messages

  • Experimental support for decorators is a feature that is subject to change in a future release. Set the ‘experimentalDecorators’ option to remove this warning.
  • Cannot find module ‘@angular/core’
  • Cannot compile module unless the ‘—module’ flag is provided with a valid module type. Consider setting the ‘module’ compiler option in a ‘tsconfig.json’ file.

typescripterrormessage

This makes no sense, as in my tsconfig.json file I had everything setup correctly. I had set experimentalDecorators to true, so I shouldn’t have received the first error message. Couldn’t work out why it couldn’t find @angular/core as I had used the npm package manager to install it, and in my tsconfig.json file I had set the module to ‘commonjs’. I checked on other websites that I had set up my tsconfig.json file correctly.

{
compilerOptions: {
declaration: true,
emitDecoratorMetadata: true,
experimentalDecorators: true,
lib: [
"es2015",
"dom"
],
module: "commonjs",
moduleResolution: "node",
noImplicitAny: true,
removeComments: false,
sourceMap: true,
suppressImplicitAnyIndexErrors: true,
target: "es5",
typeRoots: [
"../../node_modules/@types/"
]
},
compileOnSave: true,
exclude: [
"node_modules/*",
"**/*-aot.ts"
]
}

It seems if you download TypeScript 2.0 for Visual Studio 2015 you will not be able to use a tsconfig.json file. If you are working with CommonJS module system, Visual Studio will ignore the tsconfig.json file, even though putting the tsconfig.json file within the project, Visual Studio prevents the use of the TypeScript build section of the project properties.

typescriptdisabled

 

The tsconfig.json file is required in Visual Studio Code, but it doesn’t seem to be required for Visual Studio. To fix your error messages, first, remove the tsconfig.json file from your project. This then makes the Typescript build on the properties page enabled. I switched the Module system to CommonJS and ECMAScript version to ECMAScript 6. This got rid of my bottom two errors, however I was still getting the message:

Experimental support for decorators is a feature that is subject to change in future release. Set the ‘experimentalDecorators’ option to remove this warning.

To fix this error:

  • Unload the project from your solution – right click the project and select Unload Project
  • Once you have unloaded the project, you can right click it again, and then edit the project file.
  • Add the following to both PropertyGroup where the condition is for debug or Release. (<PropertyGroup Condition=” ‘$(Configuration)|$(Platform)’ == ‘Debug|AnyCPU’ “> or  <PropertyGroup Condition=” ‘$(Configuration)|$(Platform)’ == ‘Release|AnyCPU’ “> )
        <TypeScriptExperimentalDecorators>True</TypeScriptExperimentalDecorators>
        <TypeScriptEmitDecoratorMetadata>True</TypeScriptEmitDecoratorMetadata>
    

  • Save your changes, then right click the project and Reload Project

Your errors should now be gone, and you can continue to build your project.

Reference

https://www.infopulse.com/blog/using-angular-2-in-visual-studio-2015-tutorial/ – The blog post that helped me!

Ensuring Visual Studio 2015 is using the latest NodeJS and NPM version


When Visual Studio 2015 uses NodeJS and NPM it uses the version local to itself, which as I discovered is annoying if:

  1. You didn’t know this
  2. Thought your PC was up to date after installing the latest NodeJS and NPM globally.

First lets ensure you have installed the latest nodejs and npm globally.

Install / Update NodeJS globally.

  • Using your browser, navigate to https://nodejs.org and download the current version of NodeJs.
  • Once you have downloaded NodeJs, ou can run the installer and work your way through the wizard.
  • Once installed, you can open up a command prompt. Node.js command prompt is also available.

  • Open up the node.js command prompt and type node -v to get the node version. Should match the version you downloaded from the website.

Installing / Update NPM globally.

  • Open the Node.js command prompt
  • Type the following
npm install npm@latest -g
  • Then type npm -v to get the npm version number.

Extensions for Visual Studio 2015

I recommend getting the following extensions for Visual Studio

Click download in both links and install the extensions into Visual Studio.

After you have installed the “NPM Task Runner”, you might need to make it visible in your Visual Studio. To do this, select View > Other Windows > Task Runner Explorer or press Ctrl + Alt + Bkspace



After you have installed the “Package Installer”, when you right click on your project you will see a new link under Add
called Quick Install Package…

When clicked, you can select and install a package from the following package managers


We will use these extensions in a moment.

Checking Visual Studio Version and Updating.

We are going to create a project, and add a package using the Quick Install Package, this will create us a package.json file. We add some commands to the Scripts section, and run them in the task runner.

  • Create yourself a blank web project.
  • Right click
    the project and select Quick Install Package…
  • Select NPM and type TypeScript in the next box, can leave Latest Version and click Install.

  • After you have clicked install you should see a package.json file, which doesn’t have much in it.
{
  "name": "myproject",
  "version": "1.0.0",
  "devDependencies": {
    "typescript": "^2.1.5"
  }
}
  • Update the json file to include two scripts, getNPMVersion, getNodeVersion and updateNPMVersion.
{
  "name": "myproject",
  "version": "1.0.0",
  "devDependencies": {
    "typescript": "^2.1.5"
  },
  "scripts": {
    "getNpmVersion": "npm -v",
    "getNodeVersion": "node -v",
    "updateNPM": "npm install npm@latest"
  }
} 
  • After you have saved the json file, in the Task Runner Explorer window, click the refresh button. You should see your three scripts available to you.

  • Right click on getNpmVersion
    and click Run. The result will display in the Task Runner Explorer console window. You will note that this version is different to the version number you got at the start of this blog post through the Node.js command prompt window.
  • To Update NPM, right click on updateNPM and click Run. After it has completed, run getNpmVersion again. You should find that the version now matches the version you got earlier.
  • Right click on getNodeVersion and click Run. My version is v5.4.1
  • There doesn’t seem to be a command to update the Nodejs in visual studio. However, we can make it use the global version of Nodejs.
  • In Visual Studio click on Tools > Options. Inside Options, select Projects and Solutions > External Web Tools.
  • Add the NodeJS path. Mine is “C:\Program Files\nodejs”. Then move this to the top.

  • Go back to the Task Runner and run the command getNodeVersion you should now see the version matches the version you got earlier in the Node.js command window.

You should now be up to date.

Getting Started with TypeScript


What is TypeScript?

TypeScript works on any browser, any host, any operating system. TypeScript isn’t really a new language. It is an open source project, maintained by Microsoft, configurable to JavaScript version. (ES3, ES6, ES7). It is described as

“TypeScript is a typed superset of JavaScript that compiles to plain JavaScript” – Typescriptlang.org

It adds typing (e.g., String, Boolean, Integers) which for a developer is great because:

  • Allows tooling to autocomplete using intellisense
  • Mistakes in code can be spotted instantly
  • No worries of accidently converting a number into a string, as you might with JavaScript.
  • Supports Standard JavaScript code as well as TypeScript, so you can work with both together.
  • Allow encapsulation through classes and modules
  • Supports contructors, properties and functions
  • Defines Interfaces
  • Saves developer time, and cuts down debugging code.

Installing a compiler

The compiler for TypeScript is called TSC, it works across platforms. It converts TypeScript to JavaScript as browsers do not understand TypeScript. A way to install tsc is as a node.js package with node npm command line.

First you need to install nodejs.

  • Using your browser, navigate to https://nodejs.org and download the current version of NodeJs. (I downloaded the version recommended for most users)
  • Once you have downloaded NodeJs, you can run the installer and work your way through the wizard.
  • Once installed, you can open up a command prompt. Node.js command prompt is also available.

Installing TypeScript Complier

Now you have Node.js installed you can install TypeScript through the node package manager (npm). From the Node.js command prompt, type

npm install -g typescript

Note: The -g flag means to install globally not locally to a folder so that typescript complier works everywhere.

To test that the complier has been installed and working properly, you can perform this quick test.

  • With the command prompt still open, go to a folder of your choice and then type:
    Copy con test.ts
    class myfirstTSClass{
    }
    
  • Press Ctrl + Z and the file is then saved. If you open the file called test.ts in notepad, you will see that a file has been created with the class inside.
  • To compile into JavaScript, type
    tsc test.ts
    
  • In your folder, you should now see a test.js. Open this file in notepad and you should see the following JavaScript.
    var myfirstTSClass = (function () {
        function myfirstTSClass() {
        }
    
        return myfirstTSClass;
    }());
    

Editor Choices

To work with TypeScript you have many different editors you can use for example:

I’m not going to go through how to set up all the different editors, but I will show how to set up Visual Studio and Visual Studio Code as these are the two environments that I typically find myself in when coding. If you head to the TypeScript website (https://typescriptlang.org and click Donwload, you can find information for the other editors there.

Setting Up Visual Studio for TypeScript

Visual Studio is actually really easy, as it is already built into Visual Studio 2015, however it is worth while heading to the TypeScript site and clicking Visual Studio 2015 link (as shown above) to ensure you have the latest version installed within Visual Studio. If you have Visual Studio 2013, you just need to head to the TypeScript site and click the Visual Studio 2013 link.

Install NodeJS for Visual Studio.

Although it’s not a requirement, I recommend installing NodeJS for Visual Studio here too. This will allow you to create NodeJS project within Visual Studio. When I was learning TypeScript, I didn’t always need to write JavaScript that ran in a browser, my hello world application just needed to run within a console window.

In your browser head to VisualStudio.com, on the menu bar, select Features > Application Development > Node.js. Then click the link to “Get Node.js Tools for Visual Studio”

Once downloaded, I then had new project templates available to me in Visual Studio.

Creating a TypeScript Hello World in Visual Studio 2015

  • Open up Visual Studio and create a new Project, select HTML Application with TypeScript, found under the TypeScript template. Click OK.
  • In Solution Explorer you should see a structure like mine. Before we do anything, click the Show All Files button.
  • By opening the app.ts file we can see an example TypeScript class written called Greeter, it displays the current time on the screen.
  • As soon as you hit the Save button, the TypeScript complier automatically runs and creates the corresponding JavaScript and map file. If you refresh the files showing in Solution Explorer, you can see the app.js and app.js.map file. (The JavaScript files are not automatically added to the project, which is why I said click “Show All Files” button).
  • If you open the app.js file, you can see the converted JavaScript.
  • Run the application and in the browser it will tell you the current date and time.

Visual Studio 2013

If you are using Visual Studio 2013, you can install Web Essentials (https://vswebessentials.com) which gives you a JavaScript preview window, to allow side by side TypeScript/JavaScript files.

Setting up Visual Studio Code for TypeScript

As long as you have gone through the steps of installing nodejs and the typescript complier, Visual Studio Code will be able to build TypeScript projects. Unlike Visual Studio 2015, Visual Studio Code requires a bit of configuration for a brand new project to ensure the TypeScript gets converted into JavaScript.

Creating a Hello World in Visual Studio Code

  • Using the command line create a new directory somewhere, and then type code [nameofdirectory] to load it up in VS Code.

    Alternatively using Windows Explorer, you can create the folder, and then right click the folder and select Open with code.

  • Once VS Code has opened, we will create a couple of folders. One called ts and one called js. You do this by clicking on the folder icon in the explorer view.
  • In the ts folder, create a file (pressing the New File button next to the New Folder Button in the explorer view) and call this file helloworld.ts
  • Write the following TypeScript within this file.
class HelloWorld{
      constructor(){
        let divLabel = document.getElementById("mylabel");
        divLabel.innerHTML += "Hello from Visual Studio Code";
    }
}

var helloworld = new HelloWorld();
  • Then outside any folder, create a new file called index.html and put the following HTML within the file.
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div>
            <h1>Hello World App</h1>
            <div id="mylabel"></div>
        </div>

       <script src="js/app.js"></script>
    </body>
</html>
  • Now if we try to build the project, either calling up the command box (Ctrl + Shift + P), typing Build
    and then select Tasks:Run Build Task or just using the shortcut to the run build tasks (Ctrl + Shift + B) you will see the following message appear at the top of your VS CODE.

  • Click Configure Task Runner and select TypeScript – Watch Mode. This will create a new folder called .vscode and a pre-completed file called tasks.json

  • The tasks.json file contains a json object that configures the TypeScript complier to run. We are going to change the args so that it compiles our TS folder. Change the line from:
    //From
    "args": ["-w", "-p", "."],
    
    //To
    "args":["-w", "-p", "ts/"],
    

    This will ensure that the TSC watches (-w) the project directory (-p) TS/

  • We are now going to create one more file called tsconfig.json
    and this is also going to be created in the TS folder. The presence of this file specifies the root files and the compiler options required to compile the project. https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. In this folder put the following json information.
    {
        "compilerOptions": {
              "sourceMap": true,
                 "target": "es5",
                "outFile": "../js/app.js"
        }
    }
    

    The above ensures a sourcemap file is created so that debugging is available directly within TypeScript files instead of JavaScript files. It is also targeting the EcmaScript5 version of JavaScript, and that all files are compiled into one JavaScript file called app.js located in the JS folder.

  • Now if you run the build task (Ctrl + Shift + B) the project will compile and create two files within the js folder. (app.js and app.js.map).
  • Also note that when you make any changes to the helloworld.ts or any new ts files you might create within the ts directory, and save the file, because we created a watch build task, the app.js file is updated automatically.

Before we run this simple HelloWorldTS app, let me show you an extension that you should download and install in Visual Studio Code.

Installing “View In Browser” Extension

You only will need to do this once, not for each project you create.

  • Click the Extensions button and then type ‘view in browser’ in the search box. Once you have found the extension, click Install
  • Once installed you will need to Enable it. This will request for VS Code to be restarted. Click OK, to continue.

Running HelloWorldTS

With the View In Browser installed, any HTML page you go to in your project and press (Ctrl + F1), will open the page directly in the browser.

Debugging TS files

In this section I’m not going to go into explaining how the Visual Studio Code debugger works, however, I will show you that you can debug using the browser. As stated earlier, you can debug the actual TypeScript files because of the .map file. If you run your project within a browser like before then press F12 to open up the browsers developer tools. I’m using Microsoft Edge, if you are not able to see the .ts file, then press the Load Source map button. (Highlighted)

After you have set a break point, refresh the page, and you can see that you can step through the TS file by pressing F11.

Summary

In this blog post I have explained what TypeScript is, how you can set up TypeScript on your machine using Visual Studio 2013/2015 or Visual Studio Code. We have created 2 simple TypeScript applications, and briefly looked at debugging. This post hasn’t explained how you write TypeScript.

 

Nintex Custom Actions – Credential Picker


Continuing on from my previous post of Nintex Custom Actions – Error Handling, I thought I would also blog about using the Credential Control within a Custom Action.

The Credential Control allows the selection of predefined credential workflow constants (Central Admin > Nintex Workflow Management > Mange Workflow Constants) or a username and password to be typed in. When the action is run, the action can be run under the context those credentials. (Please Note: Username should be
domain\username, not just username as the picture indicates)

There are several Nintex actions that use this control already, a few are noted below:

  • Query User Profile
  • Web Request
  • Create AD Group
  • Add user to AD Group

Recently from working with Nintex I have used the Query User Profile


and Update User Profile actions.

Nintex doesn’t provide you with a Create User Profile, because normally with the SharePoint User Profile service, this would automatically import new users in. However, I needed the user to be in the User Profile database as soon as the user existed, I didn’t want to wait for SharePoint to complete the User Profile import. I therefore was required to make this custom action, and had the first opportunity to use the Credential Control Picker.

This blog post will show you which files you will need to update and what code is required, to make your custom action have a Credential Control Picker. I will also show you how to run the code within Nintex in a different user context. Please ensure you know how to create a Custom Action from reading my previous blog post on Creating Nintex Custom Actions, as this doesn’t show you every method and what needs to be filled in, only areas for the Credential control. What you use the Credential Picker is down to you, but you can find a working version in my Create User Profile in my previous Nintex Custom action project on my One Drive.

Looking at the project files below, these are the typical files required to create a Custom Nintex Action.

  • [name]Action.nwa – A XML file that contains Name, Category, Description, Assembly information of Activity and Adapter.
  • [name]Activity.cs – A class inheriting Nintex.Workflow.Activities.ProgressTrackingActivity which is the main execution of the custom action.
  • [name]Adapter.cs – A class inheriting Nintex.Workflow.Activities.Adapters.GenericRenderingAction, which sets up the bindings, and configuration of the custom action.
  • [name]Dialog.aspx – The aspx page to allow the user to configure the custom action.

Below is all the files required for one custom action.

Activity file.

First we will need to add public static DependencyProperties for the Username and one for the Password.

public static DependencyProperty UsernameCredentialsProperty = DependencyProperty.Register(&quot;UsernameCredentials&quot;, typeof(string), typeof(CreateUserProfileActivity));
public static DependencyProperty PasswordProperty = DependencyProperty.Register(&quot;Password&quot;, typeof(string), typeof(CreateUserProfileActivity));

Then each of these Dependency Properties will have its own public property.

//Implement Security
public string UsernameCredentials
{
  get { return (string)base.GetValue(UsernameCredentialsProperty); }
  set { base.SetValue(UsernameCredentialsProperty, value); }
}
 
public string Password
{
  get { return (string)base.GetValue(PasswordProperty); }
  set { base.SetValue(PasswordProperty, value); }
}

As you know the Activity file is where the main execution of the custom action takes place. The case is the same when using a Credential Picker, however you need to run the main bulk of your code in a different context, which will run in a different thread to the main execution.

We need to create an internal class, this class will hold all the information we need to pass between the threads. As you can see, this class will be storing the Username and Password from the control, the SiteID and the WebID of the current site the action is running in. There are two properties to pass a value in and a value out. This is a standard C# class, you can have as many or as little properties as required, minimum you need is the username and password obviously.

internal class RunDifferentThread {
    internal string username { get; set; }
    internal string password { get; set; }
    internal string valueToPassIn { get; set; }
    internal string valueToReturn { get; set; }
    internal Guid siteId { get; set; }
    internal Guid webId { get; set; }
}

Now this class has been created, I can next work on the Execute method.

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
   string runtimeUsername = string.Empty;
   string runtimePassword = string.Empty;

   ActivityActivationReference.IsAllowed(this, __Context.Web);
   NWWorkflowContext ctx = NWWorkflowContext.GetContext(
          this.__Context,
          new Guid(this.__ListId),
          this.__ListItem.Id,
          this.WorkflowInstanceId,
          this);
 
   base.LogProgressStart(ctx);
   try
   {
       //Create RunDifferentThread Object
       CreateUserProfileActivity.RunDifferentThread runDifferentThread = new CreateUserProfileActivity.RunDifferentThread();

       //Get the runtimeUserName and runtimePassword from the Credential picker values.
       CredentialValue.DetermineRuntimeCredentials(this.UsernameCredentials, this.Password, out runtimeUsername, out runtimePassword, ctx.Web.ID, ctx.Web.Site.ID);

       //Setup values to pass to other thread.
       runDifferentThread.username = runtimeUsername;
       runDifferentThread.password = runtimePassword;

       //User Picker field within the Custom Action
       runDifferentThread.valueToPassIn = ctx.AddContextDataToString(this.AccountName);
       runDifferentThread.siteId = this.__Context.Site.ID;
       runDifferentThread.webId = this.__Context.Web.ID;
       runDifferentThread.accountToAdd = ctx.AddContextDataToString(this.AccountName);
 
       //Using System.Threading.Thread, create a new thread passing in the parameters required.
       Thread thread = new Thread(new ParameterizedThreadStart(this.Process));
       thread.Start((object)runDifferentThread);
       thread.Join();

       //A workflow variable to store the result in
       this.returnValue = runDifferentThread.valueToReturn
       base.LogProgressEnd(ctx, executionContext);
       return ActivityExecutionStatus.Closed;
   }
   catch (Exception ex)
   {
       throw;
   }
}

The code for the Execute function starts off the same as any other custom action by getting the Workflow Context. Then you need to call Nintex.Workflow.CredentialValue.DeterminRuntimeCredentials passing in the values from the UserName and Password fields. This will output the correct format values of the Username and Password. We put all the values we want to pass through to the new thread running as the new context to our runDifferentThread class. Next we create a new thread passing in the method to run Process, and the runDifferentThread. (At this point we haven’t written the Process method.) Calling thread.Join() blocks the calling thread until the other thread has terminated, which means it will wait until the method Process being called on the other thread has finished.

Then we can grab the returning value and pass it back to be stored within a workflow variable, or whatever the user has chosen to store the value in.

Below is the code for the Process method. I worked out how to do this code mainly from reflecting on how the custom action Update User Profile.

private void Process(object contextObject)
{
    //Hydrate the runDifferentThread properties
    CreateUserProfileActivity.RunDifferentThread runDifferentThread = (CreateUserProfileActivity.RunDifferentThread)contextObject;

   //This built in Nintex class allows the code to run as different user.
   Nintex.Workflow.Administration.Security security = new Nintex.Workflow.Administration.Security();

   try
   {
       //Check that the username is in the format Domain\UserName
       string[] strArray = null;

       if (runDifferentThread.username.Contains(@&quot;\&quot;))
       {
            strArray = runDifferentThread.username.Split(new char[] { '\\' });
       }

       if(strArray.Length != 2)
           throw new InvalidOperationException(NWResource.GetString(&quot;Exception_InvalidWindowsCredentials&quot;));

       //Run the following code as the given user. Passing in Domain, Username and Password.        
       security.RunAsUser(strArray[1], strArray[0], runDifferentThread.password);

       //This site will run as passed in user.
       using(SPSite site = new SPSite(runDifferentThread.siteId))
       {
           //Perform you elevated permission code here

           //Return value
           runDifferentThread.valueToReturn = &quot;My value to return from wherever&quot;
        }
    }
    catch (Exception ex)
    {
        //Exception handling
    }
    finally
    {
       //Ensure you revert back to original user who is running the workflow.
       security.RevertToLoggedInUser();
    }
}

Walking through the Process method above, first covert the contextObject back to RunDifferentThread class. The Nintex.Workflow.Administration.Security class allows you to run as different context. After checking that the username passed in is in the correct format of Domain\Username, we then call the security.RunAsUser passing in domain, username and password. Everything after this line is ran in the user context. Please remember to finally call security.RevertToLoggedInUser(). When you update the RunDifferentThread class with new properties, these properties will be available back in the Execute method.

Adapter.cs

The adapter class has 3 main methods to change AddActivityToWorkflow, GetConfig and GetDefaultConfig. These would be the same 3 methods you would change for any controls added. At the top of the adapter class create 2 constant properties for Username and Password. These properties values should match the property names in the Activity class.

private const string UserNameCredentialsProperty = &quot;UsernameCredentials&quot;;
private const string PasswordProperty = &quot;Password&quot;;

Within the AddActivityToWorkflow method we need to ensure the properties are assigned to the correct Dependency property in the Activity Class.

parameters[UserNameCredentialsProperty].AssignTo(activity, CreateUserProfileActivity.UsernameCredentialsProperty, context);
parameters[PasswordProperty].AssignTo(activity, CreateUserProfileActivity.PasswordProperty, context);

The GetConfig method needs to return the values from the correct Dependency property in the Activity Class. Put this just before you return config.

parameters[UserNameCredentialsProperty].RetrieveValue(context.Activity, CreateUserProfileActivity.UsernameCredentialsProperty, context.ListId, context.Variables);
parameters[PasswordProperty].RetrieveValue(context.Activity, CreateUserProfileActivity.PasswordProperty, context.ListId, context.Variables);

The GetDefaultConfig method defines the parameters that the user can configure, therefore we need to ensure there are two parameters for Username and password.

config.Parameters[0] = new ActivityParameter();
config.Parameters[0].Name = UserNameCredentialsProperty;
config.Parameters[0].PrimitiveValue = new PrimitiveValue();
config.Parameters[0].PrimitiveValue.Value = string.Empty;
 
config.Parameters[1] = new ActivityParameter();
config.Parameters[1].Name = PasswordProperty;
config.Parameters[1].PrimitiveValue = new PrimitiveValue();
config.Parameters[1].PrimitiveValue.Value = string.Empty;

Optionally, if you want to ensure that the user fills in the User Credential field you could add the following code within the ValidateConfig method within the Adapter class.

if (!parameters[UserNameCredentialsProperty].Validate(typeof(string), context))
{
    isValid &amp;= false;
    validationSummary.AddError(string.Empty, ValidationSummaryErrorType.RequiredCredential);
}

Dialog.aspx

Lastly the dialog.aspx page requires some code to ensure the user has an interface to enter the username/password values. Here you will need to register the Credential control, update the two JavaScript function to read in and read out the values, and lastly update the HTML to display it.

You will need to register the CredentialControl in the page.

&lt;%@ Register TagPrefix=&quot;Nintex&quot; TagName=&quot;CredentialControl&quot; Src=&quot;~/_layouts/15/NintexWorkflow/CredentialControl.ascx&quot; %&gt;

Within the TPARetrieveConfig function you can retrieve the stored values as below. The built in Nintex JavaScript function cc_setUsername and cc_setPassword does the main work of setting the control to display previous values to the user.

if (configXml.selectSingleNode(&quot;/NWActionConfig/Parameters/Parameter[@Name='UsernameCredentials']&quot;) &amp;&amp; configXml.selectSingleNode(&quot;/NWActionConfig/Parameters/Parameter[@Name='Password']&quot;)) {

  cc_setUsername(&quot;&lt;%=credentialPicker.ClientID %&gt;&quot;, configXml.selectSingleNode(&quot;/NWActionConfig/Parameters/Parameter[@Name='UsernameCredentials']/PrimitiveValue/@Value&quot;).text);

  cc_setPassword(&quot;&lt;%=credentialPicker.ClientID %&gt;&quot;, configXml.selectSingleNode(&quot;/NWActionConfig/Parameters/Parameter[@Name='Password']/PrimitiveValue/@Value&quot;).text);
}

The TPAWriteConfig function writes back to the configuration file. Nintex has provided a corresponding get function to read from the control.

function TPAWriteConfig() {
    EnsurePrimitiveValueNode(configXml, &quot;UsernameCredentials&quot;);
    EnsurePrimitiveValueNode(configXml, &quot;Password&quot;);

    configXml.selectSingleNode(&quot;/NWActionConfig/Parameters/Parameter[@Name='UsernameCredentials']/PrimitiveValue/@Value&quot;).text = cc_getUsername(&quot;&lt;%= credentialPicker.ClientID %&gt;&quot;);

    configXml.selectSingleNode(&quot;/NWActionConfig/Parameters/Parameter[@Name='Password']/PrimitiveValue/@Value&quot;).text = cc_getPassword(&quot;&lt;%= credentialPicker.ClientID %&gt;&quot;);

    return true;
}

The HTML code sits within <TemplateRowsArea>.

&lt;Nintex:ConfigurationProperty runat=&quot;server&quot; FieldTitleResourceKey=&quot;General_Credentials&quot; RequiredField=&quot;True&quot;&gt;
&lt;TemplateControlArea&gt;
        &lt;Nintex:CredentialControl DisplayMode=&quot;dialog&quot; runat=&quot;server&quot; id=&quot;credentialPicker&quot; /&gt;
&lt;/TemplateControlArea&gt;
&lt;/Nintex:ConfigurationProperty&gt;

That is all there is to it. As previously stated a working version of the Create User Profile custom action can be found in my One Drive. To use, the account that you are creating must already exist within your Active Directory. (There is already a Nintex action that creates an Active Directory user, also using the credential control picker).

Nintex Custom Actions – Error Handling


A while ago now, I wrote a blog post about Nintex Custom Actions. This was written for SharePoint 2010. I have recently worked on a project where I’ve got a chance to use Nintex again. My own blog post came in very handy, and I have updated it so it now explains what you need to do for SharePoint 2013. To be honest there isn’t much difference. Mainly location of Nintex dll’s, and remembering to put /_layouts/15 when pointing to layout files.

Some of the out of the box Custom actions has an error handling section when configuring.

There are 3 parts to error handling.

  1. Capture Errors – If there is an error should the custom action capture it (Yes/No)
  2. Store error occurrence in – This stores if an error occurred or not. (Yes/No)
  3. Store error text in – This stores the actual error message returned if there is one (Single line of text)

This blog post will show you which files you will need to update and what code is requried, to make your custom action have Error handling section. Please ensure you know how to create a Custom Action from reading my previous blog post, as I won’t be going over old ground. I have added custom error handling to my previous project “Retrieve from Property Bag.” If the property doesn’t exist in the property bag then it will throw an error, this will allow my workflow to take a different path.

ReadFromPropertyBagActivity.cs

First we will need to add public static DependencyProperties for the 3 fields within Error Handling, add these below the previous Dependency properties.

#region Error Handling
//Determines if error handling has been switched on for this activity by the workflow designer.
public static DependencyProperty CaptureErrorsProperty = DependencyProperty.Register("CaptureErrors", typeof(bool), typeof(ReadFromPropertyBagActivity));

//Stores whether or not an error occured.
public static DependencyProperty ErrorOccurredOutputProperty = DependencyProperty.Register("ErrorOccurredOutput", typeof(bool), typeof(ReadFromPropertyBagActivity));

//Stores the details of an error if one occurred.
public static DependencyProperty ErrorMessageOutputProperty = DependencyProperty.Register("ErrorMessageOutput", typeof(string), typeof(ReadFromPropertyBagActivity));
#endregion

Then each of these Dependency Properties will have its own public property.

#region Error Dependency Properties
public bool CaptureErrors
{
    set { base.SetValue(CaptureErrorsProperty, value); }
    get { return (bool)base.GetValue(CaptureErrorsProperty); }
}

public bool ErrorOccurredOutput
{
    set { base.SetValue(ErrorOccurredOutputProperty, value); }
    get { return (bool)base.GetValue(ErrorOccurredOutputProperty); }
}

public string ErrorMessageOutput
{
    set { base.SetValue(ErrorMessageOutputProperty, value); }
    get { return (string)base.GetValue(ErrorMessageOutputProperty); }
}
#endregion

Still within the ReadFromPropertyBagActivity.cs file, the Execute method will needs to be updated. Below I have put the original Execute method and highlighted the extra code required for Error Handling.

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
    //Standard Nintex code to obtain context.
    ActivityActivationReference.IsAllowed(this, __Context.Web);
    NWWorkflowContext ctx = NWWorkflowContext.GetContext(
       this.__Context,
       new Guid(this.__ListId),
       this.__ListItem.Id,
       this.WorkflowInstanceId,
       this);
    base.LogProgressStart(ctx);
 
   //Get the property value.
   string resolvedProperty = ctx.AddContextDataToString(this.Property);

   var result = "";

   //Using the context get the property if it exists.
   if (ctx.Web.AllProperties.ContainsKey(resolvedProperty))
   {
       result = ctx.Web.AllProperties[resolvedProperty].ToString();

       if(CaptureErrors)
            ErrorOccurredOutput = false;

        //store the result.
        this.ResultOutput = result;
    }
    else
    {
        if (CaptureErrors)
        {
            ErrorOccurredOutput = true;
            ErrorMessageOutput = String.Format("Unable to find property bag key:{0}", resolvedProperty);
        }
    }

    //End Execution.
    base.LogProgressEnd(ctx, executionContext);
    return ActivityExecutionStatus.Closed;
}

What is happening here is that if the web site contains the property, then if the user sets the custom action to capture errors then set the ErrorOccurredOutput to false. If the property doesn’t exist, and the user has set the custom action to capture errors then will need to set the ErrorOccurredOutput to true and set the error message in the ErrorMessageOutput property.

ReadFromPropertyBagAdapter.cs

In this file there are only two methods that require code change to include the Error Handing. These methods are AddActivityToWorkflow and GetConfig.

Within the AddActivityToWorkflow, after setting the activity.SetBinding but before the ActivityFlags add the following piece of code.

if (context.Config.ErrorHandling != null)
{
    context.Config.ErrorHandling.AssignTo(activity,
        ReadFromPropertyBagActivity.CaptureErrorsProperty,
        ReadFromPropertyBagActivity.ErrorOccurredOutputProperty,
        ReadFromPropertyBagActivity.ErrorMessageOutputProperty,
        context);
}

Within the GetConfig method, add the error handling code just before we return the NWActionConfig.

config.ErrorHandling = ErrorHandling.BuildFrom(context.Activity,
                ReadFromPropertyBagActivity.CaptureErrorsProperty,
                ReadFromPropertyBagActivity.ErrorOccurredOutputProperty,
                ReadFromPropertyBagActivity.ErrorMessageOutputProperty,
                context.Variables);

ReadFromPropertyBagDialog.cs

This is the final piece of the puzzle. This is the configuration screen when you edit the custom action. There is two javaScript functions (TPARetrieveConfig and TPAWriteConfig) that needs updating, then lastly we will need to update the HTML to display, that uses a registered control.

Add the register control.

<%@ Register TagPrefix="Nintex" TagName="ErrorHandlingConfig" Src="~/_layouts/15/NintexWorkflow/ErrorHandlingConfig.ascx" %>

Nintex has already written the JavaScript to make the error handling work, therefore we just need to call it.

TPARetrieveConfig – This loads and displays previous saved values.

function TPARetrieveConfig() {
            setRTEValue('<%=propertyProperty.ClientID%>', configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='Property']/PrimitiveValue/@Value").text);
            document.getElementById('<%=resultOutput.ClientID%>').value = configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='ResultOutput']/Variable/@Name").text;
 
            LoadErrorHandlingSection();
}

TPAWriteConfig – This saves properties back to the custom action.

function TPAWriteConfig() {
            configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='Property']/PrimitiveValue/@Value").text = getRTEValue('<%=propertyProperty.ClientID%>');

            var resultOuputCtrl = document.getElementById('<%=resultOutput.ClientID%>');

            if (resultOuputCtrl.value.length > 0) {
                configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='ResultOutput']/Variable/@Name").text = resultOuputCtrl.value;
            }

            SaveErrorHandlingSection();

            return true;
        }

Finally we need to add the HTML to the page. This is within the content place holder ID PlaceHolderMain. This is added just before the closing </TemplateRowsArea>.

<Nintex:ConfigurationPropertySection runat="server" Id="MainControls1">
              <TemplateRowsArea>
               <Nintex:ConfigurationProperty runat="server" FieldTitle="Property Bag Property" RequiredField="True">
                   <TemplateControlArea>
                        <Nintex:SingleLineInput clearFieldOnInsert="true" filter="number" runat="server" id="propertyProperty"></Nintex:SingleLineInput>
                  </TemplateControlArea>
                </Nintex:ConfigurationProperty>

                <Nintex:ConfigurationProperty runat="server" FieldTitle="Result Output" RequiredField="False">
                  <TemplateControlArea>
                    <Nintex:VariableSelector id="resultOutput" runat="server" IncludeTextVars="True"></Nintex:VariableSelector>
                  </TemplateControlArea>
                </Nintex:ConfigurationProperty>

                <Nintex:ErrorHandlingConfig runat="server" id="errorHandlingConfig1"></Nintex:ErrorHandlingConfig>
              </TemplateRowsArea>
            </Nintex:ConfigurationPropertySection>

  <Nintex:DialogBody runat="server" id="DialogBody">
  </Nintex:DialogBody>

After I have deployed this custom action to SharePoint (All explained how in previous Nintex blog) my custom action when configured now shows the Error Handling section. I have already configured my custom action in the below screenshot.

You will need to create two workflow variables. I have created ErrorOccurred (Yes/No) and ErrorMessage (Single line of text).

Then in my workflow I have a “Set a condition” workflow action, that is configured to equal to true if ErrorOccured equals Yes. If no error occurs then I set my field value as I did previously before I include error handling, however if there is an error I log this error in the history list.

When running the workflow I have looked for a property bag key called NotThere. This has caused the workflow to error when retrieving the property from the property bag.

And below is the error in the history list.

You can download my updated SharePoint 2013 version of my ReadFromPropertyBag custom action with Error Handling from my OneDrive.