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?
Related
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");
}
I've got an ASP.NET that relies on some code that uses static constructors. The code in these type initializers sometimes fails. Let's say, for sake of argument, that the code is:
public static readonly string Thing = SomeSpecialCallThatRarelyFails();
Perhaps that's vile, but it cannot be changed. And this kinda code is in every controller, so ASP.NET can't create the controller and just sits there broken until someone comes along to restart it.
I understand this is the way it should be, because the problem may very well be non-transient and auto-restarting would create a loop. Or perhaps only one controller fails, so the app is still sort of alive. So I get the default behaviour to just keep returning the error. But in this particular case, let's pretend the best thing is to notice this failure and restart.
How can I automate the detection of this scenario and trigger a restart or recycle of the IIS app pool/AppDomain?
I've noticed that if I cause an exception on Application_Start, then the app will auto-restart. So one way is for me to iterate over all my types and try accessing them. If they have .cctor failures, then I'll crash Application_Start and ASP.NET will restart. But that's pretty hacky, plus it won't help if the actual request code references another type that I don't know about which throws on .cctor.
Is there a better way? Should I write a Web API filter and look for TypeInitializerException or something?
Just a thought. Is the 'rare failure' deterministic? Could it be solved by adding retry logic?
public static readonly string Thing = RetrySpecialCall();
private static string RetrySpecialCall()
{
while (true)
{
try
{
return SomeSpecialCallThatRarelyFails();
}
catch (Exception) {}
}
}
So here's a way to handle it in Web API 1:
In Application_Start, iterate over your controller types, calling System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor to force all your known type constructors to run. If it Application_Start fails, ASP.NET seems to restart.
Add an exception filter that looks for TypeInitializationExceptions. Then call HttpRuntime.UnloadAppDomain().
The two parts are needed as a controller failing to construct will not hit the exception filters.
With Web API 2 it seems like you could do it in one go by implementing System.Web.Http.ExceptionHandling.IExceptionLogger and registering it as a global service. Same logic: check for TypeInitializationException and UnloadAppDomain if so.
I am writing a small application that needs to communicate with a server using .NET Remoting. I am using AutoFac to register my instances and ran in to a problem when my remoting proxy object was being disposed, here is some sample code:
builder.Register(b =>
{
var channel = new TcpClientChannel();
// ...
var remoteObj = (IMyComponent)Activator.GetObject(typeof(IMyComponent), "tcp://...");
return remoteObj;
}).As<IMyComponent>();
// ... and then when using it:
using (var scope = this.container.BeginLifetimeScope()) {
var myComponent = scope.Resolve<IMyComponent>();
} // <= An exception will be thrown here since AutoFac will try to call .Dispose on myComponent
// Later I realized that the exception can be fixed by specifying an "empty" OnRealease-behavior when registering the component, probably because AutoFac doesnt try to treat MyComponent like an IDisposable.
...
}).As<MyIComponent>().OnRelease(c => { //Manual disposing here });
This exception caused me to wonder if I am doing something completely wrong here and how to I am supposed to handle the lifetime of the remote proxy correctly. Is there anything wrong in my approach, ie to "create" and return remote proxys through AutoFac? If so, how should the lifetime of remote proxys be handled?
There are some detailed docs on how Autofac handles disposal on the Autofac doc site. this may help clear up some of your questions.
If you have an IDisposable component on which you do not want Autofac to call Dispose for you, register it as ExternallyOwned and automatic disposal will be disabled.
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).
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");
}
}
}