Можно ли создать веб-сервис с сохранением состояния в C #? - PullRequest
6 голосов
/ 07 ноября 2010

У меня сейчас что-то вроде этого:

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 
    }

 ...
}

Можно ли создать веб-сервис с отслеживанием состояния, чтобы я мог повторно использовать SomeObj so и просто вызывать методы для одного и того же объекта?

Таким образом, клиент, который будет использовать этот сервис, сначала вызовет веб-метод, который создаст объект so и вернет некоторый идентификатор.И затем при последующих вызовах веб-служба будет повторно использовать тот же so объект на основе идентификатора.

EDIT


Вот мой фактический код:

[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);               
}

Ответы [ 3 ]

6 голосов
/ 07 ноября 2010

Stateful веб-сервисы не масштабируются, и я бы не рекомендовал их.Вместо этого вы можете хранить результаты дорогостоящих операций в кэше .Этот кэш может быть распределен через пользовательских провайдеров для лучшей масштабируемости:

[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;
}
1 голос
/ 07 ноября 2010

Опция 1

Вы можете использовать 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 
}

Обратите внимание, что это будет работать только в том случае, если одновременно выполняется один вызов на клиента.

Вариант 2

Вы можете оставить класс как есть, но использовать WebMethod по-другому.Если вы звоните из сгенерированного класса .Net, для этих случаев предоставляются методы async.По сути, вы вызываете метод запроса метода Method1 и получаете обратный вызов по окончании выполнения.Для этого может потребоваться настроить параметр timeout класса клиента веб-службы.

Опция 3

Вы можете использовать функции кэширования из библиотеки SixPack , чтобы сделать это без особых усилий!; -)


[Отредактировано после комментария] Теперь в параметре 1 есть два статических поля, чтобы разрешить два разных экземпляра, по одному на метод, как требуется.*


[Отредактировано после дальнейшего объяснения] Использование сеанса для выполнения вызовов с состоянием.

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

Также добавлен вариант 3.

0 голосов
/ 07 ноября 2010

Измените ServiceContract вашего интерфейса на:

[ServiceContract(SessionMode = SessionMode.Required)]

И добавьте в свой класс следующий атрибут:

[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode.PerSession)]

См. http://msdn.microsoft.com/en-us/library/system.servicemodel.sessionmode.aspx для получения дополнительной информации.и пример.

...