Nintex for SharePoint Forum
Turn on suggestions
Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
Showing results forÂ
Hi all,
Background Info:
Our Nintex Form requires a "Create COPY" function that makes a copy of an existing list item, and adds to the same list.
I have this copy logic working the way we need it to in a Nintex Workflow using the COPY ITEM workflow control.
This "Create a copy" feature is only available on completed forms via Display (view) mode.
As such, I added a Javascript Button (instead of a SAVE or SUBMIT button - as once the form is completed, the users will only have READ access to the form). So a SAVE or SUBMIT button won't work as SP won't allow saving via Display mode.
The Problem:
My solution below works 100% if the user is a system admin.
POINT 1: Setting the AUTH header in the AJAX call by executing the line:
//xhr.setRequestHeader ("Authorization", "Basic " + window.btoa("login:pass"));
// where login/pass is a system admin account
Uncommenting the above live does not work for users that have "Contribute" permissions on the site. The error is 500 - Internal server error.
POINT 2: Setting the Username and Password parameters in the AJAX call:
// username: "login",
// password: "pass",
// where login/pass is a system admin account
Uncommenting the above lines work, but it seems that after the AJAX call executes, the Logged in user for Sharepoint is now the accounts defined by (login/pass)
ie the system admin account. Which is very weird. The user needs to logout and close the browser window for Sharepoint to recognise the actual users account again.
Current solution (partially not working):
When the JS button is clicked, an AJAX call is made to the Web Service method "StartWorkflowOnListItem" using the serice @ "_vti_bin/NintexWorkflow/Workflow.asmx"
Here's the JS code:
Header 1 |
---|
function StartCreateCopyWF(ItemID, ListName, SiteURL, WFName) { var sr = '<?xml version="1.0" encoding="utf-8"?>' + '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' + 'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ' + 'xmlns:m="http://nintex.com">' + '<soap:Header>' + '</soap:Header>' + '<soap:Body>' + '<m:StartWorkflowOnListItem>' + '<m:itemId>' + ItemID + '</m:itemId>' + '<m:listName>' + ListName + '</m:listName>' + '<m:workflowName>' + WFName + '</m:workflowName>' + '<m:associationData></m:associationData>' + '</m:StartWorkflowOnListItem>' + '</soap:Body>' + '</soap:Envelope>'; NWF$.ajax({ url: SiteURL + "/_vti_bin/NintexWorkflow/Workflow.asmx", beforeSend: function (xhr) { xhr.setRequestHeader("SOAPAction", "http://nintex.com/StartWorkflowOnListItem"); //POINT[1] //xhr.setRequestHeader ("Authorization", "Basic " + window.btoa("login:pass")); }, type: "POST", dataType: "xml", data: sr, // POINT [2] // username: "login", // password: "pass", success: function () { alert("success"); }, contentType: "text/xml; charset=utf-8", error: function (requestObject, error, errorThrown) { alert(requestObject.status + " " + error + " " + errorThrown); } }); } |
Question:
a. How can I execute the above Web Service call to start a Nintex Workflow using either an elevated account (without POINT 2 issue happening).
b. OR What permissions are required to execute the StartWorkflowOnListItem web method @ "_vti_bin/NintexWorkflow/Workflow.asmx" from a user with CONTRIBUTE rights to the Sharepoint site.
c. Any other alternative solution ?
Many thanks for reading. Any help is much appreciated.!
Regards,
Jason
Hi Jason,
using the above JS, it will make the call as the current user who is logged into SharePoint. There's no way with JS, that I know of to run this in elevated mode. If you were to be able to put in credentials, would you really want to hardcode those types of credentials into the JavaScript.
Instead, maybe you can make this call to start a workflow somewhere all users have access to, and then that workflow can start the "real" workflow with elevated privileges. You could do make a similar call like this, using the Call Web Service action and store the credentials in a Workflow Constant that has permissions set on it, as to who has access to it.
I hope this helps.
Vadim
Hi Jason,
I don't think you can start a workflow on an item if you only have read access, see this question for details How to start a workflow with read permission
But instead of using workflow.asmx you could call the lists.asmx UpdateListItems method to replicate the list item explicitly (assuming that the current user can add new items), you can also use REST How to execute a REST API request with Nintex Workflow
Alternatively you could create an item in a new list referencing the ID, and then use a site workflow and the Copy Item action to add the item back to the original list.
Jan
Hi Vadim,
Thankyou for your input. We have been able to confirm the problem is the user having read permissions on the list item that is preventing the current solution from working.
As such, I am investigating your suggested approach:
a. Build a Nintex Site Workflow which inturns uses a 'Call Web Service' component to call my Subsite Copy WF.
b. Update the Javascript to execute StartSiteWorkflow using workflow.asmx web service.
Will report back my findings shortly.
Regards,
Jason
Hi Jan,
Thankyou for your response. In my case, using the UpdateListItem function isn't ideal because our list has over 150 fields.
Having to pass this to UpdateListItem won't be nice and neat.
I will try the SiteWorkflow approach and see if it will work.
Thanks Jan.
Regards,
Jason
Hi Vadim,
This worked. The JS button starts a SiteWorkflow - which in turn has a Call web service component that calls the StartWorkflowOnItem method.
Below is the JS code incase others want the same functionality:
PS: Needed to encode the AssociationData first. Otherwise you get a HTTP 400 error.
----------------------------------------------------
function htmlEscape(str) {
return String(str).replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
}
function StartCreateCopyWF(ItemID, ListName, SiteURL, SiteWFName, WFName) {
var data = '<Data>'
+ '<itemId>' + ItemID + '</itemId>'
+ '<listName>' + ListName + '</listName>'
+ '<workflowName>' + WFName + '</workflowName>'
+ '</Data>';
data = htmlEscape(data);
var sr = '<?xml version="1.0" encoding="utf-8"?>'
+ '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
+ 'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" '
+ 'xmlns:m="http://nintex.com">'
+ '<soap:Header>'
+ '</soap:Header>'
+ '<soap:Body>'
+ '<m:StartSiteWorkflow>'
+ '<m:workflowName>' + SiteWFName + '</m:workflowName>'
+ '<m:associationData>'
+ data
+ '</m:associationData>'
+ '</m:StartSiteWorkflow>'
+ '</soap:Body>'
+ '</soap:Envelope>';
NWF$.ajax({
url: SiteURL + "/_vti_bin/NintexWorkflow/Workflow.asmx",
beforeSend: function (xhr) {
xhr.setRequestHeader("SOAPAction", "http://nintex.com/StartSiteWorkflow");
},
type: "POST",
dataType: "xml",
data: sr,
success: function () {
window.location = SiteURL + "/SitePages/My Saved Requests.aspx";
},
contentType: "text/xml; charset=utf-8",
error: function (requestObject, error, errorThrown) {
alert(requestObject.status + " " + error + " " + errorThrown);
}
});
}
----------------------------------------------------
great stuff Jason. Thanks for sharing the solution.
Jason,
I just found your solution and would like to use it, thanks for sharing. However I am not quite sure how to retrieve the association data in my site workflow. Would you or anyone be willing to provide info about your site workflow as to how you are retrieving the association data? I assume you are putting it into a variable that you are using in the Call Web Service action. I have successfully used the Call Web Service action in several other workflows, I just haven't passed in the info about the workflow I am calling from a variable. Thank you so much, Randy
Hi Jason,
Did you find out on how to retrieve the association data?
You could achieve this without JavaScipt. If you add normal Save button that's connected to a field and returns a value to that field. The workflow could then evaluate that field and determine whether to copy the item:
In the above example: