The REST services are self documenting, just follow the basic documentation, they will guide you to the API page, and then the documentation for each method call is directly in the page.
I agree that REST is probably a better option. You can use SOAP services, but they have some particularities that make them tricky to use without issue. In particular with the opening and closing of sessions (so you don’t keep sessions opened using up licenses), and certificate validation.
The advantage of SOAP services is the strong typing and intellisense support you get in Visual Studio, and in some cases SOAP services can offer better performance. If you enable compression in your REST requests however (Accept-Encoding: gzip,deflate) performance is pretty much on par. REST plays best with JSON and javascript, but it’s still reasonably straightforward in C# with JSON.NET… You can also make your REST requests so that the server returns XML, if you prefer working with Linq to XML axes (Accept: application/atom+xml)…
Here are the helper classes I use to connect to the SOAP services without these issues:
using ECS.SessionModSvcRef;
using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace ECS
{
public class EpicorSession
{
private readonly string _username;
private readonly string _password;
private SessionModSvcContractClient _session;
private string _companyId;
private string _plantId;
private string _plantName;
private string _workstationId;
private string _workstationDesc;
private string _employeeId;
private string _countryGroupCode;
private string _countryCode;
private string _tenantId;
public Guid SessionId { get; private set; } = Guid.Empty;
public string CompanyId
{
get { return _companyId; }
set
{
_companyId = value;
_session.SetCompany(_companyId,
out _plantId,
out _plantName,
out _workstationId,
out _workstationDesc,
out _employeeId,
out _countryGroupCode,
out _countryCode,
out _tenantId);
}
}
public string PlantId { get { return _plantId; } }
public string PlantName { get { return _plantName; } }
public string WorkstationId { get { return _workstationId; } }
public string WorkstationDesc { get { return _workstationDesc; } }
public string EmployeeId { get { return _employeeId; } }
public string CountryGroupCode { get { return _countryGroupCode; } }
public string CountryCode { get { return _countryCode; } }
public string TenantId { get { return _tenantId; } }
public EpicorSession(string username, string password)
{
// Disable certificate validation. Necessary for self-signed certs and speeds up calls.
System.Net.ServicePointManager.ServerCertificateValidationCallback =
delegate (object thesender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ return true; };
_username = username;
_password = password;
_session = GetClient<SessionModSvcContractClient, SessionModSvcContract>();
SessionId = _session.Login();
// Create a new instance of the SessionModSvc. Do this because when you call any method on the service
// client class, you cannot modify its Endpointbehaviors, and if a HookServiceBehavior is not present
// when calling Logout, the call fails with a NullReferenceException, and the session stays opened on
// the server.
_session = GetClient<SessionModSvcContractClient, SessionModSvcContract>();
}
public void Logout()
{
if (SessionId != Guid.Empty)
{
_session.Logout();
SessionId = Guid.Empty;
}
}
public TClient GetClient<TClient, TInterface>()
where TClient : ClientBase<TInterface>
where TInterface : class
{
var client = Activator.CreateInstance<TClient>();
client.ClientCredentials.UserName.UserName = _username;
client.ClientCredentials.UserName.Password = _password;
if (SessionId != Guid.Empty) client.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(SessionId, _username));
return client;
}
}
class CustomMessageInspector : IClientMessageInspector
{
private Guid _sessionId;
private string _epicorUserId;
public CustomMessageInspector(Guid SessionId, string EpicorUserId)
{
_sessionId = SessionId;
_epicorUserId = EpicorUserId;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if (_sessionId != null && _sessionId != Guid.Empty)
{
var sessionHeader = new SessionInfoHeader() { SessionId = _sessionId, EpicorUserId = _epicorUserId };
request.Headers.Add(sessionHeader);
}
return request;
}
}
class HookServiceBehavior : IEndpointBehavior
{
private Guid _sessionId;
private string _epicorUserId;
public HookServiceBehavior(Guid SessionId, string EpicorUserId)
{
_sessionId = SessionId;
_epicorUserId = EpicorUserId;
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new CustomMessageInspector(_sessionId, _epicorUserId));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
class SessionInfoHeader : MessageHeader
{
protected override void OnWriteHeaderContents(System.Xml.XmlDictionaryWriter writer, MessageVersion messageVersion)
{
writer.WriteElementString("SessionID", @"http://schemas.datacontract.org/2004/07/Epicor.Hosting", SessionId.ToString());
writer.WriteElementString("UserID", @"http://schemas.datacontract.org/2004/07/Epicor.Hosting", EpicorUserId);
}
public override string Name
{
get { return "SessionInfo"; }
}
public override string Namespace
{
get { return "urn:epic:headers:SessionInfo"; }
}
public Guid SessionId { get; set; }
public string EpicorUserId { get; set; }
}
}
And the binding configuration:
<basicHttpBinding>
<binding name="BasicHttpBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
<security mode="TransportWithMessageCredential" />
</binding>
</basicHttpBinding>