Help WCF session still in use after logout

Hi

Can anyone see why the licence is not being released?

Thanks

Graeme

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using ConsoleApplication1.Epicor.SessionModSvc;

namespace ConsoleApplication1
{
class Program
{
private enum EndpointBindingType { SOAPHttp, BasicHttp }

    private static WSHttpBinding GetWsHttpBinding()
    {
        var binding = new WSHttpBinding();
        const int maxBindingSize = Int32.MaxValue; binding.MaxReceivedMessageSize = maxBindingSize; binding.ReaderQuotas.MaxDepth = maxBindingSize; binding.ReaderQuotas.MaxStringContentLength = maxBindingSize; binding.ReaderQuotas.MaxArrayLength = maxBindingSize; binding.ReaderQuotas.MaxBytesPerRead = maxBindingSize; binding.ReaderQuotas.MaxNameTableCharCount = maxBindingSize;
        binding.Security.Mode = SecurityMode.Message; binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
        return binding;
    }
    public static BasicHttpBinding GetBasicHttpBinding()
    {
        var binding = new BasicHttpBinding();
        const int maxBindingSize = Int32.MaxValue; binding.MaxReceivedMessageSize = maxBindingSize; binding.ReaderQuotas.MaxDepth = maxBindingSize; binding.ReaderQuotas.MaxStringContentLength = maxBindingSize; binding.ReaderQuotas.MaxArrayLength = maxBindingSize; binding.ReaderQuotas.MaxBytesPerRead = maxBindingSize; binding.ReaderQuotas.MaxNameTableCharCount = maxBindingSize; binding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential; binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
        return binding;
    }

    private static TClient GetClient<TClient, TInterface>(string url, string username, string password, EndpointBindingType bindingType) where TClient : ClientBase<TInterface> where TInterface : class
    {
        Binding binding = null; TClient client;
        var endpointAddress = new EndpointAddress(url);
        switch (bindingType) { case EndpointBindingType.BasicHttp: binding = GetBasicHttpBinding(); break; case EndpointBindingType.SOAPHttp: binding = GetWsHttpBinding(); break; }
        client = (TClient)Activator.CreateInstance(typeof(TClient), binding, endpointAddress);
        if (!string.IsNullOrEmpty(username) && (client.ClientCredentials != null)) { client.ClientCredentials.UserName.UserName = username; client.ClientCredentials.UserName.Password = password; }
        return client;
    }


    static void Main(string[] args)
    {
        ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => { return true; };
          /*EndpointBindingType bindingType = EndpointBindingType.SOAPHttp; */
        EndpointBindingType bindingType = EndpointBindingType.BasicHttp; 
        string epicorUserID = "manager"; string epiorUserPassword = "manager";
        string scheme = "http";
        if (bindingType == EndpointBindingType.BasicHttp)
        { scheme = "https"; }
        UriBuilder builder = new UriBuilder(scheme, "DELL-GRAEME.Aspera.local");
        builder.Path = "E10Demo/Ice/Lib/SessionMod.svc";
        SessionModSvcContractClient sessionModClient = GetClient<SessionModSvcContractClient, SessionModSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);
        /* builder.Path = "ERP100500/Erp/BO/AbcCode.svc"; ConsoleApplication1ContractClient ConsoleApplicationClient = GetClient < ConsoleApplicationSvcContractClient, ConsoleApplicationSvcContract> (builder.Uri.ToString(),          epicorUserID,          epiorUserPassword,          bindingType);
 */
        Guid sessionId = Guid.Empty;
        
        sessionId = sessionModClient.Login();
        builder.Path = "E10Demo/Ice/Lib/SessionMod.svc"; sessionModClient = GetClient < SessionModSvcContractClient, SessionModSvcContract> (builder.Uri.ToString(),epicorUserID,epiorUserPassword,bindingType);
        sessionModClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));
        sessionId = sessionModClient.Login();
        /*    sessionModClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID)); abcCodeClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));

*/
        if (sessionId != Guid.Empty)
        {

                sessionModClient.Logout(); 
           
       
            
          }
       
       
    }
}

}

Check out this thread, I had the same problem, but I wasn’t reading the directions carefully enough

2 Likes

I looks like you call Login 2 times. You need to recreate proxy instead, as Aaron_Moreng says

Hi

Sorry took out the second login. there is no error in 10.1.600 but still leaves the session in the admin console in use.

Havent tried it in 10.1.400 yet.

Graeme

    static void Main(string[] args)
    {
        ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => { return true; };
          /*EndpointBindingType bindingType = EndpointBindingType.SOAPHttp; */
        EndpointBindingType bindingType = EndpointBindingType.BasicHttp; 
        string epicorUserID = "manager"; string epiorUserPassword = "manager";
        string scheme = "http";
        if (bindingType == EndpointBindingType.BasicHttp)
        { scheme = "https"; }
        UriBuilder builder = new UriBuilder(scheme, "DELL-GRAEME.Aspera.local");
        builder.Path = "E10Demo/Ice/Lib/SessionMod.svc";
        SessionModSvcContractClient sessionModClient = GetClient<SessionModSvcContractClient, SessionModSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);
        /* builder.Path = "ERP100500/Erp/BO/AbcCode.svc"; ConsoleApplication1ContractClient ConsoleApplicationClient = GetClient < ConsoleApplicationSvcContractClient, ConsoleApplicationSvcContract> (builder.Uri.ToString(),          epicorUserID,          epiorUserPassword,          bindingType);
 */
        Guid sessionId = Guid.Empty;
        
        sessionId = sessionModClient.Login();
       /* builder.Path = "E10Demo/Ice/Lib/SessionMod.svc"; */
        sessionModClient = GetClient<SessionModSvcContractClient, SessionModSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);
        sessionModClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));
       
        /*    sessionModClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID)); abcCodeClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));

*/
        if (sessionId != Guid.Empty)
        {

                sessionModClient.Logout();
            sessionModClient.Close();
       
            
          }
       
       
    }
}

}

Perhaps completely unrelated but I was seeing similar results with something I was doing - turns out I didn’t pay attention to the colors of the listed users - I had many that I thought were consuming licenses but were inactive sessions.

I think it should look like
static void Main(string[] args)
{
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => { return true; };

    EndpointBindingType bindingType = EndpointBindingType.BasicHttp; 
    string epicorUserID = "manager"; string epiorUserPassword = "manager";
    string scheme = "http";
    if (bindingType == EndpointBindingType.BasicHttp)
    { scheme = "https"; }

    UriBuilder builder = new UriBuilder(scheme, "DELL-GRAEME.Aspera.local");
	builder.Path = "E10Demo/Ice/Lib/SessionMod.svc";
	
    SessionModSvcContractClient sessionModClient = GetClient<SessionModSvcContractClient, SessionModSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);
    Guid sessionId = sessionModClient.Login();

    sessionModClient = GetClient<SessionModSvcContractClient, SessionModSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);
    sessionModClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));

    if (sessionId != Guid.Empty)
    {
        sessionModClient.Logout();
    }
}

}

Its so frustrating. I have the code changed to exactly what you have recommended and still it leaves sessions in the admin console with the licence in use. I run it each time till the max number of licences are used then the program bombs out.

Graeme

I know this is an old thread, but we recently encountered the same problem, and any searches for help turned up this page, but the suggestions provided did not work for us.

Like Graeme, the number of licenses used in the admin console continues to increase until the maximum number of licenses is consumed, and then no one can access Epicor.

In our case, we have a service that runs in the background to automatically process certain transactions. The program runs multiple threads, and every time a new thread is spun up, it consumes a license. The thread uses the SessionModClient.Logout() method call after completing its work, so our thought is that the license should be released in the admin console. Instead, the license remains active in the admin console until it times out after 15 minutes. In the meantime, every other thread our application spins up consumes a new license, which is held for 15 minutes. The result is that every time our application has to process multiple transactions, the maximum license limit is hit and no one can access the system for at least 15 minutes, if not longer.

This is clearly unacceptable.

Fortunately, we have recently stumbled across a solution that I thought would be worth sharing. It appears that the sessionModClient.Logout() method doesn’t do anything (Well, it probably does something, but it clearly doesn’t free up the license in use). But there is another web service that can be called to remove the session and its associated in-use license.

You can use the following codes to remove the in-use license:

AdminSessionSvcContractClient adminSessionClient = GetClient<AdminSessionSvc.AdminSessionSvcContractClient, AdminSessionSvc.AdminSessionSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);

adminSessionClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));

adminSessionClient.DeleteBySessionId(sessionId.ToString());

To integrate this into your own application, just modify the last few lines of your code as follows:

UriBuilder builder = new UriBuilder(scheme, "DELL-GRAEME.Aspera.local");
builder.Path = "E10Demo/Ice/Lib/SessionMod.svc";

SessionModSvcContractClient sessionModClient = GetClient<SessionModSvcContractClient, SessionModSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);

builder.Path = "E10Demo/Ice/BO/AdminSession.svc";
AdminSessionSvcContractClient adminSessionClient = GetClient<AdminSessionSvcContractClient, AdminSessionSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);

Guid sessionId = sessionModClient.Login();

sessionModClient = GetClient<SessionModSvcContractClient, SessionModSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);
sessionModClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));
adminSessionClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));    

if (sessionId != Guid.Empty)
{
    sessionModClient.Logout();
    adminSessionClient.DeleteBySessionId(sessionId.ToString());
}
2 Likes

thanks!