Running a function on WCF start up - c#

I'm not sure if its possible, but I'd like to have a function run as soon as a WCF service is started to generate initial cache data. I'm not worried now about how to implement the cache, my question is strictly about having the function run when the service starts. The service will be RESTful.
The service will eventually be hosted in IIS and is using .Net Framework 4.5

The easiest way is to create an App_Code folder underneath your WCF project root, create a class (I'll call it Initializer but it doesn't matter. The important part is the method name) like so:
public class Initializer
{
public static void AppInitialize()
{
// This will get called on startup
}
}
More information about AppInitialize can be found here.

What #KirkWoll suggested works, but only if you're in IIS and that's the only AppInitialize static method under App_Code. If you want to do initialization on a per-service basis, if you have a different AppInitialize method or if you're not under IIS, you have these other options:
If using .NET Framework 4.5, and under IIS: You can use the service configuration method which will be called when the service is running. More info at http://msdn.microsoft.com/en-us/library/hh205277(v=vs.110).aspx.
If you're self-hosting your service, you control when the service starts (the call to ServiceHost.Open(), so you can initialize it there
If you're under IIS, and not on 4.5, you can use a service host factory and a custom service host to be called when the service host is being opened. At that point you can do your initialization. You can find more about service host factories at http://blogs.msdn.com/b/carlosfigueira/archive/2011/06/14/wcf-extensibility-servicehostfactory.aspx.
An example of a custom factory is shown below:
public class MyFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
host.Opening += new EventHandler(host_Opening);
return host;
}
void host_Opening(object sender, EventArgs e)
{
// do initialization here
}
}
}

In my case I did like below. I have Windows service project that hosted a WCF Rest service. I wrote below code in my windows service project MyService.cs
protected override void OnStart(string[] args)
{
try
{
ServiceHost myServiceHost = new ServiceHost(typeof(myservice));
myServiceHost.Opening += OnServiceHostOpening;
myServiceHost.Open();
}
catch (Exception ex)
{
//handle exception
}
}
private void OnServiceHostOpening(object sender, EventArgs e)
{
//do something
}

Related

Using SqlDependency in WCF Class Library project hosted as Windows Service

I have created a notification service using SqlDependency for notifying other services about the change in a particular table. This is done in the Windows Service template from Visual Studio. Hence in the OnStart event, subscription of SqlDependency is created, and during OnStop event, un-subscription is done.
The above solution is working perfectly fine.
Now, due to some reasons, I have to make this a WCF class library project and host it as a Windows service. I couldn't think of a place where the subscription and un-subscription of SqlDependency can be done in such case.
When the Windows service is started, the subscription has to be done automatically.
Note: I have a generic Windows service host, which will host all my WCF class library project and can't do much there.
Is there any solution or workaround for this?
I hope that I got your problem right. You have all the logic inside of WCF library but don't know how to sync your subscribe and unsubscribe to SqlDependancy events on Windows Service start-up that will host your WCF service.
My idea is to use a ServiceHostFactory to create an instance of your service and hook on opening and closing events of your service, calling all necessary constructors and connectors from there.
I based most of my answer from this great and lengthy article about hosting WCF services, with link pointing directly to the topic in your case. Some additional docs on ServiceHost and ServiceHostFactory classes.
Bear in mind that this is not a complete code that you can just copy/paste but rather a demonstration of usage.
Here is an example of your Windows service:
public partial class YourWindowsService : ServiceBase
{
// It's your choice where to create this instance, I used constructor injection here arbitrarily
private readonly YourWCFServiceFactory serviceFactory;
private ServiceHost host;
public YourWindowsService(YourWCFServiceFactory serviceFactory)
{
InitializeComponent();
this.serviceFactory = serviceFactory;
}
protected override void OnStart(string[] args)
{
Type serviceType = typeof(YourService);
host = serviceFactory.CreateServiceHost(serviceType, new string[] { "yourBaseUri" });
host.Open();
}
protected override void OnStop()
{
if(host != null)
host.Close();
}
}
And an example of your factory:
public class YourWCFServiceFactory: ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
host.Opening += new EventHandler(host_Opening);
host.Closing += new EventHandler(host_Closing);
return host;
}
private void host_Opening(object sender, EventArgs e)
{
// Initialization here
}
private void host_Opening(object sender, EventArgs e)
{
// Cleanup here
}
}

Running WCF Windows Service as InstanceContextMode.PerCall

I have a WCF Service which is configured to run as a windows service but it only works if I set the InstanceContextMode to Single.When I change it to be PerCall and re-install the service it becomes inaccessible.
Could somebody please clarify if I run a WCF service as a windows service does the context HAVE to be set to Single and why is that?
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CateringSSTService : ICateringSSTService
UPDATE:Here's the hosting code
private ICateringSSTService _cateringSSTService;
private ServiceHost _serviceHost;
private Task _executionTask;
public CateringSSTServer()
{
}
public void Start()
{
_executionTask = new Task(ManagerStartup);
_executionTask.Start();
}
private void ManagerStartup()
{
try
{
_cateringSSTService = new CateringSSTService();
_serviceHost = new ServiceHost(_cateringSSTService);
_serviceHost.Open();
}
catch (Exception)
{
}
}
public void Stop()
{
try
{
if (_serviceHost != null && _serviceHost.State != CommunicationState.Closed)
{
_serviceHost.Close();
}
}
catch (Exception)
{
throw;
}
}
You are creating a single object and passing it to the singleton constructor of ServiceHost. How is this ServiceHost supposed to create a new object every call? That cannot work.
If you want PerCall (or PerSession or anything but Singleton) you need to pass the type of your class to the ServiceHost constructor so it can create new instances of this type at runtime.
_serviceHost = new ServiceHost(typeof(CateringSSTService));
If you hadn't silently swallowed the exception, the Runtime would have told you what the problem is. Apply some proper error handling for future problems.

Caching objects in a RESTful WCF service

I'm looking for a way to cache objects in memory with a RESTful WCF service. The service is completely stateless and is hosted outside of an IIS. I want to implement the caching by myself, so memcached isn't an option.
Right now I'm thinking of hosting a separate stateful System.ServiceModel.ServiceHost that does all the caching. It'll communicate with the rest of the WCF methods through a separate port or by some other means. However I'm not sure if this is the ideal solution to my problem. Has anyone got any tips?
I understand your confusion between stateless service and a stateful host and how the two can interact.
In this code sample I demonstrate conceptually how an in-memory singleton (Caching mechanism, I refer to as CachingProvider henceforth) can be referenced by both the service class (the service instance more precisely during the lifecycle of the request) and the service host (in this case I chose it to be a Console Application)
I assume here, the service interface and class are both located within the console applicaiton project that hosts the service.
In this simple example, my primitive CachingProvider class basically acts as a counter of how many service calls are made to the GetData method, and the service host will poll the CachingProvider every 5 seconds to get the count of service calls made so far.
note: you can use the WCFTestClient utility to test this quickly.
Disclaimer: I by no means suggest that a complex Caching mechanism be implemented as simply as in this sample, this code is merely for demosntration purposes.
namespace ServiceHostConsole
{
[ServiceContract]
public interface ITestService
{
[OperationContract]
string GetData(int value);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class TestService : ITestService
{
public TestService()
{
CachingProvider.CallCount++;
}
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
//For demonstration purposes only
static class CachingProvider
{
static CachingProvider()
{
//private static constructor can initialize
//static cacheable resources
_callCounter = 0; //Trivial example of initialization
}
private static int _callCounter;
public static int CallCount
{
set { _callCounter = value; }
get { return _callCounter; }
}
}
class Program
{
static void Main()
{
using (var host = new ServiceHost(typeof(TestService), new Uri("http://localhost/TestService")))
{
host.Open();
//Example how the ServiceHost can report on a persistent in-memory object that is being
//updated each time the service is called.
new Timer(state => Console.WriteLine("# of service calls: {0}", CachingProvider.CallCount), null, 0, 5000);
Console.Read();
host.Close();
}
}
}
}

WCF: Accessing the service instance from the server

Context:
I need to develop a monitoring server that monitors some of our applications (these applications are in c#). So I decided to develop the system with WCF which seems suitable for my needs.
These applications must register themselves to the monitoring server when they start. After that the monitoring server can call the methods Start or Stop of these applications.
Everything is completely executed on the same machine, nothing needs to be executed remotely.
So I developed a good prototype and everything works fine. Each application registers itself to the monitoring server.
Question:
ApplicationRegistrationService (see the code below) is the implementation of the monitoring service and it is a singleton instance due to the ServiceBehavior attribute.
Here my problem: I want to access the content of ApplicationRegistrationService per example, the number of connected applications from my server (ConsoleMonitoringServer in the example). But, I am not sure how to achieve this.
Do I need to create a channel in my server to the service like I did in my clients (ConsoleClient) or it exists a better way to achieve this?
Code:
The code is very simplified for the purpose of this question:
//The callback contract interface
public interface IApplicationAction
{
[OperationContract(IsOneWay = true)]
void Stop();
[OperationContract(IsOneWay = true)]
void Start();
}
[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IApplicationAction))]
public interface IApplicationRegistration
{
[OperationContract]
void Register(Guid guid, string name);
[OperationContract]
void Unregister(Guid guid);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ApplicationRegistrationService : IApplicationRegistration
{
//IApplicationRegistration Implementation
}
public class ApplicationAction : IApplicationAction
{
//IApplicationAction Implementation
}
Console application for this example
class ConsoleClient
{
static void Main(string[] args)
{
ApplicationAction actions = new ApplicationAction();
DuplexChannelFactory<IApplicationRegistration> appRegPipeFactory =
new DuplexChannelFactory<IApplicationRegistration>(actions,
new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/AppReg"));
IApplicationRegistration proxy = appRegPipeFactory.CreateChannel();
proxy.Register(Guid.Empty, "ThisClientName");
//Do stuffs
}
}
Console server for this example
class ConsoleMonitoringServer
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(ApplicationRegistrationService),
new Uri[]{ new Uri("net.pipe://localhost")}))
{
host.AddServiceEndpoint(typeof(IApplicationRegistration),
new NetNamedPipeBinding(), "AppReg");
host.Open();
//Wait until some write something in the console
Console.ReadLine();
host.Close();
}
}
}
Finally, I find the answer and it was pretty easy. I just need to create the service instance and pass the reference to the constructor of ServiceHost.
So I need to replace the following code:
using (ServiceHost host = new ServiceHost(typeof(ApplicationRegistrationService),
new Uri[]{ new Uri("net.pipe://localhost")}))
by :
ApplicationRegistrationService myService = new ApplicationRegistrationService();
using (ServiceHost host = new ServiceHost(myService,
new Uri[]{ new Uri("net.pipe://localhost")}))
If you mean you'd like two way communication between your monitoring service and your registered services or nodes, then you probably should be using two way communication in WCF also known as duplex communication. Very cool stuff.
http://www.codeproject.com/KB/WCF/WCF_Duplex_UI_Threads.aspx

WCF: Using my "custom" ServiceHost in my app.config/web.config for my wcf service?

I have a created a simple Custom ServiceHost that inherits from ServiceHost and overrides the method InitializeRuntime.
How do i change my app.config / web.config to use the custom service host so my overriden InitializeRunTime is executes..
I see attributes in the config file like behaviorConfiguration etc but nothing obvious where i can force it to use my Custom ServiceHost
My ServiceHost is simple :-
public class UnityServiceHost : ServiceHost
{
protected override void InitializeRuntime()
{
//DO MY UNITY INJECTION HERE
//Console.WriteLine("");
base.InitializeRuntime();
}
}
Any help really appreciated.
Thanks
Oran Dennison describes how to do this using Spring.NET: http://orand.blogspot.com/2006/10/wcf-service-dependency-injection.html
In summary, you'll use WCF's "behavior injection" to supply an instance of the service created by your DI container.
1) Create custom IInstanceProvider implementation with the GetInstance method returning the service object created by your container:
public object GetInstance(InstanceContext instanceContext, Message message)
{
return _container.Resolve(_serviceType);
}
2) Implement a custom IServiceBehaviour that adds your custom IInstanceProvider to each endpoint configuration.
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider =
new YourCustomInstanceProvider(serviceDescription.ServiceType);
}
}
}
}
3) In your custom service host, override OnOpening and add your custom service behavior
protected override void OnOpening()
{
this.Description.Behaviors.Add(new CustomServiceBehavior());
base.OnOpening();
}
Note that you may have to pass down your UnityContainer instance through to the IInstanceProvider so that it can do the resolving.
You need to create a custom ServiceHostFactory and use that to create your UnityServiceHost. You specify the ServiceHostFactory to use in the SVC file. See the MSDN docs for the SVC syntax.
If you're hosting the service yourself (as opposed to using IIS or WAS), you should simply create a UnityServiceHost instead of a regular ServiceHost.
If you are using IIS or WAS, write a ServiceHostFactory

Categories