The Last Update is the Solution
I have got an App for SharePoint 2013, which needs to start a Workflow. This Workflow is in the HostWebContext, not in the AppContext. The List, the Workflow is running on is also in the HostWebContext.
I found two possible ways starting a Workflow in the internet:
With a servicesManager, where you can enumerate all subscriptions to get the Workflow
var servicesManager = SP.WorkflowServices.WorkflowServicesManager.newObject(context, context.get_web());
context.load(servicesManager);
But here I get an Error when I want to create the servicesManager with the hostContext as context.
Unhandled exception at line 2, column 78561 in http://app-d9bb496fd62eeb.dev.local:10000/_layouts/15/sp.runtime.js
0x800a01b6 - JavaScript runtime error: Object doesn't support property or method '$20_0'
With the AppContext as Context I can't enumerate the subscriptions, probably because there aren't any defined Workflows in the App Context
Second possible way is with the jquery.SPServices. But this library currently has a bug with IE11, so this is no solution for me at the moment. Nevertheless, reading some code on the internet, I've found a way to get the Workflow and the List from the HostContext the following way:
//hostcontext is initialized already and contains the HostWebContext, context is the AppContext
var lists = hostcontext.get_web().get_lists();
var list = lists.getByTitle("ListName");
var workflows = list.get_workflowAssociations();
context.load(lists);
context.load(list);
context.load(workflows);
by enumerating the workflows you can get the workflowAssociation for the Workflow you want by checking for the name.
Let's say I've got the right workflowAssociation stored in a var called workflow. Now I want to start this exact Workflow (in the hostWebContext, for a ListItem in the list)
How can I start the workflow? I have no Idea and can't seem to find the right function / way to start the workflow with this object.
The msdn documentation for a workflowAssociation is here
Is it possible to start a workflow outside of the app context?
Is it possible to start a workflow with a workflowAssociation Object?
How could I initialize the servicesManager for the HostWebContext without an error, if I need to?
Is there a workaround so I could call the SPService call shown in the GitHub Link (line 40) without SPServices?
This pretty much sums up my problems for Workflows right now.
Update
When I use the following SPServices no Error occurs:
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/0.7.1a/jquery.SPServices-0.7.1a.min.js"></script>
The GitHub Code runs through. But I can see in my site-collection and the corresponding list, the workflow didn't start. But the success-function is called, so the command is fired.
Either:
- The Link created in this script is wrong (line 27)
- I've also tried to create the link with the hostweburl, not the url of the current window. No success
- I have no permissions to start the workflow this way.
- I gave the App "Elevate" Permissions on Workflows
- Maybe I need also to tell the Server which user is activating the Workflow? Is this possible with OAuth, and how?
- The GitHub Code doesn't work (anymore, maybe because SP2013?)
- The SPServices don't work (anymore, maybe because SP2013?)
The following, quoted Update was WRONG
hostcontext.get_context() refers to the clientContext, not as described below
Update
I've tried to load the servicesManager with the hostContext again and noticed something there:
I'm creating the HostContext Object the following way:
var context = SP.ClientContext.get_current(); var hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl")); var hostcontext = new SP.AppContextSite(context, hostweburl);
The hostcontext object here is what I used to call newObject for the servicesManager. But this is not the context.
var realHostContext = hostcontext.get_context()
This is the context. With using this realHostContext in the creation of servicesManager I don't get an error.
var servicesManager = SP.WorkflowServices.WorkflowServicesManager.newObject(realHostContext,realHostContext.get_web()); context.load(servicesManager);//context is still SP.ClientContext.get_current();
There is no error, but I can't create the subs object.
var subs =servicesManager.getWorkflowSubscriptionService().enumerateSubscriptionsByList(list.get_id()); context.load(subs);
After this part I want to call the context.executeQueryAsync Function which throws an error:
Unhandled exception at line 105, column 44 in http://app-d9bb496fd62ef0.dev.local:10000/Sharepoint2013TMAApp/Scripts/WorkflowLib.js
0x800a139e - JavaScript runtime error: Error with Start workflow Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. "GetWorkflowSubscriptionService
new Microsoft.SharePoint.WorkflowServices.WorkflowServicesManager()
"
Update
MSDN Link the last Paragraph is exactly what I need. Access the Workflow of the parent web via app. But If you click on the Link:
You can locate the sample code here: SharePoint 2013 workflow: Workflow OM in a SharePoint app.
There is no code or sample or just a description. Empty Link :'(
Update
I got a quote of MSDN:
Workflows: Workflows in SharePoint 2013 use the Windows Azure-hosted workflow runtime that is new in SharePoint 2013. Coded workflows that use the SharePoint-hosted workflow runtime cannot be included in a app for SharePoint. Only declarative workflows or workflows that use the newer runtime are allowed.
Is this releant for me? I'm not sure. I created the Workflow with Visual Studio in a Solution and uploaded it to the HostWeb (Site Collection). In the Solution I have an App which needs to get to its HostWeb/Parent Web and to this Workflow to run it. Is this possible, concerning the quote?
Update
I've tested to get any subscriptions from my servicesManager.
But I get the Error:
Unhandled exception at line 140, column 8 in http://app-d9bb496fd62ef4.dev.local:10000/Sharepoint2013TMAApp/Scripts/WorkflowLib.js
0x800a139e - JavaScript runtime error: Error occured! Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. "GetWorkflowSubscriptionService
new Microsoft.SharePoint.WorkflowServices.WorkflowServicesManager()
"
Stack trace: at Microsoft.SharePoint.Client.ClientMethodsProcessor.ThrowNullReference(String objectStackTrace)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.GetObjectFromObjectPath(XmlElement xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.GetObjectFromObjectPathId(String objectPathId)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessInstantiateObjectPath(XmlElement xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessOne(XmlElement xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessStatements(XmlNode xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.Process()
The whole testWorkflow-Code is the following:
function testWorkflow() {
var context = SP.ClientContext.get_current();
var web = context.get_web();
context.load(web);
/*var list = web.get_lists().getById(listGuid);
context.load(list);
var items = list.getItems(SP.CamlQuery.createAllItemsQuery());
context.load(items);*/
var servicesManager = SP.WorkflowServices.WorkflowServicesManager.newObject(context, web);
context.load(servicesManager);
var subs =
servicesManager.getWorkflowSubscriptionService().enumerateSubscriptions();
context.load(subs);
context.executeQueryAsync(function (sender, args) {
var subsEnum = subs.getEnumerator();
while (subsEnum.moveNext()) {
var sub = subsEnum.get_current();
console.log('Web: ' + web.get_url() + ', Subscription: ' +
sub.get_name() + ', id: ' + sub.get_id());
}
}, errFunc);
function errFunc(sender, args) {
throw "Error occured! " + args.get_message() +
'\r\nStack trace: ' + args.get_stackTrace();
}
}
Update
Well, long time no hear. I've been searching for getting this thing to work for a while now. And I'm getting forward. Very very little steps, but I'm close to solve it.
After a while of struggeling, espacially with the Workflow Services Manager, I thought:
Maybe it's not my fault.
I'm new to SharePoint and my experience right now is mostly in developing. So I heard about the Workflow Manager 1.0, the Service Bus etc. And I found out a way to check if the Workflow Service is connected to the SharePoint Farm.
Go to your Central Administration -> Application Management -> Manage service applications -> Workflow Service Application Proxy.
So in my case the Workflow Manager was not connected, neither configured correctly. I had to reinstall the Service Bus and reconfigure the Workflow Service. After installing, configuring and registering everything the servicesManager used in the JavaScript worked.
So now I can access the Workflows in an App via JSOM.
This is a huge step, and if you have the same problems, check if your Workflow Service is registered and installed correctly.
But it is not solving my problem.
In my case, I have a Workflow in a List. The List is in the Hostweb of the App. So I need to get the workflow which is not in the context of the app.
I'm working on it. I have some ideas but everything I tried didn't work. Maybe you have some idea?
Solution Update
And again, an update.
Well, I've done wrong a lot of stuff in my process to get workflows to work with SharePoint via JSOM.
At this point, I got the Workflow Manager Service and the Service Bus working, so I'm able to use the relevant objects in my code. But I didn't get acces to the Workflows I already have. This is because these Workflows are imported Workflows from SharePoint 2010.
You have to reprogram these Workflows to 2013 Workflows to get them via code (WorkflowServicesManager-class)
So a little summary.
If you want to get access to Workflows of the Host-Web with JSOM
- Be sure your Workflow Manager and Service Bus is installed correctly and is connected to your SharePoint Server
- Use the WorkflowServicesManager in your code to get access to the Workflows
- Make sure, the Workflow you are using is a SharePoint 2013 Workflow
And, just a thing you have to do, but is not that simple to figure out:
var servicesManager = SP.WorkflowServices.WorkflowServicesManager.newObject(context,web);
The Context has to be the App context. So it has to be SP.ClientContext.get_current()
The Web has to be the Web of which you want to get the Workflows. So in this case is has to be hostWebContext.get_web()
If you do everything above, you'll get access to Workflows in your HostWeb.
Pheew.... long journey.
I hope this'll help you guys in the future, if you face the same problems.