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.
Related
I am using .NET Core dependency injection, but when I am trying to get the service in another class, I am getting the 'IServiceProvider.GetService(Type)' cannot be used with type arguments' error.
What does this error means?
I understand that a generic type argument is something like this: GenericInterface<>, and the GetService method does not take the GenericInterface<> as an argument.
Why am I getting this error and how do I solve it?
The interface
public interface IService
{
void Process();
}
The class implementing the interface
public class Service : BaseService<IConfig, SomType>
{
public Service(
ILogger logger : base(logger)
{
}
...
}
The BaseService class is an abstract class and it implements the IService interface.
public abstract class BaseService<TConfig, TE> : AnotherBaseService, IService where TConfig : IConfig where TE : struct, IConvertible
{
protected BaseService(ILogger logger): base(logger)
{
}
...
}
The AnotherBaseService
public abstract class BaseService
{
protected readonly ILogger Logger;
protected BaseService(ILogger logger)
{
Logger = logger;
}
...
}
How I registered them.
serviceCollection.AddScoped<IService, Service>();
How I am getting the service I need.
var incoming = serviceProvider.GetService<IService>();
NB: I am just getting started with dependency injection, .NET Core and do not know everything about DI just yet. Your answers would be of great help.
The generic GetService< T> method is an extension method. This means you need to have a :
using Microsoft.Extensions.DependencyInjection;
to allow the compiler to find it.
This method is only meant for optional services. It will return null if the object can't be constructed, either because the type wasn't registered or because some of its dependencies are missing.
GetRequiredService should be used when an application can't work unless a service is available. If an instance can't be created, it will throw an InvalidOperationException.
When that exception is thrown, the full exception text will be a huge help in finding the actual problem. Exceptions thrown in constructors can appear in the Exception.InnerException property. The sequence of calls that ended up in an exception being thrown will appear in the StackTrace property. Calling Exception.ToString() will return a string that contains all of that information for the current exception and any inner exceptions.
It means your compiler only has knowledge of the method that takes a type.
You could call
var incoming = serviceProvider.GetService(typeof(IService));
or you could add a
using Microsoft.Extensions.DependencyInjection;
to make sure your compiler knows the extension method that lets you specify your type as a generic parameter. This might need the package Microsoft.Extensions.DependencyInjection.Abstractions to be installed.
The short answer which is very well explained in the above posts:
ServiceProvider.GetService<T>();
with the use of following namespace which needs to be defined explicitly rather than relying on intellisense
using Microsoft.Extensions.DependencyInjection;
Also Keep a note there can be mutiple problems if you getting null exception after this:
In startup make sure Hostbuilder service is set to ServiceProvider value
ServiceProvider = host.Services;
Other could be the constructor of the T class couldn't resolve the dependency of the Interface being used.
**
Thanks ! Happy Coding :)
**
I want to implement AOP for the logging in my .NET Core 2.1 solution. I've never used it before and I've been looking online and cant seem to see any examples of people using it with Core 2. Does anyone know how i would go about this?
For example what packages to use for AOP and have any example code to get me started? Im using the built in DI with .net core so i dont need to worry about that part.
Microsoft DI does not offer advances scenarios such as interceptor or decorators(there is a workaround for decorators using Microsoft DI: https://medium.com/#willie.tetlow/net-core-dependency-injection-decorator-workaround-664cd3ec1246).
You can implement AOP by using Autofac (https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html) or Simple injector with dynamic proxy. Both have a really good documentation. Simple injector doesn't have an out of the box solution for interception because of their design rules but you can add an extension for it (http://simpleinjector.readthedocs.io/en/latest/aop.html).
Here is a basic AOP scenario from the official SI documentation:(http://simpleinjector.readthedocs.io/en/latest/InterceptionExtensions.html) :
//Add registration to the composition root
container.InterceptWith<MonitoringInterceptor>(serviceType => serviceType.Name.EndsWith("Repository"));`
// Here is an example of an interceptor implementation.
// NOTE: Interceptors must implement the IInterceptor interface:
private class MonitoringInterceptor : IInterceptor {
private readonly ILogger logger;
public MonitoringInterceptor(ILogger logger) {
this.logger = logger;
}
public void Intercept(IInvocation invocation) {
var watch = Stopwatch.StartNew();
// Calls the decorated instance.
invocation.Proceed();
var decoratedType = invocation.InvocationTarget.GetType();
this.logger.Log(string.Format("{0} executed in {1} ms.",
decoratedType.Name, watch.ElapsedMilliseconds));
}
}
Disclaimer: I am the producer of this solution
Microsoft does not provide an AOP solution out the box for Net Core. However, I have produced a 3rd party project which may help. It works directly with Net Core and plugs in via the ServiceCollection registration in your application.
What Microsoft does provide is a library called System.Runtime.DispatchProxy which can be used to create proxy objects for your classes. However, this proxy isnt particularly useful or feature rich on its own and would require a lot of extra code to get something that is on a level with Castle Proxy (the well known Dynamic Proxy library)
With that in mind, I have created a library which wraps the DispatchProxy into code that can be easily injected during the ServiceCollection configuration in the application startup. The trick is to have a way to create attributes AND a paired interceptor that can be applied to your methods. The attribute is then read during the Proxy wrapping and the relevant Interceptor is called.
This is an example Interceptor Attribute
public class ConsoleLogAttribute : MethodInterceptorAttribute
{
}
This is an example Interceptor class
public class ConsoleLogInterceptor : MethodInterceptor
{
public override void BeforeInvoke(IInterceptionContext interceptionContext)
{
Console.WriteLine($"Method executing: {interceptionContext.CurrentMethod.Name}");
}
public override void AfterInvoke(IInterceptionContext interceptionContext, object methodResult)
{
Console.WriteLine($"Method executed: {interceptionContext.CurrentMethod.Name}");
}
}
This is how it would be applied to your method
[ConsoleLog]
public void TestMethod()
{
}
And then finally, this is how it would be added to your ServiceCollection configuration (assuming that the class you wanted to Proxy was called [TestClass]:
public void ConfigureServices(IServiceCollection services)
{
// Configure Simple Proxy
services.EnableSimpleProxy(p => p.AddInterceptor<ConsoleLogAttribute, ConsoleLogInterceptor>());
// Configure your services using the Extension Methods
services.AddTransientWithProxy<ITestClass, TestClass>();
}
Take a look at this GitHub project: https://github.com/f135ta/SimpleProxy
I have 'standard' MVC application in next structure: UI (MVC), Business logic and data access using FluentNHibernate. I've done all steps for registering in castle container my components as described in castle documentation, used FluentRegistration API. So, all components were registered using WIndsor Installers like this:
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(IHandlerBase<>))
.WithService.AllInterfaces()
.LifestyleTransient());
In this code IHandlerBase - generic interface from which derives all my nested classes in business logic. Data access registered in same way and when I start my app all my components and services registered in container. All dependencies in MVC project relatively to BL resolved, but when I need my dependencies in business logic relatively to DataAccess they didn't. Stub example of my modules:
MVC
public ILogger Logger { get; set; } // Resolved, not null
public IHandlerBase<FooRerquest> FooHandler<FooRequest> { get; set; } // Resolved, not null
// Call Foohandler method
FooHandler.MethodName() { ... } // Here works fine
BusinessLogic
public ILogger Logger { get; set; } // Unresolved, null
public IRepository <FooCommand> FooRepository<FooCommand> { get; set; } // Unresolved, null
// Call FooRepository method
FooRepository.MethodName() { ... } // Doesn't work, catch ArgumentNullException
ILogger is a Castle NLog Facility
What and where I do in wrong way?
Thanks, Andrew
It works in UI because Controllers are created via custom ControllerFactory which uses container usually.
If instances of your business logic classes are resolved as part of MVC classes, they should be resolved. If simply constructors are used to create instances of your business logic classes then they know nothing about IoC and all references can't be resolved.
I suggest you use constructor injection since it makes Dependency Injection more visible.
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");
}
}
}