Reputation: 2055
Hi I am trying to use NLog with an Web Api 2 application that uses Ninject for dependency injection.
I have struggled to find any concrete info on how to do this so far I have installed the NuGet packages for NLog & NLog.Configuration. So far what I have read suggests that theses packages should just work and take care of the binding for me.
I set up the Nlog.config file and then I installed the Ninject.Extensions.Logging & Ninject.Extensions.NLog4 packages.
I'm trying to use NLog as follows
public class ErrorCheckController : ApiController
{
private readonly ILogger _logger;
public ErrorCheckController(ILogger logger)
{
_logger = logger;
}
public IHttpActionResult Get(string version)
{
try
{
throw new Exception("Manually thrown exception");
}
catch (Exception ex)
{
_logger.Debug(ex);
}
return Ok();
}
}
In my NinjectWebCommon I have tried
kernel.Bind<ILogger>().To<Logger>();
kernel.Bind<ILogger>().ToMethod(lm => LogManager.GetLogger("MyLogger"));
where MyLogger is the name of the target configurationWhen I do 1 & 2 I get the error
An error occurred when trying to create a controller of type 'ErrorCheckController'. Make sure that the controller has a parameterless public constructor.
The 3rd option gets a Logger but it isn't configured using the NLog.config file
EDIT Here is my config file
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false">
<targets>
<target xsi:type="Database" name="Ink3DPowderDbLogger" connectionStringName="MyDbContext">
<commandText>
INSERT INTO Log.ApiLog (
Application,
Logger,
Logged,
Level,
Environment,
Request,
Message,
BaseDir,
Message,
CallSite,
CallSiteLn,
Exception,
EventProperties,
StackTrace,
ServerName,
Port,
Url,
Https,
ServerAddress,
RemoteAddress,
) VALUES (
@Application,
@Logger,
@Logged,
@Level,
@Environment,
@Request,
@BaseDir,
@Message,
@CallSite,
@CallSiteLine,
@Exception,
@EventProperties,
@StackTrace,
@ServerName,
@Port,
@Url,
@Https,
@ServerAddress,
@RemoteAddress,
);
</commandText>
<parameter name="@application" layout="${appsetting:name=AppName:default=Unknown}" />
<parameter name="@logger" layout="${logger}" />
<parameter name="@logged" layout="${date}" />
<parameter name="@level" layout="${level}" />
<parameter name="@environment" layout="${environment}" />
<parameter name="@request" layout="${asp-request}" />
<parameter name="@basedir" layout="${basedir}" />
<parameter name="@message" layout="${message}" />
<parameter name="@callSite" layout="${callsite}" />
<parameter name="@callSiteLine" layout="${callsite-linenumber}" />
<parameter name="@exception" layout="${exception:tostring}" />
<parameter name="@eventproperties" layout="${eventproperties:tostring}" />
<parameter name="@stacktrace" layout="${stacktrace:tostring}" />
<parameter name="@serverName" layout="${aspnet-request:serverVariable=SERVER_NAME}" />
<parameter name="@port" layout="${aspnet-request:serverVariable=SERVER_PORT}" />
<parameter name="@url" layout="${aspnet-request:serverVariable=HTTP_URL}" />
<parameter name="@https" layout="${when:inner=1:when='${aspnet-request:serverVariable=HTTPS}' == 'on'}${when:inner=0:when='${aspnet-request:serverVariable=HTTPS}' != 'on'}" />
<parameter name="@serverAddress" layout="${aspnet-request:serverVariable=LOCAL_ADDR}" />
<parameter name="@remoteAddress" layout="${aspnet-request:serverVariable=REMOTE_ADDR}:${aspnet-request:serverVariable=REMOTE_PORT}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="Ink3DPowderDbLogger" />
</rules>
</nlog>
EDIT 2 I Have changed my Get Method to
public IHttpActionResult Get(string version)
{
IKernel kernel = new StandardKernel();
//var resolver = new NinjectDependencyResolver(kernel);
//var logger = (ILogger) resolver.GetService(typeof(ILogger));
var logger = kernel.Get<ILogger>();
try
{
throw new Exception("Manually thrown exception");
}
catch (Exception ex)
{
//_logger.Debug(ex);
logger.Debug(ex);
}
return Ok();
}
This gives me an error
No matching bindings are available, and the type is not self-bindable.
Which sounds like nothing is getting binded to ILogger.
Edit 3
I was looking back over my config file and noticed that I had told NLog to fail silently. I turned this off and now I am getting proper errors. There seems to be an issue with my
I get the errors
Exception: Error when setting property 'Layout' on NLog.Targets.DatabaseParameterInfo
Inner Exception: LayoutRenderer cannot be found: 'appsetting'
I'm not too sure why this can't be found I'm using the same syntax that is in the documentation for appsetting
Upvotes: 1
Views: 2526
Reputation: 2055
The problem ended up being that I was trying to Inject
NLog.ILogger
instead of
Ninject.Extensions.Logging.ILogger
It is working now.
Upvotes: 1
Reputation: 172646
Make sure that the controller has a parameterless public constructor.
The reason you get this error is because:
Because there is no explicit registration for the controller, Ninject will try to create it for you, but since there is problem in the configuration it will return null
(which is dictated by the IDependencyResolver
contract).
Once you register all your controllers explicitly (you should always register all your root types explicitly in the container), Ninject will throw an expressive exception explaining what the configuration error is. Registering all root types explicitly also allows you to test your DI configuration.
Upvotes: 1