Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create stateful web service in C#?

I have now something like this:

public class Service1 : System.Web.Services.WebService
{
    [WebMethod]
    public string Method1()
    {
        SomeObj so = SomeClass.GetSomeObj(); //this executes very long time, 50s and more
        return so.Method1(); //this exetus in a moment 
    }

    [WebMethod]
    public string Method2()
    {
        SomeObj so = SomeClass.GetSomeObj(); //this executes very long time, 50s and more
        return so.Method2(); //this exetus in a moment 
    }

 ...
}

Is it possible to make stateful web service so that I can reuse SomeObj so and just call methods on the same object?

So the client which will use this service would first call web method which would create so object and return some ID. And then in subsequent calls the web service would reuse the same so object based on ID.

EDIT


Here is my actual code:

[WebMethod]
public List<ProcInfo> GetProcessList(string domain, string machineName)
{
    string userName = "...";
    string password = "...";
    TaskManager tm = new TaskManager(userName, password, domain, machineName);

    return tm.GetRunningProcesses();
}

[WebMethod]
public bool KillProcess(string domain, string machineName, string processName)
{
    string userName = "...";
    string password = "...";
    (new TaskManager(userName, password, domain, machineName);).KillProcess(processName);               
}
like image 271
Primoz Avatar asked Nov 07 '10 12:11

Primoz


2 Answers

Stateful web services are not scalable and I wouldn't recommend them. Instead you could store the results of expensive operations in the cache. This cache could be distributed through custom providers for better scalability:

[WebMethod]
public string Method1()
{
    SomeObj so = TryGetFromCacheOrStore<SomeObj>(() => SomeClass.GetSomeObj(), "so");
    return so.Method1(); //this exetus in a moment 
}

[WebMethod]
public string Method2()
{
    SomeObj so = TryGetFromCacheOrStore<SomeObj>(() => SomeClass.GetSomeObj(), "so");
    return so.Method2(); //this exetus in a moment 
}

private T TryGetFromCacheOrStore<T>(Func<T> action, string id)
{
    var cache = Context.Cache;
    T result = (T)cache[id];
    if (result == null)
    {
        result = action();
        cache[id] = result;
    }
    return result;
}
like image 181
Darin Dimitrov Avatar answered Sep 19 '22 14:09

Darin Dimitrov


Option 1

You can use your HttpSession.

//this executes very long time, 50s and more, but only once.
private SomeObj SessionSomeObj { 
  get 
  { 
    var ret = (SomeObj)Session["SomeObjStore"] ?? SomeClass.GetSomeObj();
    SessionSomeObj = ret;
    return ret; 
  }
  set { Session["SomeObjStore"] = value; }
}

[WebMethod(EnableSession = true)]
public string Method1()
{
    return SessionSomeObj.Method1(); //this exetus in a moment 
}

[WebMethod(EnableSession = true)]
public string Method2()
{
    return SessionSomeObj.Method2(); //this exetus in a moment 
}

Note that this will only work if one call per client is made at a time.

Option 2

You can leave the class as is but use the WebMethod differently. If you are calling from a .Net generated class, async methods are provided for these occurrences. Basically you invoke the Method1 begin request method and get a call back when the execution is finished. You might need to tweak the timeout parameter of the web service client class for this to work though.

Option 3

You can use the caching features of the SixPack library to do this effortlessly! ;-)


[Edited after comment] There are now two static fields in option 1 to allow two different instances, one per method, as requested.


[Edited after further explanation] Using Session to make the calls stateful.

See: http://msdn.microsoft.com/en-us/library/aa480509.aspx

Also added Option 3.

like image 30
Sklivvz Avatar answered Sep 17 '22 14:09

Sklivvz