We have a WCF service called service1 hosted in IIS.
We are creating another WCF service, say, service2, which will always be running in the background and will monitor if a file, say, X, is having enough data that has to be consumed by Service1.
If the file X is not having enough data then service2 will call another component which will load the data to the file.
So please suggest a hosting technique for service2 which fulfils all the above requirements and should be independent, i.e if the service2 is down, it should not impact service1 or vice versa. Both these services are a part of the same app-domain.
We have one scenario where we hosted the same as a window service. Now we are looking to try something else.
Please provide your valuable suggestions.
You're looking for the right kind of screwdriver to hammer a nail. 8-)
WCF services run on demand, based on network activity (a request comes in, the service runs and handles the request). However after a defined period with no activity the service shuts down and the resources are released, and the server waits for the next request, however the existence of a file containing the data you want does not create this type of request.
What you need is a Windows Service (the things that you see in the Services Control Panel). These run continuously and are appropriate for tasks that don't produce network requests, like monitoring to see if you have the data you need.
We have one scenario where we hosted the same as a window service. Now we are looking to try something else.
There really isn't anything else suitable for unattended operation. Windows Services are designed exactly for this type of task, while WCF Services aren't.
Apart from your hosting requirement you should also consider using a FileSystemWatcher if you haven't done so already. You would obviously have to add your own logic to meet your requirements.
Basic example:
protected override void OnStart(string[] args)
{
FileSystemWatcher Watcher = new FileSystemWatcher("some file path");
Watcher.EnableRaisingEvents = true;
Watcher.Changed += new FileSystemEventHandler(Watcher_Changed);
}
// This event is raised when a file is changed
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
// your code here
}
More complete example:
http://www.rhyous.com/2012/11/27/c-creating-a-service-to-monitor-a-directory/
Related
I have below requirements:
(1) Perform 'action A' when user requests for it.
(2) We also want to perform the same 'Action A' twice in a day even if users don't request for it.
I have a WCF web service which has method XYZ that performs action A. The method XYZ will be called when user requests for it.
Now question is, can I schedule this action without creating window service (which can host this service) or creating proxy?
Is there a way to perform an action by user request and schedule that same action, using only one application?
No, WCF cannot be auto-scheduled. You need to implement a Scheduled Task (see Scheduling jobs on windows), a Windows Service with a timer (which you've said you don't want to do, if I understand correctly) or some other application with a timer.
You could start a thread as per the other answer but this relies on your service calling itself - I'd prefer to call it externally, from another process.
A scheduled task can run an executable. You could write a console application that calls your WCF service, logs any result (if necessary) and then completes.
I normally prefer to implement this type of timer through a Windows Service, simply because the Windows Service can be monitored, can log, and can auto-start / auto-restart - install it and it 'just works'. If I didn't want to use a Windows Service then I'd schedule a task.
I typically do this by just calling the WCF service method from some kind of task scheduler. In a really simple form, you could just spawn a Thread from your service, that runs the WCF method periodically. Again this isnt the best solution, but its easiest to demonstrate. You could use some other scheduler library to do this too...
[ServiceContract]
public class SomeClass
{
[ServiceOperation]
public void SomeServiceMethod() { ... }
Then somewhere in the application startup:
Thread t = new Thread(new ThreadStart(CallService));
t.Start();
...
// this will call the WCF service method once every hour
public void CallService()
{
Thread.Sleep(3600000); // sleep 1 hour
new SomeClass().SomeServiceMethod();
}
This is one way to do it, although not the best way, but basically you can just call the WCF service method just like any other method in the application.
I have 2 WCF services implemented in C# that test a client-server interaction of a 3-rd party application. Let's say I have a server-side tester interface for WCF test service (I skipped the attributes ans simplified the interfaces)
interface IServerTester
{
bool Start();
}
And a client side one:
interface IClientTester
{
bool Start();
}
The purpose of those methods is merely to start the server and to start the client of the 3-rd party application. I am using NUnit to test it. On the upper level it looks like a C# transaction script, where I first start a server, then a client and lastly verify that they are communicating.
Later, I want to easily add more clients (start more than one), thus I need to add more WCF calls to IClientTester in my transaction script.
I can do something like this, with each client has its own endpoint
//Start server
//start client 1
//start client 2
//...
//start client N
I will need to reuse the code in many other tests.But it seems to be a rather long solution. Is there any better idea, or perhaps a pattern that I can adopt? Many thanks!
I'm not sure I completely followed your question, but it sounds to me like a need for Pub/Sub. It sounds like when the server starts, you want 1:M clients to be notified and also start, correct? If so, then the server could publish a message or event that the "clients" all subscribe to. You would not need to modify anything to add new clients, simply subscribe to the message or event in the new client implementation.
From a little bit of reading around, it is my understanding that the only way to detect that a client has connected to my service is through writing my own code. I am using a Singleton service. I would like to display a message every time a client connects to my service that client x with ip xxx has connected. There is no built-in event that is generated? Am I correct?
No, I don't think there's any support in WCF for your requirement.
Not sure what you want to achieve with this, either. Your service class (in your case, just a single instance) really doesn't have any business putting up messages (on screen, I presume) - that really not it's job. The service class is used to handle a request and deliver a response - nothing more.
The ServiceHost class might be more of a candidate for this feature - but again, it's job really is to host the service, spin up the WCF runtime etc. - and it's really not a UI component, either.
What you could possibly do is this
have an Admin UI (a Winforms, console, or WPF app) running on your server alongside your service, providing an admin service to call
define a fast connection between the two services (using e.g. netNamedPipe binding which is perfect for intra-application messaging)
when your "real" service gets a call, the first thing it does is send out a message to the admin UI which can then pick up that message and handle it
That way, you could cleanly separate your real service and it's job (to provide that service) and the Admin UI stuff you want to do and build a cleanly separated system.
I have actually implemented my own connect, disconnect and ping service methods which I manually call from my client once the channel has been created. By using them as a kind of header section in all of my ServiceContract interface definitions (and their implementations, of course), they form an makeshift "base service definition" that only requires a bit of cut-n-paste.
The string-based parameters of connect and disconnect will be used to send client info to the server and return server info and (perhaps a unique connection id) to the client. In addition a set of timing reference points may make its way in also.
Note how SessionMode is required and the individual OperationContract properties IsInitiating and IsTerminating are explicitly specified for each method, the end result being what I would call a "single-session" service in that it defines connect and disconnect as the sole session bookends.
Note also that the ping command will be used as the target of a timer-based "heartbeat" call that tests the service connection state and defeats ALL connection timeouts without a single config file :-)
Note also that I haven't determined my fault-handling structure yet which may very well add a method or more and/or require other kinds of changes.
[ServiceContract( SessionMode = SessionMode.Required )]
public interface IRePropDalSvr {
[OperationContract( IsInitiating=true, IsTerminating=false )]
string connect (string pClientInfo);
[OperationContract( IsInitiating=false, IsTerminating=true, IsOneWay=true )]
void disconnect (string pClientInfo);
// ------------------------------------------------------------------------------------------
[OperationContract( IsInitiating=false, IsTerminating=false )]
string ping (string pInp);
// ------------------------------------------------------------------------------------------
// REST OF ServiceContract DEFINITION GOES HERE
One caveat: while I am currently using this code and its implemention in my service classes, I have not verified the code yet.
I am using wcf 4 and trying to transparently transfer context information between client and server.
I was looking at behaviors and was able to pass things around. My problem is how to flow the context received in the incoming headers to the other services that might be called by a service.
In the service behavior I intercept the the message and read the headers but don't know where to put that data to be accessible to the next service call that the current service might make.
What I am looking for is something like:
public void DoWork()
{
var someId = MyContext.SomeId;
//do something with it here and call another service
using(var proxy = GetProxy<IAnotherService>())
proxy.CallSomeOtherMethodThatShouldGetAccessTo_ MyContextualObject();
}
If I store the headers in thread local storage I might have problems due to thread agility(not sure this happens outside ASP.NET, aka custom service hosts). How would you implement the MyContext in the code above.
I chose the MyContext instead of accessing the headers directly because the initiator of the service call might not be a service in which case the MyContext is backed by HttpContext for example for storage.
In the service behavior I intercept
the the message and read the headers
but don't know where to put that data
to be accessible to the next service
call.
Typically, you don't have any state between calls. Each call is totally autonomous, each call gets a brand new instance of your service class created from scratch. That's the recommended best practice.
If you need to pass that piece of information (language, settings, whatever) to a second, third, fourth call, do so by passing it in their headers, too. Do not start to put state into the WCF server side! WCF services should always be totally autonomous and not retain any state, if at ever possible.
UPDATE: ok, after your comments: what might be of interest to you is the new RoutingService base class that will be shipped with WCF 4. It allows scenarios like you describe - getting a message from the outside and forwarding it to another service somewhere in the background. Google for "WCF4 RoutingService" - you should find a number of articles. I couldn't find antyhing in specific about headers, but I guess those would be transparently transported along.
There's also a two-part article series Building a WCF Router Part 1 (and part 2 here) in MSDN Magazine that accomplishes more or less the same in WCF 3.5 - again, not sure about headers, but maybe that could give you an idea.
I'm building a web application using WCF that will be consumed by other applications as a service. Our app will be installed on a farm of web services and load balanced for scalability purposes. Occasionally we run into problems specific to one web server and we'd like to be able to determine from the response which web server the request was processed by and possibly timing information as well. For example, this request was processed by WebServer01 and the request took 200ms to finish.
The first solution that came to mind was to build an ISAPI filter to add an HTTP header that stores this information in the response. This strikes me as the kind of thing somebody must have done before. Is there a better way to do this or an off-the-shelf ISAPI filter that I can use for this?
Thanks in advance
WCF offers much nicer extension points than ISAPI filters. You could e.g. create a client side message inspector that gets called just before the message goes out to the server, and then also gets called when the response comes back, and thus you could fairly easily measure the time needed for a service call from a client perspective.
Check out the IClientMessageInspector interface - that might be what you're looking for. Also see this excellent blog entry on how to use this interface.
Marc
I don't have a ready-made solution for you but I can point you towards IHttpModule.
See code in Instrument and Monitor Your ASP.NET Apps Using WMI and MOM 2005 for example.
private DateTime startTime;
private void context_BeginRequest(object sender, EventArgs e)
{
startTime = DateTime.Now;
}
private void context_EndRequest(object sender, EventArgs e)
{
// Increment corresponding counter
string ipAddress = HttpContext.Current.Request.
ServerVariables["REMOTE_ADDR"];
if (HttpContext.Current.Request.IsAuthenticated)
authenticatedUsers.Add(ipAddress);
else
anonymousUsers.Add(ipAddress);
// Fire excessively long request event if necessary
int duration = (int) DateTime.Now.Subtract(
startTime).TotalMilliseconds;
if (duration > excessivelyLongRequestThreshold)
{
string requestPath=HttpContext.Current.Request.Path;
new AspNetExcessivelyLongRequestEvent(applicationName,
duration,requestPath).Fire();
}
}