Nayana Adassuriya
Nayana Adassuriya

Reputation: 24766

Keeping a value between web service calls

I need to keep a string list between each web service call in the web service side. Simply, this list should not discard after each web service call proceed. It's life time should with web service application start and finish with web service application stop. something like static variable in the applications.

How to implement such thing in C#.net web-service?

Upvotes: 1

Views: 6024

Answers (4)

Tuncay Oner
Tuncay Oner

Reputation: 59

You can write a singleton class in which you keep your references.

Upvotes: 0

Todd Bowles
Todd Bowles

Reputation: 1574

From what you've said, I think you're using an ASP.NET Web Service (please correct me if I am wrong).

You can create a static class that contains a some type of collection (Dictionary, HashSet, whatever) which you can then use to store your information. The upside is that this will be very fast, the downside is that every time the AppDomain for your service is recycled, your data will be purged. If this is not a problem, then this is probably the simplest option.

You can stop IIS from recycling your ASP.NET processes, but recycling exists for a reason, and I wouldn't suggest doing this unless you know what the impact will be.

With regards to the actual class, something like this would work:

public static class GlobalState
{
    private static HashSet<string> _ipAddresses;
    public static HashSet<string> IPAddresses
    {
        get
        {
            if (_ipAddresses == null) _ipAddresses = new HashSet<string>();
            return _ipAddresses
        }
    }
}

Then when you want to use it:

*** some code
if (GlobalState.IPAddresses.Contains(ipAddress))
*** some more code

Or however you want to leverage the static collection.

Update: I've done some further investigation, and it looks like if you want persistence between AppDomain restarts your choices are limited. Probably either database of some sort or disk.

Also, the solution I gave above, while simple, is poor from a testability point of view, and doesn't take into account concurrency issues that can occur as a result of many multiple calls being made to the service at the same time.

I'd suggest going with something like the following:

public class Service : System.Web.Services.WebService
{
    public Service()
        : this(InMemoryTokensProvider.GetInstance())
    {

    }

    public Service(TokensProvider statePersister)
    {
        _tokens = statePersister;
    }

    private TokensProvider _tokens;

    [WebMethod]
    public string ServiceCall() 
    {
        if (_tokens.Contains("TestToken"))
        {
            return "Token was present!";
        }
        else
        {
            _tokens.Add("TestToken");
            return "Token was added!";
        }
    }
}

public interface TokensProvider
{
    void Add(string token);
    bool Contains(string token);
}

public class InMemoryTokensProvider : TokensProvider
{
    private static InMemoryTokensProvider _instance;
    public static TokensProvider GetInstance()
    {
        if (_instance == null) _instance = new InMemoryTokensProvider();

        return _instance;
    }

    private HashSet<string> _tokens = new HashSet<string>();
    public void Add(string token)
    {
        lock (_tokens)
        {
            _tokens.Add(token);
        }
    }

    public bool Contains(string token)
    {
        lock (_tokens)
        {
            return _tokens.Contains(token);
        }
    }
}

Upvotes: 2

Johann Blais
Johann Blais

Reputation: 9469

If you use WCF to create your services, you might want to consider using the SingleInstance mode for your host. It will allow you to keep data between calls. Only one instance will serve all requests, you can use attributes and properties to keep data in memory between calls.

WCF also supports sessions, you can keep the same instance to serve calls from one particular client.

In each case, the throughput will be impacted unless you authorize multithreaded access to your instance(s). Then you have to take care of the concurrency issues.

Another possible and probably better solution would be to use a persistent store to keep the data between multiples calls.

Upvotes: 0

user3221822
user3221822

Reputation:

In fact I think you can define a class-based or static global varible Dictionary:The Key is IP address, while the other string saves your value. You can use ContainsKey or related method to check whether the request IP exists or not and return the value from the dictionary, otherwises please add the new IP address into the dictionary.

Upvotes: 0

Related Questions