Hello Creatio community !
I would like to call the Creatio Webservice ..../0/rest/FinAppSpecService/InheritSpecificationsForFinApp which automatically populates the Product Terms in Application, inside a Business Process. I can not call it in a c# class because the the constructor of FinAppSpecService class does not accept UserConnection as e parameter. Which is the proper way to solve this problem ?
Like
Hello Petrika,
It's possible if you create a webservice record where the POST method complete address will be {siteURL}/0/rest/FinAppSpecService/InheritSpecificationsForFinApp and in the request parameters specify the following header parameters:
BPMCSRF
ForceUseSession (default value set to true)
Connection (default value set to true)
and the following cookies parameters:
BPMSESSIONID
UserName
BPMLOADER
BPMCSRF
.ASPXAUTH
in the webservice settings (since the FinAppSpecService service is not anonymous). The most difficult part here is setting cookies parameters. I could only recommend the following scenario here:
1) Create a separate authentication service webservice request (to {siteURL}/ServiceModel/AuthService.svc/Login)
2) Specify UserName and UserPassword request body parameters:
3) Add the Set-Cookie response header parameter:
4) Validate the response by performing a test call. It should return the Set-Cookie header that will be then used in the process:
5) Create a separate business process and configure it to run once per hour or once per half a day (depending on the value of the "UserSessionTimeout" system setting). The set-Cookie response header should be parsed to extract values for the
BPMSESSIONID
UserName
BPMLOADER
BPMCSRF
.ASPXAUTH
headers. It can be done by means of the script-task. Extracted values should be set as values for the system settings created separately (one per each header).
6) In your process where you need to call the FinAppSpecService in the "Call webservice" element set the values for the cookie parameters as values from the system settings from step 5. And also specify the value for the BPMCSRF header parameter.
7) Add all other request body parameters and call the service.
This approach should work since we simulate the Postman call of the same service, but set cookie parameters and header parameters via the separate business process and system settings.
Best regards,
Oscar
Hello Petrika,
It's possible if you create a webservice record where the POST method complete address will be {siteURL}/0/rest/FinAppSpecService/InheritSpecificationsForFinApp and in the request parameters specify the following header parameters:
BPMCSRF
ForceUseSession (default value set to true)
Connection (default value set to true)
and the following cookies parameters:
BPMSESSIONID
UserName
BPMLOADER
BPMCSRF
.ASPXAUTH
in the webservice settings (since the FinAppSpecService service is not anonymous). The most difficult part here is setting cookies parameters. I could only recommend the following scenario here:
1) Create a separate authentication service webservice request (to {siteURL}/ServiceModel/AuthService.svc/Login)
2) Specify UserName and UserPassword request body parameters:
3) Add the Set-Cookie response header parameter:
4) Validate the response by performing a test call. It should return the Set-Cookie header that will be then used in the process:
5) Create a separate business process and configure it to run once per hour or once per half a day (depending on the value of the "UserSessionTimeout" system setting). The set-Cookie response header should be parsed to extract values for the
BPMSESSIONID
UserName
BPMLOADER
BPMCSRF
.ASPXAUTH
headers. It can be done by means of the script-task. Extracted values should be set as values for the system settings created separately (one per each header).
6) In your process where you need to call the FinAppSpecService in the "Call webservice" element set the values for the cookie parameters as values from the system settings from step 5. And also specify the value for the BPMCSRF header parameter.
7) Add all other request body parameters and call the service.
This approach should work since we simulate the Postman call of the same service, but set cookie parameters and header parameters via the separate business process and system settings.
Best regards,
Oscar
Thank you very much for you response Oscar. It was very helpful.
Is there any article or example in the academy regarding point 5, parsing set-Cookie response header to extract values (inside a script task) ?
Petrika,
This is the task that should be covered by the C# code, using substring method for example. It's something as if you had a task to substring the "test" word from the "Hello test wordl!" string. Please find the way using the topics as the following:
https://stackoverflow.com/questions/9505400/extract-part-of-a-string-be…
Please also notice that the cookies values length is always constant and all of them start with the cookie name and the "=" character and end with the ";" symbol. This shouldn't be a difficult task.
Once string parts are extracted you can set them as parameter values (here is the Academy article that may be useful) and use these parameters in formulas to set parameter values to correspondent system settings.
Best regards,
Oscar
Oscar Dylan,
BPMSESSIONID is generated in the set-Cookie response header, because it seems that it's not found there ? I managed to extract everything else as required
Petrika,
Sorry, made a little mistake. BPMSESSIONID cookie is not returned as a response to the /AuthService.svc/Login call, but as a result of the first call to any other working endpoint like /0/odata/Account after authentication. Just try it in Postman and check the response headers in the next request that goes after AuthService request.
Best regards,
Oscar
Oscar ,
When i make a request from postman to another web-service the BPMSessionId is generated, I tested it.
Are you suggesting that i put the BPMSESSIONID as a reponse parameter to the InheritSpecificationsForFinApp, not as a request parameter ?
If i understand correctly.
Petrika,
If you're calling a configuration service, there's no need to actually use it as a service. It's simply a C# class that you can use directly.
For example, something like this:
var svc = new Terrasoft.Configuration.FinAppSpecService(); svc.InheritSpecificationsForFinApp()
Depending on how the configuration service is implemented, you might need to also pass a UserConnection to it, which means you'd need to modify the service to allow this to be passed in.
You had mentioned: "I can not call it in a c# class because the the constructor of FinAppSpecService class does not accept UserConnection as e parameter. Which is the proper way to solve this problem?"
Why not just add two constructors to the class? One that is the default constructor and one that accepts a UserConnection? In the class you could add a method that either returns your private UserConnection variable (passed in by code consuming the class directly) or the one from the session (or BaseService) if being used as a service. I do it this way often and it is far more easy to consume the class directly than to call as a service when it's not needed to be used as a service (not to mention the extra overhead of using it as a service rather than consuming it directly)
Ryan
Ryan Farley,
FinAppSpecService() class constructor doesnt allow UserConnection as an argument. I can not modify the FinAppSpecService class because its part of the configuration.
Ryan Farley,
Are you suggesting that i copy the
FinAppSpecService class to my package and make proper modifications to it ?
Petrika,
I was assuming this was your class, that you could modify, not a configuration one that was uneditable by you.
I assume that FinAppSpecService inherits BaseService? If so, it has a UserConnection property that is protected (that does have a setter) as well as a protected constructor that accepts a UserConnection. Since they are protected you should be able to access them if your class is derived from it.
it might work to just make a new class that inherits from the FinAppSpecService that allows a UserConnection to be passed? I've not tried that but it might work - just to throw out some ideas.
Something like this:
public class UsrFinAppSpecServiceWrapper : FinAppSpecService { public void SetUserConnection(UserConnection) { this.UserConnection = UserConnection; } }
Then to use it:
var svc = new Terrasoft.Configuration.UsrFinAppSpecServiceWrapper(); svc.SetUserConnection(UserConnection); svc.InheritSpecificationsForFinApp();
Again, I've not tested/tried that before, but I would assume something like this could work? If it does, still far easier route than calling it as a service IMO.
Ryan
Ryan Farley,
Ryan the response i get from the back-end
is the same as the reponse i get from the front-end
Still When i call this web-service from the back-end my goal isnt achieved. As you can see the detail of product terms isnt automaticalluy generated
Dont know if am missing something here
Thank you Petrika