14

У меня есть приложение MVC2, основанное на Tekpub Starter Site, поэтому оно использует Ninject для инъекции зависимостей, NLog для ведения журнала и множество других библиотек в различных мест. Насколько я могу судить, это то, что вызывает мою проблему.ASP.NET MVC2 + Ninject + NLog (+ shared hosting?) = NullReferenceException

Все работает красиво на моем ПК с использованием сервера ASP.NET dev (Cassini), но когда я развертываю сервер (это дешевая сделка с общим хостингом), я получаю исключение 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> 

Класс 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 

Стек след:

[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, поэтому я немного в недоумении. У кого-нибудь есть полезные предложения?

+0

Ответ ниже помог мне с аналогичной проблемой в WPF (пожалуйста, отметьте это как ответ!). Тем не менее, для веб-разработки это избавляет от нечетных проблем отладки, если вы только начинаете тестировать локально в IIS, а не в Cassini, - что бы ни делало ваши среды разработки/тестирования/производства настолько же схожими, насколько это возможно, сохраняло печаль в долгосрочной перспективе. – Ted

+0

Ответ на этот вопрос также решает мою проблему: NLog + Ninject не работает в режиме Release, когда режим Debug работает нормально. – Dariusz

ответ

34

Вы могли бы избежать использования LogManager.GetCurrentClassLogger() и пусть Ninject разрешить имя текущего класса для вас:

Изменить конструктор вашего класса NLogLogger в этом:

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

И изменить связывание для разрешения тока в Ninject classname:

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

Дополнительная выгода: ваш файл журнала теперь также включает имя класса, из которого была указана директива журнала UED.

Я знаю, что мой ответ немного опоздал на вечеринку, но я сам боролся с этим сегодня и не мог найти ответ нигде. Может быть, это помогает кому-то другому.

+0

Ваш ответ помог мне разобраться в решении StructureMap: http://stackoverflow.com/questions/4519261/nlog-getcurrentclasslogger-nullreferenceexception-using-structuremap-full-trus/4525456#4525456 –

+0

Большое спасибо Робин, он был действительно полезен. Я потерял почти день, раскалывая волосы, пытаясь выяснить причину ошибки, которую я получал только в режиме Release. –

+0

Спасибо. Я также получал эту ошибку только в сборке Release. –

1

Shared хостинг часто имеет ограничения на отражение и т.д.

Так что я думаю, что

[NullReferenceException:. Ссылка на объект не указывает на экземпляр объекта] NLog.LogManager.GetCurrentClassLogger () +84

связано, что - то, что произойдет, если вы получите регистратор с помощью meachanism где вы Pase в Type, что вы получите во время компиляции с помощью typeof?

+0

Одна из причин, по которой я выбрал хозяина (помимо низкой цены - некоммерческая группа и все), заключается в том, что у них, предположительно, нет никаких ограничений на подобные вещи. Я также не гуру NLog, но я понимаю, что метод, который вы цитировали, - это способ его использования, например, http://nlog-project.org/wiki/Tutorial#Creating_loggers ... I ' я посмотрю на него, когда вернусь домой ... – Jon

+0

@ Jon: Как и на всей остальной части планеты, я использовал свою долю лесорубов (и, к сожалению, написал некоторые). Я только что использовал log4net и встроенный материал на .NET, а не NLog, но у меня есть глубокие знания о том, как он работает с lo4net и все его довольно аналог. Глядя на цитируемую статью, у них есть одна, где вы передаете имя и одно, где вы не делаете. Тот, где вам не нужно определять имя, так или иначе, - это как-то отражение. Некоторое отражение (не все) ограничено в общем хостинге. Поэтому удаление «GetCurrentClassLogger» из уравнения может устранить эту возможную причину из ваших запросов. –

5

Похоже NLog не может работать в среде доверия: http://nlog-project.org/forum.html#nabble-td1685352

Если вы посмотрите в Global, журналах приложений при запуске, а также, когда он выключается. Вы должны уметь удалить это и быть счастливым.

+0

Это было разрешено с помощью NLog ver. 4.4.1 –

0

У меня возникла аналогичная проблема.

(упрощенно) решение

Мои:

заменить эти строки

private Logger Logger = LogManager.GetCurrentClassLogger(); 

по этой линии

private static Logger Logger = LogManager.GetCurrentClassLogger(); 

readonly необязательное ключевое слово.

Смежные вопросы