I have this WCF Service class:
public partial class OhmioSVC: IOhmioSVC_Security
{
// Porque no funciona si la variable no es estatica?
private static ConnectionBusiness _conn = new ConnectionBusiness();
public ConnectionBusiness Conn
{
get
{
return _conn;
}
}
public void Connect(string Usuario, string Password, string DataBase)
{
Conn.ObtenerTicket (Usuario, Password, DataBase);
}
public List<Errores> GetErrors()
{
return Conn.MyErrors;
}
}
As you can see, _conn is defined as static, because I need to preserve his value between calls. If I remove the "static", and call method Connect (creates the _conn object) and then call getErrores _conn variable is for some reason empty.
The problem with this is that if I miss calling "connect" method I whant to throw and exception, but _conn stills get the value from the last call. I know i'm doing something wrong here, but I don't see another alternative. Any Ideas?
Thanks
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.