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