Stuck Working Through Steven Sanderson's "ASP.NET MVC 2..." - asp.net-mvc-2

I received a brief introduction to ASP.NET MVC in school and I am trying to expand that knowledge base with Steven Sanderson's book Pro ASP.NET MVC 2 Framework. It's been a great help, but I have hit a wall in the example that implements Ninject. I believe the DI is setup correctly, but when I try to specify the bindings for a dependency in my Ninject controller class, I receive one of two brown screens of death:
No parameterless constructor defined for this object.
Stack Trace:
[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
System.Activator.CreateInstance(Type type) +6
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +491
[InvalidOperationException: An error occurred when trying to create a controller of type 'SportsStore.WebUI.Controllers.ProductsController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +628
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +204
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +193
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +160
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +80
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +45
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8898152
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
Object reference not set to an instance of an object.
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
SportsStore.WebUI.Infrastructure.SportsStoreServices.Load() in D:\Visual Studio 2010\Projects\CSharp2010AndDotNet4PlatformBook\SportsStore\SportsStore.WebUI\Infrastructure\NinjectControllerFactory.cs:33
Ninject.Modules.NinjectModule.OnLoad(IKernel kernel) in c:\Projects\Ninject\ninject\src\Ninject\Modules\NinjectModule.cs:60
Ninject.KernelBase.Load(IEnumerable`1 modules) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:222
Ninject.KernelBase..ctor(IComponentContainer components, INinjectSettings settings, INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:102
Ninject.KernelBase..ctor(INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:57
Ninject.StandardKernel..ctor(INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\StandardKernel.cs:31
SportsStore.WebUI.Infrastructure.NinjectControllerFactory..ctor() in D:\Visual Studio 2010\Projects\CSharp2010AndDotNet4PlatformBook\SportsStore\SportsStore.WebUI\Infrastructure\NinjectControllerFactory.cs:18
SportsStore.WebUI.MvcApplication.Application_Start() in D:\Visual Studio 2010\Projects\CSharp2010AndDotNet4PlatformBook\SportsStore\SportsStore.WebUI\Global.asax.cs:32
Here is my code in the Ninject controller class:
public class NinjectControllerFactory : DefaultControllerFactory
{
// A Ninject "kernel" is the things that can supply object instances
private IKernel kernel = new StandardKernel(new SportsStoreServices());
// ASP.NET MVC calls this to get the controller for each request
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
// Configures how abstract service types are mapped to concrete implementations
private class SportsStoreServices : NinjectModule
{
public override void Load()
{
Bind<IProductsRepository>()
.To<SqlProductsRepository>()
.WithConstructorArgument("connectionString",
ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString
);
}
}
}
The book is pushing up against the limits of my understanding, but I am following along and have been able to debug everything up to this point. This has me stumped. Any idea where I would begin to debug this?

Both issues are related to Ninject not being setup or integrated correctly. The trunk version of Ninject allows you to bypass having to define custom controller factories. It's a cleaner setup and less confusing.
See:
http://codeclimber.net.nz/archive/2009/08/14/how-to-use-ninject-2-with-asp.net-mvc.aspx
Additionally you should check out the article listed here
Ninject and Custom Controller Factory

Did you update your application_start in global.asax to point to the ninject controller factory?
as such:
protected void Application_Start() {
..........
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory ());
}

Related

Mvc5 Hangfire Autofac No parameterless constructor defined for this object

I have an MVC5 webapplication which uses Autofac for DI registrations.
Now im using Hangfire for background jobs. When i schedule a job, i got an error.
What am i missing in here? I followed the descriptions given bij Hangfire and Hangfire.Autofac documentation.
Exception i got:
System.MissingMethodException
No parameterless constructor defined for this object.
System.MissingMethodException: No parameterless constructor defined for this object.
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type)
at Hangfire.JobActivator.SimpleJobActivatorScope.Resolve(Type type)
at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass10_0.<PerformJobWithFilters>b__0()
at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId, BackgroundJob backgroundJob, IReadOnlyDictionary`2& customData)
MyJob class:
public interface IMyJob
{
void DoSomething();
}
public class MyJob : IMyJob
{
private readonly ILogger _logger;
public MyJob(ILogger logger)
{
_logger= logger;
}
public void DoSomething()
{
Console.WriteLine("Recurring!");
}
}
I am using the following versions:
Hangfire 1.7.28
Hangfire.Autofac 2.3.1
Autofac 5.2.0
I have the following Hangfire configurations:
// Startup.cs
public void Configuration(IAppBuilder app)
{
// Configure DI dependancies
Bootstrapper.SetAutofacContainer(app);
// Configure authentication
ConfigureAuth(app);
// Configure Hangfire
`Hangfire.GlobalConfiguration.Configuration.UseSqlServerStorage("DefaultConnection");
var options = new DashboardOptions { Authorization = new[] { new HangfireAuthorizationFilter() } };
app.UseHangfireDashboard("/jobs", options);
app.UseHangfireServer();`
RecurringJob.AddOrUpdate<MyJob>("MYJOB", (x) => x.DoSomething(), Cron.MinuteInterval(5));
}
// My Autofac bootstrapper class
public class Bootstrapper
{
public static void SetAutofacContainer(IAppBuilder app)
{
var builder = new ContainerBuilder();
// Register Web controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly);
// Register model binders that require DI.
builder.RegisterModelBinders(typeof(MvcApplication).Assembly);
builder.RegisterModelBinderProvider();
// Register web abstractions like HttpContextBase.
builder.RegisterModule<AutofacWebTypesModule>();
// Enable property injection in view pages.
builder.RegisterSource(new ViewRegistrationSource());
// Enable property injection into action filters.
builder.RegisterFilterProvider();
// Identity
builder.RegisterType<ApplicationUserStore>().As<IUserStore<Medewerker, Guid>>().InstancePerLifetimeScope();
builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerLifetimeScope();
builder.RegisterType<ApplicationSignInManager>().AsSelf().InstancePerLifetimeScope();
builder.Register<IAuthenticationManager>(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerLifetimeScope();
builder.Register<IDataProtectionProvider>(c => app.GetDataProtectionProvider()).InstancePerLifetimeScope();
builder.RegisterType<Logger>().As<ILogger>().InstancePerLifetimeScope();
builder.RegisterType<MyJob>().AsSelf().InstancePerBackgroundJob();
// Build the container
var container = builder.Build();
Hangfire.GlobalConfiguration.Configuration.UseAutofacActivator(container);
JobActivator.Current = new AutofacJobActivator(container);
// Replace the MVC dependancy resolver with Autofac
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Set the dependency resolver for MVC.
var mvcResolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(mvcResolver);
// Register the Autofac middleware FIRST, then the Autofac MVC middleware.
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
}
}

Mapstruct : Use of context in source argument of #Mapping

When using multiple arguments in a #Mapper, it seems that the #Context arguments is unreachable
public interface MyMapper {
#Mapping(target="target1", source="arg1.arg") //works
#Mapping(target="target2", source="arg2") //works
#Mapping(target="target3", source="arg2.arg") //works
#Mapping(target="target2", source="context.arg") //NOT WORKING
public MyTarget convert(Object arg1, Object arg2, #Context Object context);
}
I am trying to use and expression="" to work around it, but I can't get it to work.
Any suggestions?
I can see I am not the only one to ever wish this.
https://github.com/mapstruct/mapstruct/issues/1280
Thanks
I ran into the same scenario as I needed a #Context param to be able to pass to a nested mapping function, but also wanted to use it as a source in a #Mapping. I was able to achieve this using expression as follows:
public interface MyMapper {
#Mapping(target="target1", source="arg1")
#Mapping(target="target2", source="arg2")
#Mapping(target="target3", expression="java( contextArg )")
public MyTarget convert(Object arg1, Object arg2, #Context Object contextArg);
}
To answer your second question:
public interface MyMapper {
#Mapping(target="target1", source="arg1.arg")
#Mapping(target="target2", ignore = true ) // leave to after mapping
MyTarget convert(Object arg1, #Context Object context);
#AfterMapping
default convert(Object arg1, #MappingTarget MyTarget target, #Context context) {
target.setTarget2( convert ( context ) );
}
// if you have multipe mappings, you could address them here
#Mapping(target="target2", source="context.arg")
MyInnerTarget convert(Object arg1, Object context);
}
By definition a #Context annotated object is not a source. It is context So you can't use it as source in the #Mapping(target="target2", source="context.arg")
Here is a related github issue with official answer: github issue
Not really clean, but it seems having the same object as source and context allows to use it both ways.
#Mapping(target="target1", source="arg1.arg")
#Mapping(target="target2", source="arg2")
#Mapping(target="target3", source="arg2.arg")
#Mapping(target="target4", source="contextAsSource.arg")
public MyTarget convert(Object arg1, Object arg2, Object contextAsSource, #Context Object context);
Here contextAsSource and context are the same.

How the unity container will resolve the registered service

In my code I am trying to log the viewModel name on entry/exit of a viewModel.
My logger is
public interface ILoggerService : ILoggerFacade
{
void LogMessage(string message );
void LogEntry();
void LogExit();
}
public class LoggerService : ILoggerService
{
public void LogEntry()
{
var trace = new StackTrace();
if (trace.FrameCount > 1)
{
string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace;
string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name;
string message = string.Format("{0}.{1}.{2} Entry", ns, typeName,
trace.GetFrame(1).GetMethod().Name);
LogDebug(message, DefaultPriority);
}
}
// Same for LogExit
}
My Bootstrapper
public class Bootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.RegisterInstance<ILoggerService>(_logger);
}
protected override ILoggerFacade CreateLogger()
{
_logger = new LoggerService();
return _logger;
}
}
My ViewModel & Model are
public class HomeViewModel
{
private readonly ILoggerService _loggerService;
private readonly HomeModel _model;
public HomeViewModel(HomeModel model, ILoggerService logger)
{
logger.LogEntry();
_model = model;
_loggerService = logger;
// Do some other stuff here.
logger.LogExit();
}
}
public class HomeModel
{
private ILoggerService _logger;
public HomeModel(ILoggerService logger)
{
logger.LogEntry();
_logger = logger;
logger.LogExit();
}
}
Error I got
Cat[Critical} Sev[Critical] Pri[100] Framework Time:[ 2016-09-22 13:33:39.860] Shisha.exe PId: 22220 ThreadId:7428
#### An exception occurred while initializing module 'MainModule'.
- The exception message was: Resolution of the dependency failed, type = "Modules.Main.Views.HomeView", name = "(none)".
Exception occurred while: Calling constructor Modules.Main.Models.HomeModel(Services.Logging.Interface.ILoggerService logger).
Exception is: NullReferenceException - Object reference not set to an instance of an object.
-----------------------------------------------
At the time of the exception, the container was:
Resolving Modules.Main.Views.HomeView,(none)
Resolving parameter "viewModel" of constructor Modules.Main.Views.HomeView(Modules.Main.ViewModels.HomeViewModel viewModel)
Resolving Modules.Main.ViewModels.HomeViewModel,(none)
Resolving parameter "model" of constructor Modules.Main.ViewModels.HomeViewModel(Modules.Main.Models.HomeModel model, Microsoft.Practices.Prism.Regions.IRegionManager regionManager, Microsoft.Practices.Prism.Events.IEventAggregator eventAggregator, Services.Dialogs.Interface.IDialogService dialogService, Services.Logging.Interface.ILoggerService logger, Services.Localisation.Interfaces.ITranslator translator)
Resolving Modules.Main.Models.HomeModel,(none)
Calling constructor Modules.Main.Models.HomeModel(Services.Logging.Interface.ILoggerService logger)
- The Assembly that the module was trying to be loaded from was:Modules.Main, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Check the InnerException property of the exception for more information. If the exception occurred while creating an object in a DI container, you can exception.GetRootException() to help locate the root cause of the problem.
at Services.Logging.LoggerService.LogCritical(String message, Int32 priority) in C:\Projects\Utilities\DotNet\Services\Services.Logging\LoggerService.cs:line 257
at Services.Logging.LoggerService.LogCritical(String message) in C:\Projects\Utilities\DotNet\Services\Services.Logging\LoggerService.cs:line 250
at Shisha.Bootstrapper.InitializeModules() in C:\Projects\Shisha\Application\Shisha\Bootstrapper.cs:line 85
at Microsoft.Practices.Prism.UnityExtensions.UnityBootstrapper.Run(Boolean runWithDefaultConfiguration)
at Shisha.App.Application_Startup(Object sender, StartupEventArgs e) in C:\Projects\Shisha\Application\Shisha\App.xaml.cs:line 39
at System.Windows.Application.OnStartup(StartupEventArgs e)
at System.Windows.Application.<.ctor>b__1_0(Object unused)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at MyApp.App.Main() in C:\Projects\Shisha\Application\Shisha\obj\x86\Release\App.g.cs:line 0
I Googled and debugged ( by adding logs ) a lot finally came to know that it is the
"trace.GetFrame(1).GetMethod().DeclaringType.Namespace;"
that is failing..
It working fine in 'Debug' mode ( because of PDB file ) but is failing in 'Release' mode.
Instead of resolving the logger from constructor if we use
Resolve<ILoggerService>(),
it is working fine.
It is not clear for me how _container.Resolve() got the MethodBase information and 'resolving from constructor' didn't.
Can anyone explain me what is the difference between these two.
OR
Am I completely missing something?
It seems the compiler is converting the constructor to inline constructor.
By using [MethodImpl(MethodImplOptions.NoInlining)] and telling the compiler not to inline is working fine.
[MethodImpl(MethodImplOptions.NoInlining)]
public class HomeModel
{
private ILoggerService _logger;
public HomeModel(ILoggerService logger)
{
logger.LogEntry();
_logger = logger;
logger.LogExit();
}
}

Autofac MVC5 and WebAPI2.1 not working

Here is my Bootstrap in global.asax
public class Global : HttpApplication {
void Application_Start(object sender, EventArgs e) {
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
// initiate dependency injection resolver
DependencyInjectionResolver.RegisterDependencies(typeof(Global).Assembly);
}
}
Here is implementation
public class DependencyInjectionResolver {
private static IContainer _container;
public static TService Resolve<TService>() {
return DependencyResolver.Current.GetService<TService>();
}
public static void RegisterDependencies(Assembly assembly) {
var builder = new ContainerBuilder();
builder.RegisterFilterProvider();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterGeneric(typeof (Repository<>))
.As(typeof (IRepository<>))
.InstancePerHttpRequest()
.InstancePerLifetimeScope();
builder.RegisterType<LoggerService>()
.As<ILoggerService>()
.InstancePerApiRequest()
.InstancePerHttpRequest();
builder.Register(x =>
new MessageDataService(Resolve<ILoggerService>(), Resolve<IRepository<ApiRequestHistory>>()))
.As<IMessagesDataService>()
.InstancePerHttpRequest()
.InstancePerApiRequest();
#region setup
_container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(_container));
GlobalConfiguration.Configuration.DependencyResolver
= new AutofacWebApiDependencyResolver(_container);
#endregion
}
}
Here is my exception:
An error has occurred.An error occurred when trying to create a controller of type 'MessageReportController'. Make sure that the controller has a parameterless public constructor.System.InvalidOperationException at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()An error has occurred.Type 'WayToLead.Web.UI.api.MessageReportController' does not have a default constructorSystem.ArgumentException at System.Linq.Expressions.Expression.New(Type type)
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
How to fix it to work with WebApi and Mvc controllers?
Check that you have registered all of your ApiControllers' dependencies and sub-dependencies. Somewhere deep inside the stack trace you might find exacly which dependency AutoFac wasn't able to resolve.
I'm guessing that since AutoFac couldn't satisfy all dependencies then the default dependency resolver takes over.

ASP.NET MVC2 + Ninject + NLog (+ shared hosting?) = NullReferenceException

I have an MVC2 app that's based on the Tekpub Starter Site, so it uses Ninject for dependency injection, NLog for logging, and a bunch of other libraries in various places. As far as I can tell though, it's these that are causing my problem.
Everything works beautifully on my PC using the ASP.NET dev server (Cassini) but when I deploy to the server (it's a cheap shared hosting deal), I get a NullReferenceException that seems to be related to Ninject instantiating the logger.
Here's the relevant bits of my Global.asax.cs
protected override void OnApplicationStarted() {
Logger.Info("App is starting"); // <-- I think this is what's causing the problem
RegisterRoutes(RouteTable.Routes);
//MvcContrib.Routing.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
RegisterAllControllersIn(Assembly.GetExecutingAssembly());
SetEngines();
}
protected override IKernel CreateKernel() {
return Container;
}
internal class SiteModule : NinjectModule {
public override void Load() {
Bind<ILogger>().To<NLogLogger>();
// and a couple of others...
}
}
protected void Application_End() {
Logger.Info("App is shutting down");
}
protected void Application_Error() {
Exception lastException = Server.GetLastError();
Logger.Fatal(lastException);
}
public ILogger Logger {
get {
return Container.Get<ILogger>();
}
}
static IKernel _container;
public static IKernel Container {
get {
if (_container == null) {
_container = new StandardKernel(new SiteModule());
}
return _container;
}
}
The nlog.config
<?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" >
<targets>
<!--Useful for debugging-->
<target name="console" xsi:type="ColoredConsole"
layout="${date:format=HH\:mm\:ss}|${level}|${stacktrace}|${message}" />
<target name="file" xsi:type="File" fileName="${basedir}/App_Data/Site.log"
layout="${date}: ${message}" />
<target name="eventlog" xsi:type="EventLog" source="My App" log="Application"
layout="${date}: ${message} ${stacktrace}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="file" />
<!-- <logger name="*" minlevel="Fatal" writeTo="eventlog" /> -->
</rules>
</nlog>
The NLogLogger class:
public class NLogLogger:ILogger {
private Logger _logger;
public NLogLogger() {
_logger = LogManager.GetCurrentClassLogger();
}
public void Info(string message) {
_logger.Info(message);
}
// similar for Warn, Debug, etc
Stack trace:
[NullReferenceException: Object reference not set to an instance of an object.]
NLog.LogManager.GetCurrentClassLogger() +84
DynamicInjector8cdfc2eb02f8497596a4704e379a4bb4(Object[] ) +40
Ninject.Activation.Providers.StandardProvider.Create(IContext context) +319
Ninject.Activation.Context.Resolve() +182
Ninject.KernelBase.<Resolve>b__4(IContext context) +8
System.Linq.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x) +32
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +151
System.Linq.<CastIterator>d__b1`1.MoveNext() +92
System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source) +4187840
Ninject.ResolutionExtensions.Get(IResolutionRoot root, IParameter[] parameters) +149
Web.Application.get_Logger() in C:\mvcstarter\Web\Global.asax.cs:159
Web.Application.OnApplicationStarted() in C:\mvcstarter\Web\Global.asax.cs:80
Ninject.Web.Mvc.NinjectHttpApplication.Application_Start() +535
[HttpException (0x80004005): Object reference not set to an instance of an object.]
System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +9024793
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +131
System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +194
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +339
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +253
[HttpException (0x80004005): Object reference not set to an instance of an object.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +8946484
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +97
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +256
If I comment out the logging in OnApplicationStarted, I get a different exception. I'm not sure why it's happening, because there shouldn't be any logging happening so I'm not sure why it's trying to instantiate the logger.
[NullReferenceException: Object reference not set to an instance of an object.]
NLog.LogManager.GetCurrentClassLogger() +84
DynamicInjector5ca7d21cf56b4732957e22cb1bfd8bdd(Object[] ) +40
Ninject.Activation.Providers.StandardProvider.Create(IContext context) +319
Ninject.Activation.Context.Resolve() +182
Ninject.KernelBase.<Resolve>b__4(IContext context) +8
System.Linq.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x) +32
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +151
System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source) +4187840
Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent) +347
Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target) +138
Ninject.Activation.Providers.<>c__DisplayClass2.<Create>b__1(ITarget target) +17
System.Linq.WhereSelectArrayIterator`2.MoveNext() +85
System.Linq.Buffer`1..ctor(IEnumerable`1 source) +325
System.Linq.Enumerable.ToArray(IEnumerable`1 source) +78
Ninject.Activation.Providers.StandardProvider.Create(IContext context) +306
Ninject.Activation.Context.Resolve() +182
Ninject.KernelBase.<Resolve>b__4(IContext context) +8
System.Linq.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x) +32
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +151
System.Linq.<CastIterator>d__b1`1.MoveNext() +92
System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source) +4187840
Ninject.ResolutionExtensions.TryGet(IResolutionRoot root, String name, IParameter[] parameters) +261
Ninject.Web.Mvc.NinjectControllerFactory.CreateController(RequestContext requestContext, String controllerName) +108
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +124
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.Mvc.<>c__DisplayClass7.<BeginProcessRequest>b__6() +29
System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Func`1 func) +38
System.Web.Mvc.ServerExecuteHttpHandlerAsyncWrapper.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +97
System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +1508
System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) +77
System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +28
System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +22
System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter) +372
System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper htmlHelper, String actionName, String controllerName) +35
ASP.views_home_index_aspx.__RenderContent2(HtmlTextWriter __w, Control parameterContainer) in c:\HostingSpaces\<snip>\wwwroot\Views\Home\Index.aspx:8
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +109
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
System.Web.UI.Control.Render(HtmlTextWriter writer) +10
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
ASP.views_shared_site_master.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in c:\HostingSpaces\<snip>\wwwroot\Views\Shared\Site.Master:48
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +109
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
System.Web.UI.Control.Render(HtmlTextWriter writer) +10
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +208
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) +55
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3060
The only way I can get the site to work at all is to fake out the logger entirely, which I'm not at all happy with. This is my first time playing with ASP.NET shared hosting, so I'm a bit at a loss. Anyone have any helpful suggestions?
You could avoid using LogManager.GetCurrentClassLogger() and let Ninject resolve the current class name for you:
Change the constructor of your NLogLogger class into this:
public NLogLogger(string currentClassName)
{
_logger = LogManager.GetLogger(currentClassName);
}
And change the ninject binding to resolve the current classname:
Bind<ILogger>().To<NLogLogger>()
.WithConstructorArgument("currentClassName", x => x.Request.ParentContext.Request.Service.FullName);
Additional benefit: your log file now also includes the class name from where the log directive was issued.
I know my answer is a little bit late to the party, but I was struggling with this myself today and couldn't find the answer anywhere. Maybe this helps someone else.
It looks like NLog can't run in medium trust:
http://nlog-project.org/forum.html#nabble-td1685352
If you look in the Global, the app logs when it starts up as well as when it shuts down. You should be able to remove that and be happy.
Shared hosting often has restrictions on reflection etc.
So my guess is that
[NullReferenceException: Object reference not set to an instance of an object.]
NLog.LogManager.GetCurrentClassLogger() +84
is related to that - what happens if you get the logger using a meachanism where you pase in a Type that you get at compile time via typeof ?
I have experienced a similar problem.
My (simplistic) solution:
replace these lines
private Logger Logger = LogManager.GetCurrentClassLogger();
by this line
private static Logger Logger = LogManager.GetCurrentClassLogger();
The readonly keyword is optional.