Using Nintex rich text editor (RTE) control in a Nintex custom workflow action

In this post I will list the steps required to use Nintex rich text editor in a custom workflow activity. Because most of the steps are the same as when using a SingleLineInput control I will focus only on the difference. The difference is in the custom action’s configuration dialog application page. For the rest of the steps (creating the custom activity class, DependencyProperties, adapter class, etc.) you can check the Nintex Workflow SDK where there is also a sample project CustomWorkflowAction.

Steps to use RTE control in the configuration dialog page of a custom Nintex Action:

  1. In your project add reference to Nintex.Workflow.ApplicationPages.dll

  2. In your aspx page add

    <%@ Register TagPrefix=”Nintex” TagName=”RTE” Src=”~/_layouts/15/NINTEXWORKFLOW/RTE.ascx” %>

  3. Add the control

    <Nintex:ConfigurationProperty ID=”ConfigurationProperty8″ runat=”server” FieldTitle=”YourFieldTitle” RequiredField=”True”>

    <TemplateControlArea>

    <Nintex:RTE runat=”server” ID=”RTEControl1″ ApproverContext=”true” HideModeChooser=”True” height=”140″ >

    </Nintex:RTE>

    </TemplateControlArea>

    </Nintex:ConfigurationProperty>

  4. To read the value from the saved configuratioin and fill the control when the form is loaded use this javascript code in the function TPARetrieveConfig():

    setRTEValue(<%= RTEControl1.RTEClientId %>, configXml.selectSingleNode(“/NWActionConfig/Parameters/Parameter[@Name=RTEControl1]/PrimitiveValue/@Value”).text);

  5. To save the value of the control when the form is submitted use this code in the function TPAWriteConfig():

    configXml.selectSingleNode(“/NWActionConfig/Parameters/Parameter[@Name=’RTEControl1‘]/PrimitiveValue/@Value”).text = getRTEValue(<%=RTEControl1.RTEClientId %>);

  6. In the code behind of the page declare the control

    Nintex.Workflow.ApplicationPages.RTE RTEControl1;

The last step is important otherwise Visual studio will declare it automatically in the partial class (YourDialogPage.aspx.design.cs) but it will declare it as System.Web.UI.UserControl.

Because RTE control inherits from UserControl the project can be build and deployed without errors but the javascript code for reading and saving the control’s value will fail in runtime and the following Compilation Error would be thrown:

Error: Compilation Error Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately. Compiler Error Message: CS1061: ‘System.Web.UI.UserControl’ does not contain a definition for ‘RTEClientId’ and no extension method ‘RTEClientId’ accepting a first argument of type ‘System.Web.UI.UserControl’ could be found (are you missing a using directive or an assembly reference?) Source Error: setRTEValue(<%= RTEControl1.RTEClientId %>, configXml.selectSingleNode(“/NWActionConfig/Parameters/Parameter[@Name=’RTEControl1′]/PrimitiveValue/@Value”).text);

 

Users can’t edit document in SharePoint 2013 with Word 2013

There are so many reasons that can prevent users from editing a document. If you are experiencing the same symptoms and have the same environment as described below then you are probably having the same problem and my solution should work for you too.

Case and Environment

  • SharePoint 2013 (build 15.0.4667.1000)
  • Word 2013, 32 bit (build 15.0.4615.1000)
  • Users can open and edit documents with Word 2010 without any problem
  • Users can open documents as read only but they can’t edit documents in Word 2013. Word 2013 hangs and the process must be killed.
  • IMPORTANT!: The document library or the content type has a choice field with only number choices (relatively big numbers)

Troubleshooting

After some time lost in troubleshooting (checking form another PC, inspecting the document content, checking permissions, inspecting the traffic with Fiddler,…) I didn’t find anything. Then I started removing columns from the content type one by one and testing the result. As soon as I removed one of the choice columns the problem was gone. Obviously Word 2013 is having troubles with SharePoint choice fields. That choice field had 15 choices and all were big numbers (2000,2001,…,2014). I added the choice field back and started to experiment with different range of consecutive numbers and got the following results:

Choice Values Edit in Word 2013
49,50,…,60 OK
49,50,…,62 OK
49,50,…,64 Failed
157,158,…,164 OK
154,155,…,164 Failed
1162,1163,1164 OK
1560,1561,1562,1563,1164 Failed

From the results we see that Word 2013 has more problems with bigger numbers, it can handle 14 choices with smaller numbers (sequence 49,50,..,62) but it can only handle 3 values with bigger numbers (sequence 1162,1163,1164).
The results presented above probably depend on the available resources for Word 2013, so on another more powerful PC it would probably be able to handle more choice values.
I can’t be sure what Word 2013 is trying to do when it has only number choices but we can add a text choice so Word 2013 treats them all as text. As soon as a text choice is added to the field Word 2013 works fine.
In my case I fixed it by adding a text choice “NA” so now the choice field has the following choices “NA”,”2000″,”2001″,…,”2014″.

Solution

Since Word 2010 is working fine with the same SharePoint choice field its clear that this is a Word 2013 issue, a bug we hope will be fixed with future updates.
As a workaround the problem can be fixed by adding at least one text choice value for the choice field which has only number choices.

User field in Event Receivers when using Claims based authentication and Classic mode authentication

When accessing a user field in event receivers there are few differences in the returned values when Classic mode authentication is used from the value when Claims based authentication is used. The difference is present in AfterProperties of ItemAdding and ItemUpdating event. This is true for SharePoint 2010 and SharePoint 2013 and its present only for custom lists but not for document libraries. I’ve done some testing and the results are presented in this post.

Testing

For testing I created a custom list that contains one User field, added the event receiver and overrode all the list item event handlers. For every event I tried to get the value of the user field from properties.BeforeProperties, properties.AfterProperties and properties.ListItem. The test is performed when adding/changing/deleting the item’s user field using the UI (New and Edit form) and when adding/changing/deleting the field pragmatically. The test is repeated when using Classic authentication and when using Claims based authentication. Also the test is repeated for SharePoint 2010 and SharePoint 2013.

Test results

From the results it turns out that when getting the value of a user field from AfterProperties in ItemAdding and ItemUpdating events the value is different when using the New and Edit form from the value when adding and updating the field pragmatically. This difference is present only when using Claims based authentication.
Below are shown the results only for the events that have this problem. At the end of this post you can find the complete test results for SharePoint 2013. In the tests user1 and user2 are used and they happen to have ID of 41 and 42.

Results when using claims based authentication :

When adding, modifying and deleting item using the UI:

Event From Value
ItemAdding AfterProperties -1;#i:0#.w|domain\user1
ItemUpdating AfterProperties -1;#i:0#.w|domain\user2

When adding,modifying and deleting an item programatically:

Event From Value
ItemAdding AfterProperties 41
ItemUpdating AfterProperties 42
Results when using classic authentication:

When adding,modifying and deleting an item using the UI:

Event From Value
ItemAdding AfterProperties 41
ItemUpdating AfterProperties 42

When adding,modifying and deleting an item programatically:

Event From Value
ItemAdding AfterProperties 41
ItemUpdating AfterProperties 42

You can see that the problem is only with claims based authentication while with classic authentication the results are the same when the item is added/modified using the UI and when it’s added/modified programmatically.
One small difference between SharePoint 2010 and SharePoint 2013 is that in SharePoint 2010 even if the user field is not changed the AfterProperties in ItemUpdating event will have the value “-1;#i:0#.w|domain\user1”. In SharePoint 2013 if the field is not changed then the AfterProperties in ItemUpdating event contain the user ID.

Consequences

Because of these differences it’s possible that your old code which has worked fine with classic authentication will not work with claims based authentication.
For example with classic based authentication in ItemAdding and ItemUpdating events the modified value of a user field can be retrieved as below:

 SPUser user = new SPFieldUserValue(properties.Web, properties.AfterProperties["UserField"].ToString()).User;

This code will not work when using Claims based authentication because the value of properties.AfeterProperties[“UserField”] is “-1;#i:0#.w|domain\user1”

Solution

Because its happening only when adding and modifying a user field using the New and Edit form it seems that the problem is with the PeapleEditor control. For some reason it doesn’t work as well with claims based authentication as it does with classic authentication.
To solve the problem I changed my code for getting the user from AfterProperties so it would work for Claims authentication no matter is the field changed using the PeapleEditor control or programmatically.

public static SPUser GetUserFromAfterProperties(object property, SPWeb web)
{
	SPUser user = null;
	string fieldValue = property == null ? null : property.ToString();

	//If adding/editing item directly in the list using NewItem/EditItem form
	if (fieldValue.Contains(";#"))
	{
		string loginName = fieldValue.Contains(";#") ? fieldValue.Split(new string[] { ";#" }, StringSplitOptions.None)[1] : null;
		user = web.EnsureUser(loginName);
	}
	//If adding/editing item programatically
	else
	{
		user = new SPFieldUserValue(web, poperty.ToString()).User;
	}

	return user;
}

To get the user from after properties call the above function in your event receiver:

SPUser user = GetUserFromAfterProperties(properties.AfterProperties["YourUserField"], properties.Web);

All test results

For reference below are all the results from the tests for SharePoint 2013 for Claims based authentication and Classic authentication, both when working with a list item using the UI and programmatically.

Resluts when using claims based authentication:

When adding, modifying and deleting item using the UI:

Event From Value
ItemAdding AfterProperties -1;#i:0#.w|neodomain0\u1
ItemAdding BeforeProperties N/A
ItemAdding ListItem ListItem = null
ItemAdded AfterProperties 41
ItemAdded BeforeProperties N/A
ItemAdded ListItem 41;#u1
ItemUpdating AfterProperties -1;#i:0#.w|neodomain0\u2
ItemUpdating BeforeProperties N/A
ItemUpdating ListItem 41;#u1
ItemUpdated AfterProperties 42
ItemUpdated BeforeProperties N/A
ItemUpdated ListItem 42;#u2
ItemDeleting AfterProperties N/A
ItemDeleting BeforeProperties N/A
ItemDeleting ListItem 42;#u2
ItemDeleted AfterProperties N/A
ItemDeleted BeforeProperties N/A
ItemDeleted ListItem ListItem = null

When adding,modifying and deleting an item programatically:

Event From Value
ItemAdding AfterProperties 41
ItemAdding BeforeProperties N/A
ItemAdding ListItem ListItem = null
ItemAdded AfterProperties 41
ItemAdded BeforeProperties N/A
ItemAdded ListItem 41;#u1
ItemUpdating AfterProperties 42
ItemUpdating BeforeProperties N/A
ItemUpdating ListItem 41;#u1
ItemUpdated AfterProperties 42
ItemUpdated BeforeProperties N/A
ItemUpdated ListItem 42;#u2
ItemDeleting AfterProperties N/A
ItemDeleting BeforeProperties N/A
ItemDeleting ListItem 42;#u2
ItemDeleted AfterProperties N/A
ItemDeleted BeforeProperties N/A
ItemDeleted ListItem ListItem = null
Results when using classic authentication:

When adding,modifying and deleting an item using the UI:

Event Properties Result
ItemAdding AfterProperties 8
ItemAdding BeforeProperties N/A
ItemAdding ListItem ListItem = null
ItemAdded AfterProperties 8
ItemAdded BeforeProperties N/A
ItemAdded ListItem 8;#u1
ItemUpdating AfterProperties 9
ItemUpdating BeforeProperties N/A
ItemUpdating ListItem 8;#u1
ItemUpdated AfterProperties 9
ItemUpdated BeforeProperties N/A
ItemUpdated ListItem 9;#u2
ItemDeleting AfterProperties N/A
ItemDeleting BeforeProperties N/A
ItemDeleting ListItem 9;#u2
ItemDeleted AfterProperties N/A
ItemDeleted BeforeProperties N/A
ItemDeleted ListItem ListItem = null

When adding,modifying and deleting an item programatically:

Event Properties Result
ItemAdding AfterProperties 8
ItemAdding BeforeProperties N/A
ItemAdding ListItem ListItem = null
ItemAdded AfterProperties 8
ItemAdded BeforeProperties N/A
ItemAdded ListItem 8;#u1
ItemUpdating AfterProperties 9
ItemUpdating BeforeProperties N/A
ItemUpdating ListItem 8;#u1
ItemUpdated AfterProperties 9
ItemUpdated BeforeProperties N/A
ItemUpdated ListItem 9;#u2
ItemDeleting AfterProperties N/A
ItemDeleting BeforeProperties N/A
ItemDeleting ListItem 9;#u2
ItemDeleted AfterProperties N/A
ItemDeleted BeforeProperties N/A
ItemDeleted ListItem ListItem = null
%d bloggers like this: