How to handle Fault state on WCF? (hosting in Windows service) - c#

I'm hosting WCF as Widnows Service but I have a problem with handling Faulted state of WCF channel. Faulted event on ServiceHost never rise up.
Hosting application:
protected override void OnStart(string[] args)
{
_serviceHost = new ServiceHost(typeof(WCF_FaultTest.Service1));
_serviceHost.Faulted += _serviceHost_Faulted;
_serviceHost.Open();
}
void _serviceHost_Faulted(object sender, EventArgs e)
{
// never raise up..
}
Faulted state I try to simulate like this:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class Service1 : IService1
{
public string GetFault()
{
throw new Exception("Should went to fault..");
}
Do I using it correctly? Thank you.

You are using more than one CommunicationObject. When you throw the exception in your service implementation the channel is faulted, but the host it is not. The ServiceHost.Faulted event does not apply in this case.
One thing to remember is that once a CommunicationObject enters the faulted state, it can no longer be used. The only thing to do with a faulted CommunicationObject is to close/abort. After your service throws the exception, if you create a new channel you can still call the service. Therefore the service is not faulted.
From an architecture point of view, a service host event is not the "right" place to implement error handling. In general you want error processing to be part of the service configuration. For example error handling in a ServiceHost event doesn't easily move to IIS hosting. Your comment makes it sound like IErrorHandler didn't meet your requirements. What requirement are you trying to implement?

Related

TCP/IP Exception when using WCF Discovery

We have the following code...
DiscoveryService.cs
[ServiceContract]
public interface IDiscoveryService
{
[OperationContract]
void PrintHello();
}
public class DiscoveryService : IDiscoveryService
{
public void PrintHello()
{
MessageBox.Show("Hello");
}
}
Server.cs
private void InitializeDiscovery()
{
Uri baseAddress = DiscoveryHelper.AvailableTcpBaseAddress;
ServiceHost host = new ServiceHost(typeof (DiscoveryService), baseAddress);
host.EnableDiscovery();
host.Open();
}
Client.cs
private void DiscoverAddressClick(object sender, EventArgs e)
{
EndpointAddress address = DiscoveryHelper.DiscoverAddress<IDiscoveryService>();
Binding binding = new NetTcpBinding();
IDiscoveryService proxy = ChannelFactory<IDiscoveryService>.CreateChannel(binding, address);
proxy.PrintHello();
(proxy as ICommunicationObject).Close();
}
Now, this code seems to work up until the point where we modify anything having to do with the Service Contract, at which point we get a TCP Exception, Error Code 10061 (Connection Actively Refused). However, we cant figure out who is refusing, or why. If we try to revert our code to a previous state, when it was working, we can't, it simply refuses to work after (it seems) we add / remove things from the project.
Every time I build I clean first. We're also following the instructions posted here.
Any thoughts?
I will begin by stating that I'm not all that familiar with WCF Discovery....though I may implement it in our new server stack. But one thing I do not see here is the presence of a proxy server in what you present here.
As I understand it from what I've read on MSDN your WCF service will basically register it's presence to a proxy server running on the network. Your client will then 'discover' your service server via the DiscoveryProxy server. That may be the piece of the plumbing you are missing.
You current implementation of the server will close down the server as soon as the InitializeDiscovery Method is complete because your host only has function scope and will be cleaned up by the garbage collector unless you keep a reference somewhere else.

How to enable user GUI response in wcf service to trigger duplex callback to client

Maybe I am trying the impossible...
I have created a wpf application to start a wcf service with the following service contract:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IRejectCallback))]
public interface IRejectService
{
[OperationContract(IsOneWay = true)]
void SubmitNewRejectInfo();
[OperationContract(IsOneWay = true)]
void SendRejectCallback();
}
My service behavior:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = true)] //(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single, UseSynchronizationContext = true)]
public class RejectService : IRejectService, IPostRejectEvent
I create my duplex channel and call the SubmitNewRejectInfo service method:
InstanceContext ic = new InstanceContext(new RejectCallbackHandler());
tcpFactory = new DuplexChannelFactory<IRejectService>(ic, "netTcp");
IRejectService _rejectService = tcpFactory.CreateChannel();
_rejectService = _tcpFactory.CreateChannel();
_rejectService.SubmitNewRejectInfo();
The SubmitNewRejectInfo method is run on the service side. Normally, I would add my callback method like this:
public void SubmitNewRejectInfo(RejectInformation rejectInformation)
{
// Do something here...
callback.RejectCallback();
}
However, when the SubmitNewRejectInfo method is run from the client (using IsOneWay = true), I do not want to callback to the client at that time. I would like to wait for the user to click a button on my WPF GUI which will transmit the signal to callback to the client. ** Is it possible to postpone the callback, or send a callback via a different operation contract? **
How could the client invoke the service via an operation contract method and then receive a callback after user interaction happens on the service side? I saw one duplex example where someone used a reentrant service with Thread.Sleep() as follows:
public void Register()
{
OperationContext ctxt = OperationContext.Current;
IClientCallback callBack = ctxt.GetCallbackChannel<IClientCallback>();
Thread.Sleep(3000);
callBack.TempUpdate(10);
}
In my case, I would need to trigger the callback in the Register method after a user clicks a button on a gui that is hosting the service. Would this be possible? Any ideas?
UPDATE **
I have discovered my main issue:
I make a call from my wcf client to my operation service contract method:
InstanceContext ic = new InstanceContext(new RejectCallbackHandler());
_tcpFactory = new DuplexChannelFactory<IRejectService>(ic, "netTcp");
_rejectService = _tcpFactory.CreateChannel();
_rejectService.SubmitNewRejectInfo();
The wcf service operation is invoked here:
public void SubmitNewRejectInfo(RejectInformation rejectInformation)
{
// Throw event to notify MainViewModel that new reject information is available.
OnSubmitNewRejectInfo(new RejectInfoArgs(rejectInformation));
callback.RejectCallback();
}
The event is fired to notify my MainViewModel that some data has been updated and refresh some properties. Then problem begins... I do not want the callback.RejectCallback(); to fire just yet. I need the user to click a button on my Mainwindow GUI associated to the view model to "authorize" the duplex callback to return a message to the wcf client.
Any ideas how to "pause" the callback long enough for a user to click a button to authorize the duplex callback to deliver a message to the wcf client? Perhaps my OnSubmitNewRejectInfo event can return some event argument before the callback is invoked? Could a new delegate be triggered to return information from my MainViewModel before the callback is invoked?
I hope this describes my problem a little better. Any help is VERY much appreciated.
Update number 2 **
More information... :)
The WCF service was created as a WCF service class library. The WCF client was also created as a WCF service class library. This makes it easy for other applications or class objects to host the service and client. This was done in order for human interaction via a GUI on the service side, and other software interaction on the wcf client side. The WCF service and client are hosted on separate machines.
The WCF service is hosted by a WPF application, and communication is event driven between the two. The service class is created as a singleton in the MainViewModel of the WPF application.
The WCF service class must talk via duplex communication with the wcf client. The client invokes an operation contract to update information in the service, which is displayed on the WPF GUI. After the information is displayed on the GUI, then the user must click a button to invoke the callback to the client indicating that the service has completed it's task.
So, WPF app hosts a wpf service class library. There is communication between the WPF app and service class via events. The service class is consumed by a wcf client via duplex channel communication. The wcf client is also hosted by another class object with a service reference to the wcf service. The client communicates with it's host via events.
WCF CLIENT CODE:
InstanceContext ic = new InstanceContext(new RejectCallbackHandler());
_tcpFactory = new DuplexChannelFactory<IRejectService>(ic, "netTcp");
_rejectService = _tcpFactory.CreateChannel();
_rejectService.SubmitNewRejectInfo(); // This is where I invoke a service operation from my client.
WCF SERVICE CODE:
// This service operation is consumed by the client.
public void SubmitNewRejectInfo(RejectInformation rejectInformation)
{
// Create event to notify MainViewModel that new reject info is available.
OnSubmitNewRejectInfo(new RejectInfoArgs(rejectInformation));
// **** I need something to happen here in order to halt the duplex callback to the client until a human creates a button click event in my MainViewModel, which indicates the duplex callback may be sent back to the client. ****
callback.RejectCallback();
}
Sorry this question has become very detailed. I never should have fallen asleep during my technical writing class in college... :)
Update number 3 **
I tried running the code that degorolls mentioned below. His example code is perfect for my needs!! (Thanks degorolls!) However I get a null reference exception: "Object reference not set to an instance of an object".
First the action executes in this part of degoroll's demo code:
if (pendingNotifications.TryGetValue(rejectInformation, out action))
{
try
{
action(rejectInformation); // This is invoked
Then this part of the demo code is called -> callback.RejectCallback(new RejectCallbackMessage())); :
public void SubmitNewRejectInfo(RejectInformation rejectInformation)
{
// Throw event to notify MainViewModel that new reject information is available.
OnSubmitNewRejectInfo(new RejectInfoArgs(rejectInformation));
pendingNotifications.Add(rejectInformation, info => callback.RejectCallback(new RejectCallbackMessage())); // **** the action returns to callback.RejectCallback here ****
This is where I get my null exception error.
Here is my code to get the callback channel:
IRejectCallback callback
{
get { return OperationContext.Current.GetCallbackChannel<IRejectCallback>(); }
}
My guess is that I am not returning null instead of the original callback channel...
Is there a way I can obtain the correct channel at this point in the code?
If I'm understanding things correctly it seems that the server simply needs to be keep a list of things it is waiting to do. How you implement will be tied closely to the instancing of the server. If you stick with singleton, you can simply hold a map of pending notification in the server class. E.g.:
public class RejectService
{
Dictionary<RejectInformation, Action<RejectInformation>> pendingNotifications = new Dictionary<RejectInformation, Action<RejectInformation>>();
public void SubmitNewRejectInfo(RejectInformation rejectInformation)
{
OnSubmitNewRejectInfo(new RejectInfoArgs(rejectInformation));
pendingNotifications.Add(rejectInformation, info => callback.RejectCallback(info));
}
public void SendRejectCallback(RejectInformation rejectInformation)
{
Action<RejectInformation> action;
if (pendingNotifications.TryGetValue(rejectInformation, out action))
{
acion(rejectInformation);
pendingNotifications.Remove(rejectInformation);
}
}
}
If you want to make this reentrant you may need to think about locks... This is a really simplistic approach but gives a starting point.

Calling Close() on Service Proxy blocks after One Way WCF call

I have a simple Fire and Forget service operation that works fine and doesn't block. However, when I try to close the service proxy, it will block until the one-way call completes. Is this expected behavior?
Client Code:
var serviceProxy = new MyServiceProxy();
serviceProxy.OneWayCall();
serviceProxy.Close(); // This blocks until OneWayCall() is finished.
Service:
[ServiceContract]
public interface IMyService {
[OperationContract(IsOneWay = true)]
void OneWayCall();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyService : IMyService {
public void OneWayCall() {
// Stuff and things
}
}
Yes - depending on the binding/configuration your service is using and if you are using sessions in any way. See the below link for information on configurations that lead to blocking:
WCF Best Practice #5: One-way is not always really one-way
Hope that helps
For completeness' sake; here is what Microsoft has to say about this behavior:
Clients Blocking with One-Way Operations

unhandled exception will make WCF service crash?

I want to know whether unhandled exception will make WCF service crash. I have written the following program which shows unhandled exception in a thread started by WCF service will make the whole WCF service crash.
My question is, I want to confirm whether unhandled exception in threads (started by WCF service) will make WCF crash? My confusion is I think WCF should be stable service which should not crash because of unhandled exception.
I am using VSTS 2008 + C# + .Net 3.5 to develop a self-hosted Windows Service based WCF service.
Here are the related parts of code,
namespace Foo
{
// NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in Web.config.
[ServiceContract]
public interface IFoo
{
[OperationContract]
string Submit(string request);
}
}
namespace Foo
{
// NOTE: If you change the class name "Service1" here, you must also update the reference to "Service1" in Web.config and in the associated .svc file.
public class FooImpl : IFoo
{
public string Submit(string request)
{
return String.Empty;
}
}
}
namespace Foo
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
ServiceHost host = new ServiceHost(typeof(FooImpl));
protected override void OnStart(string[] args)
{
host.Open();
// start a thread which will throw unhandled exception
Thread t = new Thread(Workerjob);
t.Start();
}
protected override void OnStop()
{
host.Close();
}
public static void Workerjob()
{
Thread.Sleep(5000);
throw new Exception("unhandled");
}
}
}
An unhandled exception on the service side will cause the channel (the connection between the client and the server) to "fault" - e.g. to be torn down.
From that point on, you cannot call from the client using the same proxy client object instance anymore - you'll have to re-create the proxy client.
Your best bet is to handle all error on the server side whenever possible. Check out the IErrorHandler interface, which you should implement on your service implementation class, to turn all unhandled .NET exceptions into either SOAP faults (which will NOT cause the channel to fault), or to report / swallow them entirely.
Marc
Yes, an unhandled exception in a thread will take the process down.
This process will crash:
static void Main(string[] args)
{
Thread t = new Thread(() =>
{
throw new NullReferenceException();
});
t.Start();
Console.ReadKey();
}
This one will not:
static void Main(string[] args)
{
Thread t = new Thread(() =>
{
try
{
throw new NullReferenceException();
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
}
});
t.Start();
Console.ReadKey();
}
The default behavior of the WCF runtime is to swallow all but a few types exceptions. So if your code throws an exception down the stack to the WCF runtime (such as if you throw from a WCF operation), it will NOT crash the app (unless it is deemed a "fatal" exception, such as OOM, SEHException, etc.). If the exception is not part of the operation's fault contract, then the channel will be faulted, otherwise not.
If the WCF runtime is not under your code on the stack, then the exception /will/ crash the process.
This is similar to the ASP.NET runtime.
If you would like to screen for exceptions flying out of WCF operations in a general way, I recommend using the IOperationInvoker interface. You can also use IErrorHandler, but your IErrorHandler implementation will be notified of exceptions other than those thrown from "user code" (WCF operations), such as SocketAbortedExceptions on WCF internal I/O threads, which are probably not interesting to you.
If you don't handle an exception it gets passed on the operating system and it will respond by killing what ever application caused the exception.
Why don't you just add a try/catch to handle the exceptions so that your service is not killed ?
If you don't have proper error handling it will make the program crash. Its good practise to put a
try{//do something
}
catch{ //handle errors
}
finally{//final clean up
}
block in your code to make sure that if it does throw an exception is to handle it gracefully. examples at http://msdn.microsoft.com/en-us/library/fk6t46tz(VS.71).aspx
You can make use of FaultException to communicate errors to the client side and keep the logic in the service.
Check this example, hope it helps you.

How do I prevent a WCF service from enter a faulted state?

I have a WCF Service that should not enter the faulted state. If there's an exception, it should be logged and the service should continue uninterrupted. The service has a one-way operation contract and is reading messages from an MSMQ.
My problems are twofold:
The service appears to be swallowing
an exception/fault so I am unable to
debug it. How do I get the service
to expose the exception so that I
can log or handle it?
The service is
entering into a faulted state after
this exception is swallowed. How do
I prevent the service from entering
into a faulted state?
The official documentation on how to handle Faults is here:
Handling Exceptions and
Faults
Understanding State
Changes
with the main page being at Channel Model Overview
There's a nice state diagram showing how things happen:
Most, if not all exceptions can be seen in the WCF Trace (Configuring Tracing) and the trace is best viewed with the Service Trace Viewer.
Obviously, this is not something you should have running all day in a production environment, but it helps in troubleshooting anyway.
Apart from that, note that oneways may not run as a true "fire and forget" depending on the SessionMode you use. If you have your service configured for SessionMode.Allowed or even SessionMode.Required, the oneway operation will run as if it was not oneway at all (this can be observed when using oneways over the netTcpBinding). To be frank, however, I don't know if that changes the type of exceptions you can get, or when you get them. However, in any case, you should get an exception if the request could not be send at all. AFAIK, the oneway "ends" when it is successfully enqued on the server side. So there is some place for (WCF framework related) exceptions until then (serialization/deserialization comes to mind).
Then, such framework related exceptions are best seen (even an IErrorHandler doesn't get them all due to the fact when it is called in the request/response-flow) using the above mentioned trace / traceviewer.
Exceptions will fault the proxy. You can't AFAIK do much about that: don't cause exceptions ;-p
I'm a little surprised that one-way is still causing a problem, but for swallowing in general, there are 3 aspects:
are you throwing faults? or exceptions? it matters (and should be "faults")
as a hack, you can enable debug exception messages - but turn it off please!!!
are you "using" the service object? I've just blogged on this exact subject... basically, your "using" can swallow the exception.
3 options:
don't use "using"
subclass the proxy and override Dispose()
wrap it, as per the blog
Usually the WCF service is hosted in a ServiceHost, if the WCF-Service fails then the only option is to kill the WCF service and start a new one.
The ServiceHost has an event trigger "Faulted" that is activated when the WCF Service fails:
ServiceHost host = new ServiceHost(new Service.MyService());
host.Faulted += new EventHandler(host_faulted);
host.Open();
It is possible to get the exception causing the fault, but it requires a bit more work:
public class ErrorHandler : IErrorHandler
{
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
public bool HandleError(Exception error)
{
Console.WriteLine("exception");
return false;
}
}
public class ErrorServiceBehavior : IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
ErrorHandler handler = new ErrorHandler();
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add(handler);
}
}
}
ServiceHost host = new ServiceHost(new Service.MyService());
host.Faulted += new EventHandler(host_faulted);
host.Description.Behaviors.Add(new ErrorServiceBehavior());
host.Open();
Credits http://www.haveyougotwoods.ca/2009/06/24/creating-a-global-error-handler-in-wcf
I had an issue where the Channel remained in a faulted state after a ReceiveTimeout exception. This would cause the service to be rendered unusable by any subsequent connections.
The fix for recovering the service from the faulted state for me was to handle the Faulted event of the communication channel:
channelFactory = new ChannelFactory<IService>(endpoint);
channelFactory.Faulted += OnChannelFaulted;
var channel = channelFactory.CreateChannel();
Then define OnChannelFaulted:
void OnChannelFaulted(object sender, EventArgs e)
{
channelFactory.Abort();
}
Note: I am running the WCF config via code versus using bindings in the Web.config's.
About 2)...
The trick is that you should use "using" and should always call Abort() on the proxy that threw an exception. The article WCF Gotcha explains it all.
We use service class inspired by that article that wraps service calls. This is sample code from my project:
ServiceHelper<CodeListServiceClient, CodeListService.CodeListService>.Use(
proxy => seasonCodeBindingSource.DataSource = proxy.GetSeasonCodes(brandID);
);
And this is the code of ServiceHelper, slightly modified from the article. So far it has served us really well.
using System;
using System.ServiceModel;
namespace Sportina.EnterpriseSystem.Client.Framework.Helpers
{
public delegate void UseServiceDelegate<TServiceProxy>(TServiceProxy proxy);
public static class ServiceHelper<TServiceClient, TServiceInterface> where TServiceClient : ClientBase<TServiceInterface>, new() where TServiceInterface : class
{
public static void Use(UseServiceDelegate<TServiceClient> codeBlock)
{
TServiceClient proxy = null;
bool success = false;
try
{
proxy = new TServiceClient();
codeBlock(proxy);
proxy.Close();
success = true;
}
catch (Exception ex)
{
Common.Logger.Log.Fatal("Service error: " + ex);
throw;
}
finally
{
if (!success && proxy != null)
proxy.Abort();
}
}
}
}

Categories

Resources