代码之家  ›  专栏  ›  技术社区  ›  Jon

ASP.NET MVC2+Ninject+nlog(+shared hosting?)=空引用异常

  •  14
  • Jon  · 技术社区  · 15 年前

    我有一个基于 Tekpub Starter Site 因此,它使用ninject进行依赖注入,使用nlog进行日志记录,并在不同的地方使用许多其他库。但据我所知,正是这些导致了我的问题。

    使用ASP.NET开发服务器(cassini)在我的PC上一切都很好地工作,但是当我部署到服务器上时(这是一个便宜的共享托管交易),我得到一个nullReferenceException,它似乎与实例化记录器的ninject有关。

    以下是我的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;
            }
        }
    

    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>
    

    nlogogogger类:

    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
    

    堆栈跟踪:

    [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
    

    如果我对登录发表评论 OnApplicationStarted ,我得到一个不同的例外。我不知道为什么会发生这种情况,因为不应该有任何日志记录发生,所以我不知道为什么它试图实例化日志记录程序。

    [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
    

    我能让这个网站工作的唯一方法就是完全伪造出日志记录程序,我对此一点也不满意。这是我第一次使用ASP.NET共享宿主,所以我有点不知所措。有人有什么有用的建议吗?

    4 回复  |  直到 9 年前
        1
  •  34
  •   Julian    9 年前

    你可以避免使用 LogManager.GetCurrentClassLogger() 并让ninject为您解析当前类名:

    将nlogogogger类的构造函数更改为:

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

    并更改ninject绑定以解析当前类名:

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

    其他好处:现在日志文件还包括发出日志指令的类名。

    我知道我的答案在派对上有点晚了,但我今天自己也在努力,找不到答案。也许这对其他人有帮助。

        2
  •  5
  •   user1151    15 年前

    看起来nlog不能在中等信任下运行: http://nlog-project.org/forum.html#nabble-td1685352

    如果你在全局中查看,应用程序在启动时和关闭时都会记录下来。你应该能够把它去掉并且快乐。

        3
  •  1
  •   Ruben Bartelink    15 年前

    共享主机通常对反射等有限制。

    所以我的猜测是

    [NullReferenceException:对象引用未设置为对象的实例。] nlog.logmanager.getcurrentClassLogger()+84

    与此相关-如果你让记录器使用一种方法,你在一个 Type 在编译时通过 typeof ?

        4
  •  0
  •   Julian    9 年前

    我也遇到过类似的问题。

    我的(简单)解决方案:

    替换这些行

    private Logger Logger = LogManager.GetCurrentClassLogger();
    

    按这条线

    private static Logger Logger = LogManager.GetCurrentClassLogger();
    

    这个 readonly 关键字是可选的。