XeroxDucati
XeroxDucati

Reputation: 5190

How do I get a service to start from global.asax without having to invoke it?

I have a simple app where I use global.asax to map a serviceroute to a wcf service through a custom servicehostfactory in Application_Start. The constructor of that service does some initial processing to set up the service which takes a bit of time.

I need this constructor to fire when its serviceroute is added automatically. I tried creating a clientchannel from global.asax and making a dummy call to spin up the service, but discovered the service isn't up yet -- it seems application_start has to return?

So how do I get the constructor of the service to fire when first mapped through global.asax without having to manually hit the service? Unfortunately AppFabric isn't an option for us, so I can't just use it's built-in autostart..

UPDATE

I was asked for a bit more detail;

This is like a routing management service. So I have Service1 -- it gets added as a serviceroute in global.asax. Now I have http://localhost/Service1

Inside Service1 I have a method called 'addServiceRoute'. When called, it also registers a route for Service2. Now I have http://localhost/Service1/Service2.

My initial solution from global.asax was to build a channelfactory to http://localhost/service1 but that wouldn't work. Service1 wasn't up yet and wouldn't come up till Application_Start returned (Still not sure why?). So then I thought I'd cheat and move that initial addserviceroute call to the constructor of service1. Also didn't work.

It was mentioned that this shouldnt be in the constructor -- i agree, this is just testing code.

A singleton was also mentioned, which might be ok, but I intend to have more than one instance of Service1 on a machine (in the same app pool) so I don't think that'll work?

** UPDATE #2 ** I was asked for sample code.. here it is from global.asax (trimmed a bit for brevity).. So http://localhost/Test DOES come up.. But if I have to use appfabric to warm up Test and get its constructor to fire, then don't I need Test.svc or something? How do I get appfabric to even see this service exists?

protected void Application_Start(object sender, EventArgs e)
        {
            RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
            RouteTable.Routes.Add(
                new ServiceRoute("Test", new MyServiceHostFactory(ITestService, BindingType.BasicHttpBinding, true), TestService)); 
        }

Upvotes: 3

Views: 2740

Answers (2)

SliverNinja - MSFT
SliverNinja - MSFT

Reputation: 31651

AppFabric autostart is what I would recommend - even though you say you cannot use it - this is the problem it was meant to solve (warming up your service).

As an alternative before AppFabric existed, you would have to use a scheduled task (a.k.a cron job) with an executable that calls into the service you want initialized. The way AppFabric autostart works is by using named pipes (net.pipe) to trigger the warm up - but it just does this exact thing when the service is recycled. The difference between the scheduled task approach and the AppFabric autostart is that the scheduled task doesn't know when your application pool has been recycled - you would need to poll your service periodically to keep it warm.

Alternatively you could consider hosting your WCF application outside of IIS via self-hosting. This would avoid the warm-up issue, but you wouldn't achieve many of the benefits of the IIS hosted container. See HttpSelfHostServer in the new MVC Web API or review using a standard ServiceHost.

Upvotes: 2

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364369

What you describe requires singleton service (something you should avoid) because normally each call or session gets a new instance = a new call to constructor. In self hosted WCF service you can instantiate singleton service instance and pass it to ServiceHost constructor. In case of IIS hosted service used together with ServiceRoute you can try to create your own class derived from ServiceHostFactory and pass created service instance as a parameter to its constructor. In this factory class implement CreateServiceHost method and pass that existing service instance into ServiceHost constructor. To make this work your service class must still be handled as singleton through service behavior.

Btw. constructor should not do any time consuming operation. Constructor is for constructing object not for initializing infrastructure. Using constructor for such initialization is bad practice in the first place.

Upvotes: 2

Related Questions