How can I preserve values between WCF service methods calling?

后端 未结 1 755
暗喜
暗喜 2021-01-24 23:15

I have this WCF Service class:

public partial class OhmioSVC: IOhmioSVC_Security
{
    // Porque no funciona si la variable no es estatica?
    private static Co         


        
相关标签:
1条回答
  • 2021-01-24 23:40

    By default, a WCF service class is instantiated for every new session that is created. For some bindings which do not support sessions, then a "session" spans only a single call, meaning that for two calls from the client (one for Connect, one for GetErrors), there will be two instances of the OhmioSVC class created, which is why if you don't specify the ConnectionBusiness property as static, two of them will be created and you will get the result you see.

    What you need to to tell WCF that you require a session in your service contract. You can do that by adding the SessionMode property in your service contract declaration:

    [ServiceContract(SessionMode = SessionMode.Required)]
    public interface IOhmio_Security
    {
        [OperationContract]
        void Connect(string user, string password, string db);
        [OperationContract]
        List<string> GetErrors();
    }
    

    If you have that, and you use a binding which does not support sessions (e.g., BasicHttpBinding), then your service will fail to open - you then need to change to a binding that supports sessions (e.g., WSHttpBinding). The code below shows an example with sessions that work:

    public class StackOverflow_31541498
    {
        class ConnectionBusiness
        {
            List<string> errors = new List<string>();
            public void ObtenerTicket(string user, string password, string db)
            {
                errors.Add(string.Format("ObtenerTicket called: {0}, {1}, {2}", user, password, db));
            }
            public List<string> MyErrors
            {
                get
                {
                    var result = new List<string>(this.errors);
                    errors.Clear();
                    if (result.Count == 0)
                    {
                        result.Add("No errors!");
                    }
                    return result;
                }
            }
        }
        [ServiceContract(SessionMode = SessionMode.Required)]
        public interface IOhmio_Security
        {
            [OperationContract]
            void Connect(string user, string password, string db);
            [OperationContract]
            List<string> GetErrors();
        }
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
        public class OhmioSVC : IOhmio_Security
        {
            private ConnectionBusiness _conn = new ConnectionBusiness();
            public void Connect(string user, string password, string db)
            {
                _conn.ObtenerTicket(user, password, db);
            }
    
            public List<string> GetErrors()
            {
                return _conn.MyErrors;
            }
        }
        static Binding GetBinding()
        {
            // var result = new BasicHttpBinding(); // This will not work, as it doesn't support sessions
            var result = new WSHttpBinding(); // This will work
            return result;
        }
        public static void Test()
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(typeof(OhmioSVC), new Uri(baseAddress));
            host.AddServiceEndpoint(typeof(IOhmio_Security), GetBinding(), "");
            host.Open();
            Console.WriteLine("Host opened");
    
            var factory = new ChannelFactory<IOhmio_Security>(GetBinding(), new EndpointAddress(baseAddress));
            var proxy = factory.CreateChannel();
    
            proxy.Connect("user", "pwd", "db");
            var errors = proxy.GetErrors();
            Console.WriteLine("Errors:\n   {0}", string.Join("\n   ", errors));
    
            ((IClientChannel)proxy).Close();
            factory.Close();
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }
    

    Another alternative would be to merge the two methods in your scenario - make Connect return the list of errors, this way you don't have to make a separate call to get them, and you won't have to deal with sessions.

    0 讨论(0)
提交回复
热议问题