Handle exceptions during WCF service instance creation - c#

I am using Unity.Wcf to inject dependencies in the service class and it work fine. But if I configure my dependencies incorrectly an exception is thrown by unity that it cannot build up my service instance which is correct. Does anyone knows where I can handle this exception to log it for example? It's much easier to check the log than debug it every time.

Another way to capture the exception is to override the CreateServiceHost methods in the service factory. Call base.CreateServiceHost() inside of a try...catch block and use your logging component of choice to save the exception to the log. Other than logging the error, the behavior will be the same.
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
try {
return base.CreateServiceHost(constructorString, baseAddresses);
}
catch (Exception ex) {
// log here
throw;
}
}

After some investigations I have found out how the instance is created and it seems there is no way to add logging to it easily. The only way it to either change the source code of Unity.Wcf or to inherit few classes and override default behavior. For those who are interested the logic is following: UnityServiceHostFactory creates UnityServiceHost, UnityServiceHost adds behavior class UnityInstanceProvider, this UnityInstanceProvider has a GetInstance method that creates the service and does Unity resolving. So to log something you need to do one of the following:
Substitute this class with yours and inherit both UnityServiceHostFactory and UnityServiceHost
Get the sources and change something right in this class (UnityInstanceProvider).

Related

Send all Exceptions to Server in C#

I thought about sending all exceptions created in the programm to a server, but didn't find a good solution. My idea was to create a base class, which, with in the constructor, adds the exception to a queue. A sender does wait on the queue and sends all registered exceptions to the server.
But at the time the exceptions is registered the constructor is not done, which means it is possibile not all values are set when it is send to the server. Is waiting a set amount of ms a good solution or is there a better way to collect all exceptions, that does not require me to do it for every exception/catch manually?
What type of connection should be used? Setting up a tpc connection is expensiv, should I implement a simple UDP based protocol, or is that overkill?
You can look at a article by Jason Taylor on how to do this. Here is his github source code link.
https://github.com/jasontaylordev/CleanArchitecture/blob/main/src/WebUI/Filters/ApiExceptionFilterAttribute.cs
I also wrote a simplified example for you. Hope this helps.
Exception filter:
using Microsoft.AspNetCore.Mvc.Filters;
namespace Multitrust.API.Filters
{
public class ApiExceptionFilter : ExceptionFilterAttribute
{
public ApiExceptionFilter()
{
}
public override void OnException(ExceptionContext context)
{
HandleException(context);
}
private void HandleException(ExceptionContext context)
{
//This will catch all exceptions, you can them log them here. I recommend using serilog.
}
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options =>
options.Filters.Add(new ApiExceptionFilter()));
//Bind other services...
}
Let me know if you need any help with this.
Happy coding!
It's better to use existing ones rather than write custom error catchers. Using a nlog style solution makes the project more universal.

How to troubleshoot simple injector in web api?

I'm using the Simple Injector IoC container in my web api service. Currently, I'm experiencing an error that I'm finding very difficult to investigate.
The container is configured as follows:
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
container.Register<IQueryHandler<LoginQuery, AccountDTO>, LoginQueryHandler>(
Lifestyle.Scoped);
When requests come into the web service, rather than being routed to controllers, they are instead handled by a custom message handler. These handlers are created by inheriting from the DelegatingHandler class (see here for more info).
The custom message handler will then look at the request and invoke a specific handler to handle the request. This is done as follows:
// For the sake of the example (and my testing), I have hard coded the types
// below, but usually these are pulled from the request.
Type handlerType = typeof(IQueryHandler<,>)
.MakeGenericType(typeof(AccountQuery), typeof(AccountDTO));
try
{
// Something does wrong here
dynamic handler = this.handlerFactory.Invoke(handlerType);
// Code execution never reaches this point, exception is not caught
... other code
}
// I have also just tried catching the general exception
catch (TargetInvocationException ex)
{
// do something
}
My current problem is that something goes wrong when trying to invoke the handler from the handler factory (simple injector). When I'm debugging, as soon as I step through that line, I imagine the web service hits an exception, and returns (my client just gets an "Internal Server Error" message). Despite the try/catch, no exceptions are caught, so I have absolutely no idea what is happening. I would think I probably have something configured wrong for simple injector, but I just don't know what (simple injector verifies successfully).
Does anyone have suggestions on what I can do here to figure out what is going on?

WCF client-side error-handling

I'm consuming a clunky WCF server that occasionally throws various exceptions, and additionally returns some of its errors as string. I have no access to the server code at all.
I want to override the inner WCF-client request invocation method and handle all inner exceptions and hard-coded errors returned by the server and raise the Fault event if an error occurs, pseudo:
class MyClient : MyServiceSoapClient
{
protected override OnInvoke()
{
object result;
try
{
result = base.OnInvoke();
if(result == "Error")
{
//raise fault event
}
catch
{
//raise fault event
}
}
}
So that when I call myClient.GetHelloWorld(), it goes thru my overridden method.
How can this be achieved?
I know I don't have to use the generated client, but I don't want to re-implement all the contracts again, and I want to use the generated ClientBase subclass or at least its channel.
What I need is control over the inner request call method.
Update
I read this answer, and looks it's partially what I'm looking for, but I'm wondering if there is a way to attach an IErrorHandler to the consumer (client) code only, I want to add it to the ClientBase<TChannel> instance somehow.
Update
This article also looks very promising but it doesn't work. The applied attribute doesn't seem to take effect.
I can't find a way to add IServiceBehavior to the client side.
Update
I tried attaching an IErrorHandler via IEndpointBehavior.ApplyClientBehavior calling:
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.CallbackDispatchRuntime.ChannelDispatcher.ErrorHandlers
.Add(new ErrorHandler());
}
(clientRuntime is a parameter), but exceptions are still thrown directly skipping MyErrorHandler.
ApplyDispatchBehavior isn't called at all.
Conclusion
I need to achieve two aspects:
Wrap all exceptions that might occur during the lifetime of a BaseClient<TChannel> and decide whether to handle them or throw them on. This should take care of all operation (the service I'm consuming exposes few dozens)
Parse all server-replies and throw exceptions for some of them, so they're forwarded as in statement 1.
You could use and modify the Exception Handling WCF Proxy Generator, more specifically, the base class that it uses. It's basic idea (check this description too) is to provide connection resilience by catching connection faults, and retrying the failed operation. As you can imagine, for this purpose it needs to be able to catch thrown exceptions, and also, it can inspect the result of calls.
The main functionality is given by the ExceptionHandlingProxyBase<T> base class, which you use instead of the ClientBase<T>. This base class has an Invoke method as follows, you'd need to modify that.
Simplified Invoke:
protected TResult Invoke<TResult>(string operationName, params object[] parameters)
{
this.Open();
MethodInfo methodInfo = GetMethod(operationName);
TResult result = default(TResult);
try
{
this.m_proxyRecreationLock.WaitOne(this.m_proxyRecreationLockWait);
result = (TResult)methodInfo.Invoke(m_channel, parameters);
}
catch (TargetInvocationException targetEx) // Invoke() always throws this type
{
CommunicationException commEx = targetEx.InnerException as CommunicationException;
if (commEx == null)
{
throw targetEx.InnerException; // not a communication exception, throw it
}
FaultException faultEx = commEx as FaultException;
if (faultEx != null)
{
throw targetEx.InnerException; // the service threw a fault, throw it
}
//... Retry logic
}
return result;
}
You'll need to modify the throw targetEx.InnerException; part to handle the exceptions as you need, and obviously the resturn value shoudl also be inspected for your needs. Other then that you can leave the retry logic or throw it away if you don't expect connection problems. There is another variant of the Invoke for void return methods.
Oh, and by the way, it works with duplex channels as well, there is another base class for those.
If you don't want to use the generator (it might not even work in newer versions of VS), then you could just take the base class for example from here, and generate the actual implementation class with T4 from your service interface.
If the service isn't returning a true exception, but just a message, you probably want to add a ClientMessageInspector as a new client behavior. Please see: https://msdn.microsoft.com/en-us/library/ms733786.aspx
I've ended up using something based on the answers in this question.
It sticks to the generated client code, and allows invocation of the operations generically.
The code is incomplete, feel free to fork and edit it. Please notify me if you found any bugs or made any updates.
It's pretty bulky so I'll just share the usage code:
using (var proxy = new ClientProxy<MyServiceSoapClientChannel, MyServiceSoapChannel>())
{
client.Exception += (sender, eventArgs) =>
{
//All the exceptions will get here, can be customized by overriding ClientProxy.
Console.WriteLine($#"A '{eventArgs.Exception.GetType()}' occurred
during operation '{eventArgs.Operation.Method.Name}'.");
eventArgs.Handled = true;
};
client.Invoke(client.Client.MyOperation, "arg1", "arg2");
}

Using Custom IHttpActionInvoker in WebAPI for Exception Handling

I'm trying to add a custom IHttpActionInvoker to my WebAPI application in order to prevent the need for lots of repeated exception handling code in my action methods.
There really doesn't seem to be much out there about how to do this other than this article. After writing my IHttpActionInvoker as per the article I added this code:
GlobalConfiguration.Configuration.Services.Remove(typeof(IHttpActionInvoker),
GlobalConfiguration.Configuration.Services.GetActionInvoker());
GlobalConfiguration.Configuration.Services.Add(typeof(IHttpActionInvoker),
new MyApiControllerActionInvoker());
Into a method within my Global.asax file. Now when executing a call to my API I get the following exception raised at the Remove() method:
The service type IHttpActionInvoker is not supported
I guess I have two questions.
Considering there doesn't seen to be an awful lot out there about writing custom IHttpActionInvoker classes is this considered a good approach to solve exception handling in WebAPI applications?
Does anyone know why I would get such an exception when executing the Remove() method and how best to fix this particular issue?
I suffered the same error you describe when attempting to remove the service.
I discovered I didn't need to remove anything from the global config, as it appears if you've registered the interface in your container then it will resolve this first.
For example, I'm using SimpleInjector and in my global.asax I have this:
container.Register<IHttpActionInvoker , MyApiControllerActionInvoker >();
// Register the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
At runtime, it is resolving MyApiControllerActionInvoker dependency when required.
You can then perform exception handling in your customer ActionInvoker and any dependencies set in your constructor will be wired up correctly. The reason I was looking at the ActionInvoker was to get the constructor injection, since injecting into Attributes appears to require property injection.
Also rather than the remove/insert, replace seems to work. (in Global.asax)
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new MyApiControllerActionInvoker(fooService));
Have you considered registering an exception filter instead? Here's some documentation about that:
http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling
You shouldn't have to fall down to the action invoker layer if all you want to do is handle some exceptions in a particular way.
As for me it works with IActionInvoker instead of IHttpActionInvoker. As I understand, IHttpActionInvoker is used for the async api calls, isn't it?
public class RepControllerActionInvoker : ControllerActionInvoker
{
ILogger _log;
public RepControllerActionInvoker()
: base()
{
_log = DependencyResolver.Current.GetService<ILogger>();
}
public override bool InvokeAction(ControllerContext controllerContext, string actionName)
{
try
{
return base.InvokeAction(controllerContext, actionName);
}
catch (Exception e)
{
_log.Error(e);
throw new HttpException(500, "Internal error");
}
}
}

Inject logging dependency with Castle Windsor

I was trying to inject logging dependency by Castle Windsor to my code. More precisely, whenever a method in a class throws an error or application flow enters into a method it simply logs into a file. How to do this by writing nothing like
logger.Debug("Error code");
in the methods explicitly for each of the methods. Suppose we add attribute on each of the class or methods to leverage the logging facility for that.
Thanks in advance.
Use the interceptor facility in Castle Windsor.
So mark your class with
[Interceptor(typeof(UnhandledExceptionLogger))]
and create a class UnhandledExceptionLogger that implements IInterceptor. Roughly:
public void Intercept(IInvocation invocation) {
try {
invocation.Proceed();
}
catch (Exception e) {
// log the exception e
throw;
}
}
and then when Castle Windsor creates an instance of your class marked with this Interceptor, it will create a proxy that wraps all methods invocations in the above try/catch log/rethrow block.

Categories