Hi community,

I’m working on a custom web service in Creatio that connects to an external PostgreSQL database deployed on Neon. My goal is to query data from this external database, acting like a custom ORM. However, I’m running into an issue with using the Npgsql package inside Creatio’s source code.

 

I’ve added the necessary references, but I keep getting the following error:

The type or namespace name 'Npgsql' could not be found (are you missing a using directive or an assembly reference?)

 

I’ve already added the Npgsql.dll to the Terrasoft.web/bin folder and modified the web.config to include a binding redirect for Npgsql. After restarting the IIS server and flushing Redis, I now get a 'System.Data.Common' assembly error.

Here’s the code I’m using:

using Npgsql;
using System;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
using System.Data;
using System.Collections.Generic;
using Terrasoft.Core;
using Terrasoft.Web.Common;
 
namespace Terrasoft.Configuration
{
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class PostgresService : BaseService
    {
        private string connectionString;
 
        public PostgresService()
        {
            // PostgreSQL connection string
            connectionString = "Host=your_host;Port=5432;Database=your_database;Username=your_username;Password=your_password";
        }
 
        [OperationContract]
        [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "GetData")]
        public List<Dictionary<string, object>> GetData()
        {
            var result = new List<Dictionary<string, object>>();
            try
            {
                using (var connection = new NpgsqlConnection(connectionString))
                {
                    connection.Open();
                    string sql = "SELECT * FROM users LIMIT 100";
 
                    using (var cmd = new NpgsqlCommand(sql, connection))
                    using (var reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            var row = new Dictionary<string, object>();
                            for (int i = 0; i < reader.FieldCount; i++)
                            {
                                row.Add(reader.GetName(i), reader.GetValue(i));
                            }
                            result.Add(row);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"Error retrieving data: {ex.Message}");
            }
 
            return result;
        }
 
 
 
    }
}

 

Like 1

Like

1 comments

Hello,

 

Please revert all the changes and perform the setup in the following manner:

 

  1. 1) Deploy another website that will be used as a mediator between the custom PostgreSQL database and your local Creatio app.
  2. 2) Create an endpoint in this separate server that can be accessed either via POST\GET request and that can receive some parameters in the request body.
  3. 3) Create a code in this separate server that will communicate with the custom PostgreSQL server in some method (that will be used as an endpoint to be called).
  4. 4) Call this endpoint from the webservice in local Creatio app and get data from the database as a JSON string and then process it as you need in the local Creatio app.
Show all comments

Hello Creatio Community,

I am working on a project where I need to either replace or override an existing Creatio web service with a custom implementation. Specifically, I want to extend or modify the functionality of a base Creatio web service (e.g., CallServiceSchemaService) to fit my business requirements.

Here’s what I want to achieve:

  • Create a custom web service in a separate package without affecting the existing functionality of the base service.
  • Either extend the existing service (if possible) or completely replace it with my custom implementation.
  • I want to customize the behavior of how service requests and responses are handled, while ensuring that all references to the original service use my new service.

Questions:

  1. What is the best approach to achieve this in Creatio? Should I extend or replace the service, and what are the steps to do so?
  2. How can I ensure that the system references my custom service in place of the base service without breaking existing functionality?
  3. Are there any best practices or limitations I should keep in mind when implementing custom web services in Creatio?

I would appreciate any guidance, examples, or documentation that can help me with this process.

Thank you!

Like 0

Like

1 comments
Best reply

Hi,

 

We would recommend not to redo the standard web service page, but to set up a custom service.

Here are the options for configuring the integration:

https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platform/architecture/development-in-creatio/integrations

Hi,

 

We would recommend not to redo the standard web service page, but to set up a custom service.

Here are the options for configuring the integration:

https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platform/architecture/development-in-creatio/integrations

Show all comments

Hi Creatio Community,

I am working on extending the existing implementation of the Execute method in the web service designer, which is part of a base package in Creatio. My goal is to modify the method to add additional functionality: specifically, I want to save the web service response as a record using an EntitySchemaQuery (ESQ), so that the response can be displayed in a custom section inside Creatio.

However, I am encountering a compilation error:

Error:
cannot convert from 'System.Collections.Generic.IEnumerable<Terrasoft.Configuration.ServiceSchemaParameter>' to 'System.Collections.Generic.IEnumerable<Terrasoft.Configuration.ServiceSchema.ServiceSchemaParameter>'

It appears that the system is having difficulty converting between two types that have the same name but are possibly from different namespaces. I am using ServiceSchemaParameter in my custom implementation, but the IServiceSchemaClient.Execute() method is expecting the parameter to be of a slightly different type.

Here’s an overview of my approach:

  1. I've modified the Execute method to include an ESQ that logs the web service call and stores the response.
  2. The issue arises when passing the parameters (of type List<ServiceSchemaParameter>) to the Execute method, where it's expecting IEnumerable<ServiceSchema.ServiceSchemaParameter>.
  3. I believe the conflict is due to namespace ambiguity or mismatched types between base and custom implementations.

    My code: 
     
  4. namespace Terrasoft.Configuration
    {
     
     
        using System;
        using System.Linq;
        using System.Collections.Generic;
        using System.Runtime.Serialization;
        using System.ServiceModel;
        using System.ServiceModel.Web;
        using System.ServiceModel.Activation;
        using Terrasoft.Core.Factories;
        using Terrasoft.Services;
        using Terrasoft.Web.Common;
        using Terrasoft.Core;
        using Terrasoft.Core.Entities;
        using Terrasoft.Configuration.ServiceSchema;
     
    	#region Class: CallServiceSchemaService
     
    	[ServiceContract]
    	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    	public class CallServiceSchemaService : BaseService
    	{
    		#region Methods: Public
     
    		[OperationContract]
    		[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
    			ResponseFormat = WebMessageFormat.Json)]
    		public CallServiceSchemaResponse Execute(string serviceName, string methodName, List<ServiceSchemaParameter> parameters) {
    			if (parameters == null) {
    				parameters = new List<ServiceSchemaParameter>();
    			}
    			try {
    				UserConnection.DBSecurityEngine.CheckCanExecuteOperation("CanManageSolution");
     
    				// Getting the builder and client from the ClassFactory
    				var builder = ClassFactory.Get<IServiceSchemaParameterBuilder>();
    				var serviceSchemaClient = ClassFactory.Get<IServiceSchemaClient>();
     
    				// No need to cast, List<T> already implements IEnumerable<T>
    				var serviceResponse = serviceSchemaClient.Execute(UserConnection, serviceName, methodName, builder.Build(parameters.AsEnumerable()));
     
    				// Log the request and response
    				LogWebServiceCall(serviceName, methodName, parameters, serviceResponse);
     
    				return new CallServiceSchemaResponse(serviceResponse);
    			} catch (Exception e) {
    				return new CallServiceSchemaResponse(e);
    			}
    		}
     
    		#endregion
     
    		private void LogWebServiceCall(string serviceName, string methodName, List<ServiceSchemaParameter> parameters,
                IServiceClientResponse response = null, Exception error = null) {
                var entitySchema = UserConnection.EntitySchemaManager.GetInstanceByName("UsrWebServiceLog");
                var assignersEntity = entitySchema.CreateEntity(UserConnection);
                assignersEntity.SetDefColumnValues();
     
                assignersEntity.SetColumnValue("UsrServiceName", serviceName);
                assignersEntity.SetColumnValue("UsrMethodName", methodName);
                // Log additional columns if needed, as seen in your commented code
                assignersEntity.Save();
            }
     
    	}
     
    	#endregion
     
    	#region Class: CallServiceSchemaResponse
     
    	[DataContract(Name = "CallServiceSchemaResponse")]
    	public class CallServiceSchemaResponse : ConfigurationServiceResponse
    	{
    		#region Constructor: public
     
    		public CallServiceSchemaResponse(IServiceClientResponse serviceResponse) {
    			StatusCode = serviceResponse.StatusCode;
    			Success = serviceResponse.Success;
    			ResponseBody = serviceResponse.Body;
    			ResponseRawData = serviceResponse.RawDataResponse;
    			RequestBody = serviceResponse.RequestBody;
    			RequestRawData = serviceResponse.RawDataRequest;
    			ParameterValues = Newtonsoft.Json.JsonConvert.SerializeObject(serviceResponse.ParameterValues);
    		}
     
    		public CallServiceSchemaResponse(Exception e) : base(e) {}
     
    		#endregion
     
    		#region Properties: Public
     
    		[DataMember]
    		public int StatusCode;
     
    		[DataMember]
    		public string ParameterValues;
     
    		[DataMember]
    		public string RequestRawData;
     
    		[DataMember]
    		public string RequestBody;
     
    		[DataMember]
    		public string ResponseRawData;
     
    		[DataMember]
    		public string ResponseBody;
     
    		#endregion
    	}
     
    	#endregion
     
    	#region Class: ServiceSchemaParameter
     
    	[DataContract]
    	public class ServiceSchemaParameter
    	{
    		#region Properties: Internal
     
    		[DataMember(Name = "code")]
    		public string Code;
     
    		[DataMember(Name = "value")]
    		public object Value;
     
    		[DataMember(Name = "nested")]
    		public List<List<ServiceSchemaParameter>> NestedParameters;
     
    		#endregion
    	}
     
    	#endregion
    }

 

Request:
Could anyone guide me on how to properly resolve this type conversion issue? If there is a better way to manage the namespace or cast the types correctly, I would appreciate any advice or best practices to ensure compatibility between the types.

Thank you for your help!

Code Context:
CallServiceSchemaService.svc 
Service Designer Package

Looking forward to your suggestions and insights!

Like 2

Like

1 comments

Hello Pranshu Basak,

Please change the part of the code 

var serviceResponse = serviceSchemaClient.Execute(UserConnection, serviceName, methodName, builder.Build(parameters.AsEnumerable()));

to the new one:

var serviceResponse = serviceSchemaClient.Execute(UserConnection, serviceName, methodName, builder.Build((IEnumerable&lt;ServiceSchema.ServiceSchemaParameter&gt;)parameters.AsEnumerable()));

for solving the compilation error.

 

Show all comments

Hi All, I have setup a web service in Creatio that is working fine when I send parameters with data.

 

Sometimes I gonna call thie web service without all the parameters on the query, just one or more, it will depends on othe step before.

 

Is there a way to have a web service set up in Creatio with all parameters, but only make the call using the parameters that are not null?

Like 1

Like

3 comments

Hello!

 

It depends on whether the parameters with NULL values are required or not.

 

You can try leaving out the NULL parameters and see how the service responds. If the call fails with an error, then you'll need to include those parameters.

 

Let us know if you need further assistance!

If the API you're calling is picky about the parameters being included without values, you can add the same service method twice, once with the params, and one without. Then just call one or the other based on the needs.

Thanks for the replies, would be nice to have a way to disable a parameter, for situations like this.
For thie particular API I´m calling there are about 10 parameters available, and the way Creatio is doing, it´s sending all (query) parameters, even though its value is empty.
I´m trying to find a work around or a way to call this API sending only the required data.

Show all comments

Hello,

 

I am trying to automate the gathering of data using some business process that perform API calls to one of our client private APIs. I have defined the WebServices with no problem like the one from this example:

 

 

And sending the test request with a valid API Key and Authorization token works perfectly. However, if I try to group all of this inside a business process I get an error that I don't know how to solve. This is the business process:

 

 

And the error that I get exactly on the web service call is this one:

 

 

The full error message states:

Terrasoft.Common.UnsupportedTypeException: Type "System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" is not supported.

 

I have done some tests and I can confirm that the error only appears when I try to use a the valid Authorization token retrieved previously, and if I set any other value in that Web Service parameter I don't get the error but obviously the call fails because I am using and incorrect token.

 

The length of the token is 299 characters and as it is an authorization token, it must be preceded by the word "Bearer", so the full value that I am passing to that parameter is "Bearer " with a total length of 306 characters. I also tested using some random strings of length 500+ and the error doesn't show up, so it is not related to a limit of the parameter length. I also checked that the token I am passing is 'correct', i.e. no breaklines, weird characters (not UTF-8) or anything that could cause problems with the encoding of the string.

 

Therefore, I guess it is something related to the way Creatio builds the API request from inside the process, that is not the same as doing from a test request inside the Web Service...

 

Your help is highly appreciated.

Regards.

Like 0

Like

2 comments

Note: I have not tried yet to perform the same kind of requests inside a business process to another API (like a public one), but the error I am getting is not related to the API I am using, it must something related to the Creatio business process logic when invoking web services methods, regardless of the endpoint and the API specifications.

Hello,

 

I recommend that you create a support request.

Show all comments

Hi,

I'm trying to pass the result of below "json" (in script task),

var schema = UserConnection.EntitySchemaManager.GetInstanceByName("Account");

    var entity = schema.CreateEntity(UserConnection);

    entity.FetchFromDB(id);

    json = Terrasoft.Core.Entities.Entity.SerializeToJson(entity);

 

to a process parameter and that process parameter needs to be passed to web service element as an request object. Since, the structure of "json" variable might vary, how to send this to a process parameter and eventually to web service element?

 

Any suggestions would be appreciated. Thanks.

Like 2

Like

5 comments

public bool FetchFromDB(object keyValue, bool useDisplayValues = true)

All the `FetchFromDB` methods return a bool, you could test the call.

SerializeToJson(Entity)

Should work.

 

I've had a great deal of trouble with JSON in Creatio in the past.   What's the error you're getting?

Hi Gareth,

Thanks for your reply.

Is there a sample as how this can be sent to webservice element? Use case is to handle this as an object while sending it to webservice element and not as a string. For example, the request at the web service element should look like below.

{

"objectName" : "Contact",

"Payload" : { "Name" : "Halludeen", "Age" : 24 }

}

But, if I pass it as a string then it looks like,

{

"requestJson" : "{\r\n \"ObjectName\": \"Contact\", \r\n \"Payload\": { \"Name\" : \"Halludeen\"}"

}

 

Let me know if you have any suggestions for this.

 

Thanks again.

 

 

 

Halludeen,

The only JSON library I have been able to get to work in Creatio is 

`System.Text.Json.JsonSerializer`.  You have to call it with the full namespace rather than add the namespace in a `using` statement, see here.

 

You could use the `Serialize<TValue>(TValue, JsonSerializerOptions)` method.  The technique is essentially the reverse of the example linked to above, create an object for the deserialised JSON in a module (see example), add the namespace to your process, create an object with the data you want to serialise, and serialise it using the above method into a string.  Hopefully that will work!

Gareth Osler,

Having said the above, I wrote in June,

By way of an epilogue, while the `System.Text.Json` namespace is available in a trial, for some reason it was not available in the dev environment I was using.  However classes in the `Terrasoft.Common.Json` namespace were available.  I was able to use the `Deserialize<T>(String)` method of the Json class.  (Note at the time of writing the `DeserializeDictionary(String)` method has a bug in it and cannot be used.)

You may have to use the above class to do the same.

Show all comments

Hello team,

I have exposed an endpoint, but keep recieveing the 404 (Endpoint not found) when i call it from postman.

I have followed: https://academy.creatio.com/docs/developer/getting_started/develop_appl…

Is there any other prior configurations that need to be done in order to recieve a status 200?

Thank you

Sasori

Like 0

Like

3 comments
Best reply

Hello,

 

404 error means that there is no issue with the authorization or with the request type (GET\POST etc), it means that the endpoint you are calling doesn't exist (either because the link is not valid or because there is nothing behind this link). Also please try configuring the service as it's described here.

PS:

I am able to login. I recieve a status 200 when calling 

ServiceModel/AuthService.svc/Login.

I copy the generated BPMCSRF and place it to the Headers of the Custom web-service. But i keep recieving status 404

Hello,

 

404 error means that there is no issue with the authorization or with the request type (GET\POST etc), it means that the endpoint you are calling doesn't exist (either because the link is not valid or because there is nothing behind this link). Also please try configuring the service as it's described here.

Thank you for you advice Oleg. Issue was resolved

Show all comments

Hi,

 

I have begun playing with the web service integration capabilities within a process to send a message to a Teams channel. Obviously many use cases exist for having a message sent to a Team channel.

 

I have been able to successfully send a message to a channel, however I am having issues in managing the formatting of the message, so a clear title, and message body structure can be provided. Has anyone got any integration working with Teams that would be prepared to share how the web service, variables etc. are configured to allow formatted messages to be sent?

 

Thanks in advance.

Like 0

Like

6 comments

no one has?

 

Any guidance would be appreciated

Mark Roberts,



Could you please share how the implementation is done currently?

Also, have you tried about the content using <HTML>







BR,

Bhoobalan Palanivelu

 

Bhoobalan Palanivelu writes:

Mark Roberts,

Could you please share how the implementation is done currently?

Also, have you tried about the content using <HTML>

BR,

Bhoobalan Palanivelu

 

hi Mark Roberts,



Using the Content type as HTML  depicted below.

GraphServiceClient graphClient = new GraphServiceClient( authProvider );
 
var chatMessage = new ChatMessage
{
	Body = new ItemBody
	{
		ContentType = BodyType.Html,
		Content = "{\r\n  \"title\": \"This is an example of posting a card\",\r\n  \"subtitle\": \"&lt;h3&gt;This is the subtitle&lt;/h3&gt;\",\r\n  \"text\": \"Here is some body text. &lt;br&gt;\\r\\nAnd a &lt;a href=\\\"http://microsoft.com/\\\"&gt;hyperlink&lt;/a&gt;. &lt;br&gt;\\r\\nAnd below that is some buttons:\",\r\n  \"buttons\": [\r\n    {\r\n      \"type\": \"messageBack\",\r\n      \"title\": \"Login to FakeBot\",\r\n      \"text\": \"login\",\r\n      \"displayText\": \"login\",\r\n      \"value\": \"login\"\r\n    }\r\n  ]\r\n}",	}
};
 
await graphClient.Teams["{team-id}"].Channels["{channel-id}"].Messages
	.Request()
	.AddAsync(chatMessage);





BR,

Bhoobalan Palanivelu.

Bhoobalan Palanivelu,

Hi

 

Thanks for your reply. This is what I have done so far:

 

1. Created a new Web Service entry

2. Configured a single Method and populated top fields. I know this is correct as I can successful send a test request with just a single parameter line and it was received and displayed in my Teams channel

3. The issue I have is with the configuration of the Parameters, for which all but contentType I assume are Body parameters. The following screenshot is me playing with various structures and content entries, but I cannot get anything working :/

 

 

I am trying to send a message in a form similar to the following:

 

https://adaptivecards.io/samples/ActivityUpdate.html

 

I feel I am missing something straightforward in how this should be built within the Creatio Web Service definition, but the docs are not helping find it.

 

thanks

 

Mark

did you ever get this working?

keith schmitt,

No, I have been distracted with other things, so not got back to this. This would be a great blog for someone to write up and share!

Show all comments

Hi all

I have created a web service that accepts values from a third party server. Next, I need to transfer one value from the request to the section field.

Question:

How do I call my finished web service in C#?

Like 0

Like

4 comments

Hi,

Are you talking about a service created in the configuration or in the "Web services" section?

Dmytro Vovchenko, in the web services section

 

the question is how to set up its call in c#, so that in the future to use its result in one of the fields of the section

 

Alexandr Bezbozhnov,

As far as I know, currently, there is no direct way of running this sort of web service from code. However, you can run it inside a business process and you can run this process inside C# code using

ProcessEngineService.svc, with it you even can get the result values of the process.

Show all comments

Hello all,

 

I am trying to enable access for a portal user to trigger a service within Creatio. I'm following the steps as listed in this academy page but when I try to declare _baseService and publish, I receive an error saying that GlbInterviewService is "'GlbInterviewService' is a namespace but is used like a type"

 

namespace Terrasoft.Configuration.KeenGlbInterviewService
{
	using System;
	using System.IO;
	using System.Collections.Specialized;
	using System.Globalization;
	using System.Runtime;
	using System.Runtime.Serialization;
	using System.ServiceModel;
	using System.ServiceModel.Web;
	using System.ServiceModel.Activation;
	using System.Threading;
	using System.Threading.Tasks;
	using System.Web;
	using Terrasoft.Core;
	using Terrasoft.Core.Factories;
	using Terrasoft.Web.Common;
    using Terrasoft.Web.Common.ServiceRouting;
 
	#region Class: KeenGlbInterviewService
 
	[DefaultServiceRoute, SspServiceRoute]
	[ServiceContract]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
	public class KeenGlbInterviewService : BaseService
	{
 
		#region Methods: Public
		private static readonly GlbInterviewService _baseService = new GlbInterviewService();
 
		[OperationContract]
		[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
		public InterviewServiceResponse Start(InterviewServiceRequest request)
		{
			return _baseService.Start(request); 
		}
 
		[OperationContract]
		[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
		public InterviewServiceResponse Complete(InterviewServiceRequest request)
		{
			return _baseService.Complete(request);
		}
 
		#endregion
 
	}
 
	#endregion
 
	#region DataContract
 
	[DataContract]
	public class InterviewServiceResponse : ConfigurationServiceResponse
	{
		[DataMember(Name = "isSuccess")]
		public bool IsSuccess {get; set;}
	}
 
	[DataContract]
	public class InterviewServiceRequest
	{
		[DataMember(Name = "interviewId")]
		public Guid InterviewId { get; set; }
	}
 
	#endregion
 
}

From what I can tell I've set everything up exactly as the article says but I still receive the error. Though they declare _baseService the same way. Any suggestions as to what I could be doing wrong?

Like 0

Like

3 comments
Best reply

Kevin Brady,

 

Ok, according to the error you should have the Terrasoft.Configuration.GlbInterviewService namespace in your system, but you try to create a new method that has the same name as the namespace (as well as your current class KeenGlbInterviewService has the same name as your namespace Terrasoft.Configuration.KeenGlbInterviewService). So theoretically adding "using Terrasoft.Configuration.GlbInterviewService" to your code should fix this issue, but still you need to rename either classes or namespaces since they shouldn't have the same name.

Hello Kevin,

 

I used the same exact code and created a source code in my local app and it didn't return error messages. Try recreating it and also check if the error message is returned from the source code you've shared.

Oleg Drobina,

I recreated the code and also tried pasting the above code directly back into Creatio to ensure that there weren't any changes that occurred in creating this post and I still received the error.

Kevin Brady,

 

Ok, according to the error you should have the Terrasoft.Configuration.GlbInterviewService namespace in your system, but you try to create a new method that has the same name as the namespace (as well as your current class KeenGlbInterviewService has the same name as your namespace Terrasoft.Configuration.KeenGlbInterviewService). So theoretically adding "using Terrasoft.Configuration.GlbInterviewService" to your code should fix this issue, but still you need to rename either classes or namespaces since they shouldn't have the same name.

Show all comments