Sharepoint App cannot start hostweb workflow
-
10-10-2020 - |
質問
I have a site workflow on my Apps hostweb that I would like to call from within the app.
The issue I am facing is that while I can successfully query the WorkflowServicesManager, find the specific workflow subscription and initiate a startWorkflow - I am getting a NullReferenceException within the ULS logs.
My suspicion is that this has something to do with the App context not sending the correct information to the WorkflowServicesManager
var ctx = new SP.ClientContext(appweburl);
var appContextSite = new SP.AppContextSite(ctx, hostweburl);
ctx.load(appContextSite.get_web());
var wfServiceManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, appContextSite.get_web());
var wfSubService = wfServiceManager.getWorkflowSubscriptionService();
var wfSubs = wfSubService.enumerateSubscriptions();
var wfParams = new Object();
wfParams['personName'] = "Thomas";
var wfSub = null;
ctx.executeQueryAsync(function () {
wfSubEnum = wfSubs.getEnumerator();
while (wfSubEnum.moveNext()){ if(wfSubEnum.get_current().get_name() == "PersonWorkflow"){} wfSub = wfSubEnum.get_current(); }
wfServiceManager.getWorkflowInstanceService().startWorkflow(wfSub, wfParams );
ctx.executeQueryAsync(function () {
})
})
The same code (with just Client context) on the hostweb works fine. Using wireshark I can see that the App sending an extra contructor in the XML during POST - but I am still thinking this is something to do with the appweb contexts or maybe the User Profile Service/WorkFlow manager not handling the App "user".
A similar post here going into quite alot of depth but the resolution does seem to be what I have already been doing. I don't think I am doing anything wrong in that regard.
Is it possible to call a hostweb site workflow from within a sharepoint App?
Update.
It seems as though my problem was with enumerateSubscriptions()
I wanted to enumerate them to get the workflow based on its name, but get_current() does not return an object that startWorkflow can use.
the following code now works
var ctx = new SP.ClientContext.get_current();
var hostCtx = new SP.AppContextSite(ctx, hostweburl);
var wfServiceManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, hostCtx.get_web());
var wfSubService = wfServiceManager.getWorkflowSubscriptionService();
var wfSubs = wfSubService.enumerateSubscriptions();
var wfSub = null;
var wfParams = new Object();
wfParams['personName'] = "thomas";
ctx.load(wfSubs);
ctx.executeQueryAsync(
function () {
var wfSubEnum = wfSubs.getEnumerator();
while (wfSubEnum.moveNext()){ if(wfSubEnum.get_current().get_name() == "PersonWorkflow"){ wfSub = wfSubService.getSubscription(wfSubEnum.get_current().get_id()) } };
wfServiceManager.getWorkflowInstanceService().startWorkflow(wfSub, wfParams);
ctx.executeQueryAsync(function() {});
}
);
解決
This is what I use to start workflows on the host web.
var startWorkflow = function(subId, itemId) {
var d = $.Deferred(),
ctx = new SP.ClientContext.get_current(),
hostCtx = new SP.AppContextSite(ctx, this.hostUrl),
wfServiceManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, hostCtx.get_web()),
wfSubService = wfServiceManager.getWorkflowSubscriptionService();
ctx.load(wfSubService);
ctx.executeQueryAsync(function() {
var wfSubscription = wfSubService.getSubscription(subId);
wfServiceManager.getWorkflowInstanceService().startWorkflowOnListItem(wfSubscription, itemId, new Object());
ctx.executeQueryAsync(function() {
console.log("Workflow started.");
d.resolve();
}, function(sender, args) {
console.error("Failed to start the workflow. " + args.get_message());
d.reject();
});
}, function(sender, args) {
console.error("Failed to start the workflow. " + args.get_message());
d.reject();args.get_message());
});
return d.promise();
};
The key difference being I pass in the subscription id of the workflow I need to start.