14

Ho un'app MVC2 basata su Tekpub Starter Site, quindi utilizza Ninject per l'iniezione delle dipendenze, NLog per la registrazione e un mucchio di altre librerie in varie posti. Per quanto posso dire, sono questi a causare il mio problema.ASP.NET MVC2 + Ninject + NLog (+ hosting condiviso?) = NullReferenceException

Tutto funziona magnificamente sul mio PC utilizzando il server di sviluppo ASP.NET (Cassini) ma quando eseguo il deploy sul server (è un accordo di hosting condiviso a basso costo), ottengo una NullReferenceException che sembra essere correlata a Ninject che istanzia il logger .

Ecco i bit rilevanti delle mie 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; 
     } 
    } 

Il 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> 

La classe NLogLogger:

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 

traccia stack:

[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 

Se commento l'accesso OnApplicationStarted, ottengo un'eccezione diversa. Non sono sicuro del motivo per cui sta accadendo, perché non dovrebbe esserci alcuna registrazione in corso, quindi non sono sicuro del motivo per cui sta tentando di creare un'istanza del 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 

L'unico modo che posso ottenere il sito funzionerà a tutti è di falsificare il registratore del tutto, che io non sono affatto soddisfatti. Questa è la prima volta che gioco con l'hosting condiviso ASP.NET, quindi sono un po 'in perdita. Qualcuno ha qualche suggerimento utile?

+0

La risposta di seguito mi ha aiutato con un problema simile in WPF (contrassegnarlo come risposta!). Tuttavia, per lo sviluppo web risparmia problemi di debugging dispari se si inizia con test localmente su IIS invece che su Cassini - qualsiasi cosa accresca il più possibile gli ambienti di sviluppo/test/di produzione nel minor tempo possibile. – Ted

+0

La risposta qui sotto risolve anche il mio problema: NLog + Ninject non funziona sulla modalità di rilascio quando in modalità Debug funziona correttamente. – Dariusz

risposta

34

Si potrebbe evitare di utilizzare LogManager.GetCurrentClassLogger() e lasciare Ninject risolvere il nome della classe corrente per voi:

Modificare la costruzione della classe di NLogLogger in questo:

public NLogLogger(string currentClassName) 
{ 
    _logger = LogManager.GetLogger(currentClassName); 
} 

e modificare la Ninject vincolante che risolva la corrente classname:

Bind<ILogger>().To<NLogLogger>() 
    .WithConstructorArgument("currentClassName", x => x.Request.ParentContext.Request.Service.FullName); 

Ulteriore vantaggio: il file di registro ora include anche il nome della classe da cui è stata emessa la direttiva di registro UED.

So che la mia risposta è un po 'in ritardo per la festa, ma stavo lottando con questo me stesso oggi e non riuscivo a trovare la risposta da nessuna parte. Forse questo aiuta qualcun altro.

+0

La tua risposta mi ha aiutato a capire una soluzione StructureMap: http://stackoverflow.com/questions/4519261/nlog-getcurrentclasslogger-nullreferenceexception-using-structuremap-full-trus/4525456#4525456 –

+0

Grazie mille Robin, è stato davvero utile. Ho perso quasi un giorno spaccandomi i capelli cercando di capire la causa di un errore che stavo ottenendo solo in modalità di rilascio –

+0

Grazie. Stavo ricevendo questo errore solo in Release build. –

1

condiviso di hosting ha spesso restrizioni alla riflessione ecc

Quindi la mia ipotesi è che

[NullReferenceException:. Il riferimento non impostato a un'istanza di un oggetto] NLog.LogManager.GetCurrentClassLogger () +84

è legata a quella - cosa succede se si ottiene il registratore utilizzando un meachanism dove si Pase in un Type che si ottiene al momento della compilazione via typeof?

+0

Uno dei motivi per cui ho scelto l'host (a parte il prezzo basso, il gruppo senza scopo di lucro e tutto il resto) è che presumibilmente non hanno restrizioni su cose del genere. Non sono nemmeno un guru di NLog con qualsiasi mezzo, ma la mia comprensione è il metodo che hai citato è il modo di usarlo, vedi http://nlog-project.org/wiki/Tutorial#Creating_loggers per esempio ... I ' Vi darò un'occhiata quando arrivo a casa ... – Jon

+0

@Jon: Come il resto del pianeta, ho usato la mia parte di registratori (e con mia vergogna ne ho scritti alcuni). Ho appena usato log4net e le cose incorporate su .NET, non su NLog - ma ho una profonda conoscenza di come funziona con lo4net e tutto è piuttosto analogo. Guardando l'articolo citato, ne hanno uno in cui si passa un nome e uno dove non lo si fa. Quello in cui non devi determinare il nome in qualche modo - che in qualche modo è Reflection. Alcune riflessioni (non tutte) sono limitate nell'hosting condiviso. Pertanto rimuovere 'GetCurrentClassLogger' dall'equazione può eliminare questa possibile causa dalle vostre richieste. –

5

Sembra NLog non può essere eseguito in attendibilità media: http://nlog-project.org/forum.html#nabble-td1685352

Se si guarda nel Global, i registri app quando si avvia così come quando si spegne. Dovresti essere in grado di rimuoverlo ed essere felice.

+0

Questo problema è stato risolto con NLog ver. 4.4.1 –

0

Ho riscontrato un problema simile.

La mia soluzione (semplicistica):

sostituire queste linee

private Logger Logger = LogManager.GetCurrentClassLogger(); 

da questa linea

private static Logger Logger = LogManager.GetCurrentClassLogger(); 

Il readonly parola chiave è opzionale.