14

Tengo una aplicación MVC2 que se basa en el Tekpub Starter Site, por lo que utiliza Ninject para la inyección de dependencia, NLog para el registro y un montón de otras bibliotecas en varios lugares. Sin embargo, por lo que puedo decir, son estos los que están causando mi problema.ASP.NET MVC2 + Ninject + NLog (+ alojamiento compartido?) = NullReferenceException

Todo funciona muy bien en mi PC usando el servidor de desarrollo ASP.NET (Cassini) pero cuando implemento en el servidor (es un alojamiento de alojamiento compartido barato), obtengo una NullReferenceException que parece estar relacionada con Ninject instanciando el registrador .

He aquí los bits correspondientes de mis 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; 
     } 
    } 

El 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 clase 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 

Seguimiento de la pila:

[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 

Si comento el registro en OnApplicationStarted, recibo una excepción diferente. No estoy seguro de por qué está sucediendo, porque no debería haber ningún registro, así que no estoy seguro de por qué está tratando de crear una instancia del registrador.

[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 

La única manera que puedo conseguir que el sitio funcione en absoluto es falsa cabo el registrador del todo, que no estoy del todo contento con. Esta es la primera vez que juego con alojamiento compartido ASP.NET, así que estoy un poco perdido. ¿Alguien tiene alguna sugerencia útil?

+0

La respuesta a continuación me ayudó con un problema similar en WPF (por favor, ¡márquelo como la respuesta!). Sin embargo, para el desarrollo web ahorra extraños problemas de depuración si solo comienzas con pruebas locales en IIS en lugar de hacerlo en Cassini: lo que sea que tus entornos de desarrollo/pruebas/producción sean lo más similares posibles ahorrará dolor a largo plazo. – Ted

+0

La respuesta siguiente también resuelve mi problema: NLog + Ninject no funciona en el modo de lanzamiento cuando el modo de depuración funciona bien. – Dariusz

Respuesta

34

Se puede evitar el uso de LogManager.GetCurrentClassLogger() y dejar Ninject resolver el nombre de la clase actual para usted:

Cambiar el constructor de la clase NLogLogger en esto:

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

Y cambiar vinculante para resolver la corriente del ninject nombre de clase:

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

beneficio adicional: el archivo de registro también incluye ahora el nombre de clase desde donde la directiva de registro fue ISS ued.

Sé que mi respuesta es un poco tarde para la fiesta, pero hoy he tenido problemas con esto y no he podido encontrar la respuesta en ningún lado. Quizás esto ayuda a alguien más.

+0

Su respuesta me ayudó a encontrar una solución de StructureMap: http://stackoverflow.com/questions/4519261/nlog-getcurrentclasslogger-nullreferenceexception-using-structuremap-full-trus/4525456#4525456 –

+0

Muchas gracias Robin, se fue realmente útil. Perdí casi un día partiéndome el pelo tratando de descubrir la causa de un error que estaba recibiendo solo en el modo de Liberación –

+0

Gracias. También recibí este error solo en la versión de lanzamiento. –

1

alojamiento compartido a menudo tiene restricciones a la reflexión, etc.

Así que mi conjetura es que

[NullReferenceException:. Referencia a objeto no establecida como instancia de un objeto] NLog.LogManager.GetCurrentClassLogger () +84

tiene que ver con que - lo que sucede si se obtiene el registrador mediante un meachanism donde PASE en un Type que se obtiene en tiempo de compilación a través de typeof?

+0

Una de las razones por las que escogí el host (aparte del bajo precio - grupo sin fines de lucro y todo) es que supuestamente no tienen restricciones en cosas como esa. Tampoco soy un gurú de NLog de ninguna manera, pero mi entendimiento es que el método que citó es la forma de usarlo, vea http://nlog-project.org/wiki/Tutorial#Creating_loggers por ejemplo ... I ' Lo echaré un vistazo cuando llegue a casa ... – Jon

+0

@Jon: Como el resto del planeta, he usado mi parte de madereros (y para mi vergüenza escribí algunos). Acabo de usar log4net y las cosas integradas en .NET, no en NLog, pero tengo un conocimiento profundo de cómo funciona con lo4net y todo es bastante análogo. Mirando el artículo citado, tienen uno donde pasas un nombre y otro donde no. El que no tiene que determinar el nombre de alguna manera, que de alguna manera es Reflexión. Algunas reflexiones (no todas) están restringidas en el alojamiento compartido. Por lo tanto, eliminar 'GetCurrentClassLogger' de la ecuación puede eliminar esta posible causa de sus consultas. –

5

Parece que Nlog no se puede ejecutar en fideicomiso medio: http://nlog-project.org/forum.html#nabble-td1685352

Si nos fijamos en el Mundial, los registros de aplicaciones cuando se pone en marcha, así como cuando se apaga. Deberías poder eliminar eso y ser feliz.

+0

Esto se ha resuelto con NLog ver. 4.4.1 –

0

He tenido un problema similar.

Mi (simplista) solución:

reemplazar estas líneas

private Logger Logger = LogManager.GetCurrentClassLogger(); 

por esta línea

private static Logger Logger = LogManager.GetCurrentClassLogger(); 

readonly La palabra clave es opcional.

Cuestiones relacionadas