Kevin, hopefully one last issue… I installed RestSharp 110.2.0 in my project and used the example from the link above to code a POST call to my Epicor function. Below is the code I created and a Swagger page showing the function call I’m trying to make. The function call works fine in Swagger, however it’s failing without any error when calling from the RestSharp code. Do I need to deserialize the argument data in the request to call the function, or is there something else I have screwed up?
private static void CallPostFunction()
{
try
{
var options = new RestClientOptions(Properties.Settings.Default.AppServerURL);
options.Authenticator = new HttpBasicAuthenticator(Properties.Settings.Default.BatchEntryPerson, Properties.Settings.Default.BatchEntryPass);
var client = new RestClient(options);
var request = new RestRequest();
request.AddHeader("Accept", "application/json");
request.AddHeader("X-API-Key", Properties.Settings.Default.APIKey);
request.Method = Method.Post;
string RequestContent = "\"GroupID\":" + $@"{BatchGroupID}";
request.AddParameter("application/json", RequestContent, ParameterType.RequestBody);
var response = client.Execute(request);
}
catch (Exception e)
{
throw new Exception("REST Call", e);
}
}
Kevin, I built the JSON object and serialized it like you said, then ran my debug. However, when I try to execute the POST call to the server I’m getting the following error:
The SSL connection could not be established. See inner exception for details.
Name Value Type
▶ InnerException {"The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot"} System.Exception {System.Security.Authentication.AuthenticationException}
at System.Net.Http.ConnectHelper.<EstablishSslConnectionAsync>d__2.MoveNext() at System.Threading.Tasks.ValueTask`1.get_Result() at System.Net.Http.HttpConnectionPool.<ConnectAsync>d__100.MoveNext() at System.Threading.Tasks.ValueTask`1.get_Result() at System.Net.Http.HttpConnectionPool.<CreateHttp11ConnectionAsync>d__102.MoveNext() at System.Threading.Tasks.ValueTask`1.get_Result() at System.Net.Http.HttpConnectionPool.<AddHttp11ConnectionAsync>d__76.MoveNext() at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.<WaitWithCancellationAsync>d__1.MoveNext() at System.Threading.Tasks.ValueTask`1.get_Result() at System.Net.Http.HttpConnectionPool.HttpConnectionWaiter`1.<WaitForConnectionAsync>d__5.MoveNext() at System.Net.Http.HttpConnectionPool.<SendWithVersionDetectionAndRetryAsync>d__86.MoveNext() at System.Threading.Tasks.ValueTask`1.get_Result() at System.Net.Http.RedirectHandler.<SendAsync>d__4.MoveNext() at System.Threading.Tasks.ValueTask`1.get_Result() at System.Net.Http.DecompressionHandler.<SendAsync>d__16.MoveNext() at System.Net.Http.HttpClient.<<SendAsync>g__Core|83_0>d.MoveNext() at RestSharp.RestClient.<ExecuteRequestAsync>d__3.MoveNext()
Couple of questions:
Can I use a self-signed certificate?
Where on the server does it need to be located?
Where in the project do I need to indicate where and what certificate is to be used?
When you installed your appServer, you had the opportunity to choose a certificate or let Kinetic create one for you. You can see these certs in certmgr at the server.
To check binding, use IIS Manager and select bindings:
To automate all of this, you can follow @jgiese.wci and @EarlGrei’s “stupid simple” advice and use a service that generates free certs for you. Or if you want to do it yourself with a little help from Azure (yes, even for on-prem servers) you can read the following. Using real trusted certs just makes life so much more simple.
Kevin, I found a certificate that IIS is using on the server to which I’m issueing the REST call that is not expired. To verify the certificate like you indicated, where would I find the hash value? I have a screenshot of the certificate details below, would it be the Thumbprint or Serial Number value?
Kevin, the code snippet isn’t working, I think due to the version I’m using (110.2.0). VS is saying the RemoteCertificateValidationCallback is under the RestClientOptions class, so I set up the code like this:
var options = new RestClientOptions(Properties.Settings.Default.AppServerURL)
{
Authenticator = new HttpBasicAuthenticator(Properties.Settings.Default.BatchEntryPerson, Properties.Settings.Default.BatchEntryPass)
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
string certHash = "";
certHash = certificate.GetCertHashString(System.Security.Cryptography.HashAlgorithmName.SHA512);
Console.WriteLine(certHash);
}
};
Kevin, I still can’t get the string to display in the console window. The REST still isn’t working either. What do I need to do to put the hash where it’s needed, or to bypass it if I’m checking it myself? I’m not getting any kind of exception in the call. I did find there is a self-signed certificate in the IIS bindings that doesn’t expire until 2031. What am I doing wrong if I can call the function from the REST V2 help page?
Kevin, I just tried the code above in a new project, will not return a certificate hash from the lambda expression. What next? Also wanted to ask if I need to have the certificate from the server installed on my system as well for the call to work…