I have a WCF service that is using a custom UsernamePasswordValidator. The validator needs to access my entity framework context.
I would like to create one ObjectContext for the entire service call and then destroy/dispose it at the end of the call. So I created a singleton static class that provided this functionality, however, what's happening now is that if two service calls happen concurrently, one of the calls disposes the singleton.
I either keep a local reference to the ObjectContext, in which case the second service to use it sees it as disposed and throws and error, or, I put a wrapper property around the Singleton class wherever I need it and then all my changes get thrown away because I'm getting a new instance of the object if another call has disposed it.
So basically my question is how do I instantiate an ObjectContext per service call?
NOTE: The instance needs to be accesible in both the service code AND the custom UsernamePasswordValidator code.
I can't just do it in the constructor or use a using statement because then the custom UsernamePasswordValidator doesn't have access to it. Is there a way to have a static class per call? It does sound impossible, but what's the way around this? Should I be caching the object in a session?
My service is hosted in IIS.
UPDATE:
So I've nailed this down to storing state in the InstanceContext using an IExtension object. But How do I access the current InstanceContext in a UsernamePasswordValidator?
Ok, so in the end I solved it by using the following static class and relying on ASP.NET to cache the context for me.
I'm not sure if this is the best way to do things, but this allows me to use one ObjectContext per request so I'm not spinning up too many and this also means I don't have to use a lock on the object which would become a nightmare if many users were using the service.
public static class MyContextProvider
{
public static MyModel Context
{
get
{
if (HttpContext.Current.Items["context"].IsNull())
{
HttpContext.Current.Items["context"] = new MyModel();
}
return HttpContext.Current.Items["context"] as MyModel;
}
}
}
Then wherever I need an ObjectContext in the app I just call
var context = MyContextProvider.Context;
You have one instance per call, you also have 1 call per instance.
So it should be very simple, use a using () { } block in the toplevel of your OperationContract method.
Ok, here is the class with thread-safe static method that provides single ObjectContext entity model object for any WCF service call and automatically dispose it at the end of call:
public static class EntityModelProvider
{
private static readonly Dictionary<OperationContext, MyEntityModel> _entityModels = new Dictionary<OperationContext, MyEntityModel>();
public static MyEntityModel GetEntityModel()
{
if (OperationContext.Current == null)
throw new Exception("OperationContext is missing");
lock (_entityModels)
{
if (!_entityModels.ContainsKey(OperationContext.Current))
{
_entityModels[OperationContext.Current] = new MyEntityModel();
OperationContext.Current.OperationCompleted += delegate
{
lock (_entityModels)
{
_entityModels[OperationContext.Current].Dispose();
_entityModels.Remove(OperationContext.Current);
}
};
}
return _entityModels[OperationContext.Current];
}
}
For your service, you can specify a service behaviour which details the instance mode of the service:
[ServiceBehaviour(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService {
ObjectContext context;
}
A cleaner way may be to use the ServiceAuthenticationManager, which is in .NET 4.
http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceauthenticationmanager.aspx
From the Authenticate method (which you'll override) you can access the Message object and set properties on it. I've not used it in anger, so YMMV :)
EDIT the problem with this approach is that you don't have the Username and Password, so will still need the custom Authentication.
Take a look at the UsernameSecurityTokenAuthenticator...
http://msdn.microsoft.com/en-us/library/system.identitymodel.selectors.usernamesecuritytokenauthenticator(v=vs.90).aspx
Further reading from my research:
Answers to this question gives some hints about how to use it:
Custom WCF authentication with System.ServiceModel.ServiceAuthenticationManager?
If you can read (or ignore) the Russian, I found useful hints at:
http://www.sql.ru/forum/actualthread.aspx?tid=799046
This rather good CodeProject article goes further (encryption and compression as well as custom authorization)
http://www.codeproject.com/Articles/165844/WCF-Client-Server-Application-with-Custom-Authenti
Why not pass in the context into your CustomValidator when you assign to the service - store your object context in your validator, and in the overridden validation method new it up if need be. Then you still have access to the object through the Services CutomUserNameValidator ..
Depending on what you are asking :
Create your separate ObjectContext class as a dynamic object - add that as a property to you CustomValidator.
In your custom Validator - you can now check if the object is disposed and create the object again if need be.
Otherwise if this is not what you are after - just store the Context in the validator - you still have access on server side.
The code here is just generalized idea - I am just posting it as a frame of reference so you can have an idea of what I talking about.
public DynamicObjectContextObjectClass
{
ObjectContext internalObjectContext;
}
public class ServiceUserNamePasswordValidator : UserNamePasswordValidator
{
public DynamicObjectContextObjectClass dynamiccontext;
public override void Validate(string userName, string password)
{
if(dynamiccontext.internalObjectContext.isdisposed)
{
dynamiccontext.internalObjectContext = new Context;
}
try
{
if (string.IsNullOrEmpty(userName) || password == null)
{
//throw new ArgumentNullException();
throw new FaultException("Username cannot be null or empty; Password cannot be null and should not be empty");
}
}
}
}
Related
I need to provide an api to a long running windows service which does a bunch of processing and retains a memory of that history. An api is required to provide status on current activity levels of the system (records processed, records waiting to be processed, etc).
I was wanting to use a self-hosted Owin ApiController to provide a nice interface to the system. However, the ApiController is completely stateless and there is no method (after searching dozens of IoC posts) for injecting an already active instance into the controller.
Is there a way to provide a class instance to an ApiController?
I don't think you can inject an old instance of the controller, because you get a new instance every time you perform a request.
However you can create a singleton object with a collection inside, and you can inject it into the controller constructor and use in every request.
You can also use some sort of persistence such as DB, that you can run on your device.
Here is an example for a singleton class:
using System;
public class Singleton
{
public Dictionary<string,object> State {get; private set;}
private static Singleton instance;
private Singleton() {
State = new Dictionary<string,object>();
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
Even though you can get Session state in web api controller, it is going to be questionable solution, instead, I would recommend going the following way:
include Hangfire as dependancy and use it for long running tasks
Use signal-r to to push state of background task
return JobID from your API method and use it on the client to subscribe to signal-r hub
I have created a WCF service which reads from a database and sends back results. For performance reasons I'd like to cache the tables on service startup (which happens in a windows service OnStart). But there's no such thing as constructors in WCF (right?) so best thing I came up with is create an Init() function and call that like the following:
protected override void OnStart(string[] args)
{
mServiceHost = new ServiceHost(typeof(DLSService.DLSService), new Uri("http://localhost:8000/DLS"));
mServiceHost.AddServiceEndpoint(typeof(DLSService.IDLSService), new BasicHttpBinding(), "ServicesHost");
((DLSService.DLSService)mServiceHost.SingletonInstance).Init();
mServiceHost.Open();
}
But using SingletonInstance and casting to the correct type does not seem all that elegeant to me.
Are there more elegant ways to achieve constructor like functionality in WCF?
The recommended best practice is to use the per-call activation model in WCF and keep the services totally stateless.
This means: every time the client makes a request, on the server-side, an instance of your service implementation class will be created, the requested service call will be made, and then the service class will be destroyed again.
So putting your initialization code into the service implementation class constructor would be a really bad idea - it would be executed for each and every single request.
What you could do is have some kind of logic (either in your service class, or some support code, e.g. some kind of an admin interface) that would load those tables you want to cache into a persistent cache, e.g. something like the AppFabric cache. Once done, multiple service instances handling requests could use that common cache to get better performance.
This can be solved with a memoization library, like MbCache. We are doing exactly what you are looking for; on application start-up we call each service operation that we want to cache, and MbCache caches the result for consecutive calls (i.e. no database round-trip to get results) until the cache expires.
MbCache does come with its on fair share of complexity, but once it is running it works very well and handles all the cache logic for us.
You can use the IInstanceProvider interface to create your service, read this article for more information.
Here's an example of code:
public class CustomInstanceProvider:IInstanceProvider
{
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return new DLSService.DLSService();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
var mServiceHost = new ServiceHost(typeof(DLSService.DLSService), new Uri("http://localhost:8000/DLS"));
mServiceHost.AddServiceEndpoint(typeof(DLSService.IDLSService), new BasicHttpBinding(), "ServicesHost");
foreach (var channelDispatcher in mServiceHost.ChannelDispatchers.OfType<ChannelDispatcher>())
{
foreach (var endpointDispatcher in channelDispatcher.Endpoints)
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new CustomInstanceProvider();
}
}
mServiceHost.Open();
With framework 4.5 you can use a configuration's function in your service implementation code:
http://msdn.microsoft.com/en-us/library/hh205277(v=vs.110).aspx.
In a couple of .NET C# webservice projects that i have done i have made access to db static with help of the singleton pattern. Then the other day my friend told me that this is a bad thing to do, because if a lot of request is made for the same db entity then the db would be locked because of the static instance. Is my friends assumptations right? I thought that every new request would make a new instance of the class?
The implementation of the singleton class looks like this:
public class WebService
{
private readonly IFactory _factory;
public WebService(IFactory factory)
{
_factory = factory;
}
public IDataRepository Data
{
get
{
return _factory.GetDatabase();
}
}
}
public static class WebServiceImpl
{
private static readonly WebService _webService = new WebShop(new WebserviceFactoryImpl());
public static WebService webService { get { return _webService; } }
}
_factory.GetDatabase() returns a new instace of the Database class.
Looking at WebServiceImpl, all calls will be sharing a single WebService instance. Now, this isn't necessarily a problem, depending on how that is implemented; for example, if _factory.GetDatabase(); ends up getting called per-request, then it might be that you are getting away with it. Depending further on what GetDatabase() does - i.e. does it get a new instance per call? or does it give you the same instance every time? Simply: we don't have enough information there to answer fully. But:
sharing a single database connection between requests is dangerous; either you need to lock / synchronize, or you risk lots of errors (database connections are not usually written to be thread-safe)
sharing an ORM between requests is even worse: in addition to everything above, you also get issues with data accumulating in the identity / object cache; ORM instances (data-context, etc) are intended to be short-lived and then discarded (and sometimes: disposed)
Having static access to the database is not necessarily a problem; it all comes down to how that is implemented - for example, a static-based API could still create (and dispose) a connection on every call.
I need to instantiate a singleton object per web request, so that the data is processed once and is valid throughout the request, I was using HttpContext.Current.Items to share data during HTTP request, everything was fine until we needed the singleton object instance across multiple threads, the first thing that I came up with was to pass the HttpContext instance to the new thread:
HttpContext context = HttpContext.Current;
ThreadPool.QueueUserWorkItem(callback =>
{
HttpContext.Current = context;
// blah blah
});
Which I don't think is a thread-safe approach as noted here.
Using Reflector I figured HttpContext.Current.Items actually uses CallContext to store objects in each logical thread. So I changed the singleton interface to this:
public static SingletonType SingletonInstance
{
get { return CallContext.GetData(key) as SingletonType; }
set { CallContext.SetData(key, value); }
}
And simply overwrite SingletonInstance when starting any new thread! The code works fine, however it seems that somehow under heavy load, CallContext.GetData(key) returns null and the application crashes with with a null reference exception!
I was thinking, if CallContext.GetData is atomic? But it just doesn't seem right, the CallContext is thread specific data storage and must be atomic or I am missing the point!
My other guess is that setting the SingletonInstance (CallContext.SetData) happens in one thread while CallContext.GetData executes in another as noted here but I don't know how/why?
update:
We are keeping an instance of each online user in an array on the server. The singleton object is actually a reference to the object representing current user. Current user must be unique and available in each thread for database querying, logging, error handling and more, this is how it is done:
public static ApplicationUser CurrentUser
{
get { return CallContext.GetData("ApplicationUser") as ApplicationUser ; }
set { CallContext.SetData("ApplicationUser", value); }
}
ASP.NET may migrate request between threads if it's under load. Once request is received page constructor may execute on one thread and page load on another. In this thread switch CallContext and ThreadStatic are not migrated, but luckaly HttpContext is.
This may be misleading as HttpContext is call context, but this is a little quirk in ASP.NET, probably due to cutting corners to improve performance.
You'll have to remove dependencies to CallContext and use HttpContext entire way through.
You can read more details in this terrific blog post by Piers7.
This was resolved during a chat session.
In essence it involves long-running tasks and a suggestion of using an external service (Web, or regular Windows Service) was decided as the best solution to the problem.
Thread-safing your second method is the best approach.
This is thread-safe version of your singletone:
public sealed class SingletonType
{
#region thread-safe singletone
private static object _lock = new object();
private SingletonType() { }
public static SingletonType SingletonInstance
{
get
{
if (CallContext.GetData(key) == null)
{
lock (_lock)
{
if (CallContext.GetData(key) == null)
CallContext.SetData(key, new SingletonType());
}
}
return CallContext.GetData(key) as SingletonType;
}
}
#endregion
//
//
// SingletoneType members
//
//
}
NOTE : using a lock { } block is the key.
Background/Question:
I'm fairly new to the singleton design pattern. I've used it once in a web application (with the help of the SO community):
public static AppGlobal Instance
{
get
{
if (HttpContext.Current.Session != null)
{
HttpSessionState session = HttpContext.Current.Session;
if (session["AppGlobalInstance"] == null)
{
session["AppGlobalInstance"] = new AppGlobal();
}
return (AppGlobal)session["AppGlobalInstance"];
}
else
{
return null;
}
}
}
The above implementation makes sense to me because the instance of the AppGlobal is stored in the session. When the session dies, AppGlobal dies. What happens if I use the same design pattern in a class library that is called by a web application? For example, the users requests a page that calls methods in a DLL that doesn't know about the session. Will the data stored in the singleton instance be persisted through multiple calls?
private static readonly Singleton instance = new Singleton();
private Singleton() { }
public static Singleton Instance
{
get
{
return instance;
}
}
Additional Information:
Here's what I'm trying to accomplish: I have a web application that is going to receive XML requests from a third party application. This XML will tell my web application to do one of three things (or all three of them). I would like to have a singleton instance of a class that stores data that can be accessed by multiple classes. I want the singleton instance to DIE after each request. If the above doesn't accomplish this, what's the best way to accomplish it?
Note: This web application runs on a single server and will never run on a farm.
EDIT 1:
Based on the suggestion below, I've used System.Web.HttpContext.Current.Session to store my class instance. Does this look like the correct approach for a singleton that will be unique to each session (remember I'm in a class library)?
public static Ariba Instance
{
get
{
if (HttpContext.Current.Session != null)
{
HttpSessionState session = HttpContext.Current.Session;
if (session["AribaInstance"] == null)
{
session["AribaInstance"] = new Ariba();
}
return (Ariba)session["AribaInstance"];
}
else
{
return null;
}
}
}
It will be persisted through multiple calls, but there is one caveat. The static variables are scoped to the AppDomain, so any time the IIS worker process is recycled, any data stored in a static variable will be lost. The same is true of session data, if you're storing it "in proc."
If you want an object that will only exist for the duration of the HTTP request, you can use the HttpContext.Items property.
Because the singleton is static, your data will be available for all the requests in your web application, so it will not be available only for the session.
But in ASP.NET applications, you should avoid using Singletons. Instead you should use the Application object. Main reason for that is that if you will use a web farm then your singleton is no longer singelton for the application scope but only on the machine.
Oh!
If you want to use the instance PER REQUEST, why don't you pass it as a parameter to the methods you are calling or as a constructor parameter for the classes that requires the xml. This will be the best design approach, I think.