Asp.net mvc2 + ninject + nlog ( + hosting condiviso?) = NullReferenceException
-
26-09-2019 - |
Domanda
Ho un'app MVC2 basata su Sito di avviamento Tekpub, quindi utilizza Ninject per l'iniezione di dipendenza, Nlog per la registrazione e un sacco di altre librerie in vari luoghi. Per quanto ne so, sono questi che stanno causando il mio problema.
Tutto funziona magnificamente sul mio PC utilizzando ASP.NET Dev Server (Cassini) ma quando distribuisco sul server (è un accordo di hosting condiviso a buon mercato), ottengo un NullReferenceException che sembra essere correlato all'istanza del Ninject.
Ecco i bit pertinenti del mio 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
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
Se commento l'accesso OnApplicationStarted
, Ho un'eccezione diversa. Non sono sicuro del perché stia accadendo, perché non dovrebbe esserci alcuna registrazione, quindi non sono sicuro del perché stia cercando di istanziare il 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 in cui posso far funzionare il sito è fingere del tutto il logger, di cui non sono affatto soddisfatto. Questa è la prima volta che gioco con l'hosting condiviso ASP.NET, quindi sono un po 'in perdita. Qualcuno ha qualche suggerimento utile?
Soluzione
Potresti evitare di usare LogManager.GetCurrentClassLogger()
E lascia che Ninject risolva il nome della classe corrente per te:
Cambia il costruttore della tua classe Nloglogger in questo:
public NLogLogger(string currentClassName)
{
_logger = LogManager.GetLogger(currentClassName);
}
E modificare l'associazione Ninject per risolvere il nome di classe corrente:
Bind<ILogger>().To<NLogLogger>()
.WithConstructorArgument("currentClassName", x => x.Request.ParentContext.Request.Service.FullName);
Ulteriori vantaggi: il tuo file di registro ora include anche il nome della classe da cui è stata emessa la direttiva del registro.
So che la mia risposta è un po 'tardi alla festa, ma oggi stavo lottando con questo e non riuscivo a trovare la risposta da nessuna parte. Forse questo aiuta qualcun altro.
Altri suggerimenti
Sembra che Nlog non possa funzionare in media fiducia:http://nlog-project.org/forum.html#nabble-td1685352
Se guardi nel globale, l'app registra quando si avvia e quando si spegne. Dovresti essere in grado di rimuoverlo ed essere felice.
L'hosting condiviso ha spesso restrizioni sulla riflessione ecc.
Quindi la mia ipotesi è quella
NullReferenceException: riferimento dell'oggetto non impostato su un'istanza di un oggetto.] Nlog.logManager.getCurrentClassLogger () +84
è correlato a questo - cosa succede se si ottiene il logger usando un meachanism in cui si ritiene in a Type
che ottieni al tempo di compilazione tramite typeof
?
Ho riscontrato un problema simile.
La mia soluzione (semplicistica):
Sostituisci queste linee
private Logger Logger = LogManager.GetCurrentClassLogger();
da questa riga
private static Logger Logger = LogManager.GetCurrentClassLogger();
Il readonly
La parola chiave è facoltativa.