Is it advisable to use singleton pattern in wcf application?. I have ServiceResponse class which will take care the response and errordetail and almost all the details of the wcf current request. When i first hit the service, lets say i have 5 properties in ServiceResponse class and which got filled with respective values and some error details in errordetail property. For the next hit, lets say i dont get any error details and all other 4 properties got filled up.
But the thing here is, the errordetail property is still populated with the previous values which i assume the singleton object doesnt get created even after the subsequent hits. So only changed values got affected but untouched property still holds the previous value for the subsequent hits.
is it because the appdomain never get unloaded to release the object to allow the next sinleton object to get created for the other imm. request? How to acheive the singleton pattern in wcf otherwise. Appreciate the help.
The singleton pattern implies that the object is only instantiated once and lives for the entire lifetime of the AppDomain. You should not store data that is specific to a given request in static objects because all of them will share the same data which might not be what you are looking for.
Whether it is a good idea or not to use static objects in a WCF application is a question that will entirely depend on your scenario and what you need to store there. Since WCF is a multithreaded environment where multiple threads could access this shared data you will have to take special care to ensure that this data is thread safe by using the proper synchronization mechanisms.
is it because the appdomain never get unloaded to release the object
to allow the next sinleton object to get created for the other imm.
request?
There's a single AppDomain that gets created when your application starts. Don't expect to get a different AppDomain on each request. Requests will all be served from the same AppDomain until the application gets recycled by IIS.
...almost all the details of the wcf current request.
This is not a singleton. A singleton will per definition be shared between all requests. You want to create an instance that lives through the whole requets or connection context. Create an instance of your object and store it in the relevant request/connection cache the first time it is needed.
Related
I am creating a web API in ASP.Net with IIS. However, I have been storing class members statically so that they can be accessed across different classes. This is obviously bad practice and I am noticing that every time a request is being made for the API, the same values are being returned due to the members not being cleared. How would I clear the members every request while also being able to access them across classes?
You should almost never use static variables in a web application. Even if you want to share variables across requests, access to statics is not thread-safe in many cases, and that can result in corrupt memory, incorrect system behavior, and even total system failure (if you're unlucky).
If you have variables that need to be shared, use an application variable instead. If you need to have a common cache, use one of the established caching techniques.
As for your specific question
How would I clear the members every request while also being able to access them across classes?
I think there is a misunderstanding here. There is no absolutely no reason to re-use a variable if it is being reset every time. I am guessing you think there is a performance cost to allocating new variables with each request; this is false. It is actually less efficient to use shared variables as multiple threads will experience false sharing and have to wait for each other as each request completes. If you use a new set each time, each thread has its own sandbox to work in and can complete the request much more quickly.
Instead, store your variables locally or as member variables in an object that is discarded at the end of the request. If you need some common location across all modules within a request, you can use HttpContext.Item or one of its alternatives.
I have a simple aspx page.
I need to instantiate a class object myObj one time on first hit. On subsequent hits from clients the same object needs to be used.
I am reading a file from local drive when obj is created and also maintaining some state. On subsequent hits I want object to be not created but states to be maintained.
I would cache the obj on Application_Start() in the global.asax.
Just be certain you're persisting state after each hit.
See this Caching Objects article to get started. Keep in mind, if you are making changes to the object it can be dangerous due to multi-user collisions so it's best to use the cache for data that you need to reference a lot. A list of states, text strings used throughout, settings, etc. that don't change but you need everywhere are perfect items for the cache.
I will go ahead and preface this by saying: I am somewhat new to WCF.
I'm working on a server-side routine that's responsible for doing a great deal of business logic. It's accessible from a client via WCF.
My main WCF method calls off to several other private methods. Instead of passing around all of the "lookup data" I need for the business logic to each private method, I decided to use a singleton instance of a class named DataProvider that contains all of this "lookup data".
At the end of the routine, I "release" the DataProvider's lookup data so the next time the routine is executed, the latest lookup data will be used.
So, here's a simplified example:
public void Generate()
{
try
{
//populate singleton DataProvider with it's lookup data...
DataProvider.Instance.LoadLookupData();
//do business logic...
}
finally
{
//release provider's lookup data...
DataProvider.Release();
}
}
This works great until I have two different clients that execute the method at (or near) the same time. Problems occur because they share the same singleton instance and the task who finishes first will release the DataProvider before the other completes.
So...
What are my options here?
I'd like to avoid passing around all of the lookup data so the singleton pattern (or some derivative) seems like a good choice. I also need to be able to support multiple clients calling the method at the same time.
I believe the WCF service is configured as "Per-Call". I'm not sure if there's a way to configure a WCF service so that the static memory is not shared between service invocations.
Any help would be appreciated.
By default WCF is using "Per-Call", which means new instance of the WCF service is created for each client's call. Now since you implemented singleton even though new instance of the WCF is created it still calls your singleton.
If you would like to create lookup that is created for each call (like you have now) you should not do it as singleton. This way each client that calls your method will have new instance of the lookup, I think that was your intention.
However if you have lookup that is not changing that fast, I would recommend to share it between all calls, this will improve performance of your WCF service. You will need to declare your WCF service as
InstanceContextMode = InstanceContextMode.Single
ConcurrencyMode = ConcurrencyMode.Multiple
What this does is creating Singleton automatically for you by WCF, so you don't have to do it yourself, second it will support > 1 concurrent user (ConcurrencyMode.Multiple).
Now if you have your lookup that is changing and it needs to be reloaded after some period of time, I still would recommend using
InstanceContextMode = InstanceContextMode.Single
ConcurrencyMode = ConcurrencyMode.Multiple
but inside in your code cache it and then expire your cache at specific time or relative time (1 hours).
Here are some links that might help you:
3 ways to do WCF instance management (Per call, Per session and Single)
Hope this will help.
The static variables in a WCF service are always shared between instances regardless of the WCF InstanceContextMode setting. It seems you would be better off using a caching pattern for your look up data. The answers to this caching question provide some alternatives to rolling your own although they are a bit dated.
Also, if you decide that making the whole service instance a singleton (InstanceContextMode=Single) is the easiest solution be aware that you'll generally kill service scalability unless you also make your code multi-threaded (ConcurrencyMode=Multiple). If you can knock out thread-safe code in your sleep then a singleton service might be for you.
simplest is to use a synchronization mechanism - have you looked at lock(...) - this will act as a gatekeeper a lot like a critical section (if you have come across those in windows programming)
define a static object in your class
i.e.
static object lockObject = new object();
and use it in Generate method
i.e.
void Generate()
{
lock(lockObject)
{
...
}
}
I just don't know if the Controller instance is existing in server memory for a certain period of time after the Request/Response or if it just appears in memory and disappears after each Request/Response. Or if it can depend on certain things, what does it depend on?
The DefaultControllerFactory will indeed instantiate and destroy the controller instance for each request. (You can browse the source yourself, or see Dino Esposito's article Inside the ASP.NET MVC Controller Factory for a tour.)
On an ASP.NET website, are static classes unique to each web request, or are they instantiated whenever needed and GCed whenever the GC decides to disposed of them?
The reason I ask is because I've written some static classes before in C# and the behavior is different than I would have expected. I would have expected static classes to be unique to each request, but it doesn't seem like that is the case.
If they are not unique to each request, is there a way to allow them to be?
UPDATE:
The answer driis gave me was exactly what I needed. I was already using a singleton class, however it was using a static instance and therefore was being shared between requests even if the users were different which in this case was a bad thing. Using HttpContext.Current.Items solves my problem perfectly. For anyone who stumbles upon this question in the future, here is my implementation, simplified and shortened so that it easy to understand the pattern:
using System.Collections;
using System.Web;
public class GloballyAccessibleClass
{
private GloballyAccessibleClass() { }
public static GloballyAccessibleClass Instance
{
get
{
IDictionary items = HttpContext.Current.Items;
if(!items.Contains("TheInstance"))
{
items["TheInstance"] = new GloballyAccessibleClass();
}
return items["TheInstance"] as GloballyAccessibleClass;
}
}
}
Your static classes and static instance fields are shared between all requests to the application, and has the same lifetime as the application domain. Therefore, you should be careful when using static instances, since you might have synchronization issues and the like. Also bear in mind, that static instances will not be GC'ed before the application pool is recycled, and therefore everything that is referenced by the static instance, will not be GC'ed. This can lead to memory usage problems.
If you need an instance with the same lifetime as a request, I would suggest to use the HttpContext.Current.Items collection. This is by design meant to be a place to store stuff that you need througout the request. For nicer design and readability, you can use the Singleton pattern to help you manage these items. Simply create a Singleton class that stores its instance in HttpContext.Current.Items. (In my common library for ASP.NET, I have a generic SingletonRequest class for this purpose).
Static members have a scope of the current worker process only, so it has nothing to do with requests, because different requests may or may not be handled by the same worker process.
In order to share data with a specific user and across requests, use HttpContext.Current.Session.
In order to share data within a specific request, use HttpContext.Current.Items.
In order to share data across the entire application, either write a mechanism for that, or configure IIS to work with a single process and write a singleton / use Application.
By the way, the default number of worker processes is 1, so this is why the web is full of people thinking that static members have a scope of the entire application.
Since the types are contained in an app domain, I would expect static classes to be present as long as the app domain is not recycled, or if the request gets served by a different app domain.
I can think of several ways to make objects specific to a particular request depends on what you want to do, for e.g. you could instantiate the object in Application.BeginRequest and then store it in HttpRequest object so that it can be accessed by all objects in the request processing pipeline.
If they are not unique to each request, is there a way to allow them to be?
Nope. Static members are owned by the ASP.NET process and shared by all users of the Web app. You'll need to turn to other session management techniques such as session variables.
Normally static methods, properties and classes are common at the Application level. As long as the application lives, they are shared.
You can specify a different behaviour by using the ThreadStatic attribute. In that case they will be specific to the current thread, which, I think, is specific for each request.
I would not advise this though as it seems overcomplicated.
You can use HttpContext.Current.Items to set stuff up for one request, or HttpContext.Current.Session to set stuff up for one user (across requests).
In general though, unless you have to use things like Server.Transfer, the best way is basically creating things once and then passing them explicitly via method invocation.