EnterpriseLibraryContainer error

Topics: Logging Application Block
Sep 12, 2014 at 3:48 PM
Hi,
I'm using Ent5 and try to create the email trace listener dynamically. The problem is when trying to get an instance of LogWriter by using EnterpriseLibraryContainer.Current.GetInstance(), the error below is thown
Resolution of the dependency failed, type = "Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.ILogFormatter, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was:

  Resolving Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterImpl,LogWriter.__default__ (mapped from Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter, (none))
  Resolving parameter "structureHolder" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterImpl(Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder structureHolder, Microsoft.Practices.EnterpriseLibrary.Logging.Instrumentation.ILoggingInstrumentationProvider instrumentationProvider, Microsoft.Practices.EnterpriseLibrary.Logging.ILoggingUpdateCoordinator updateCoordinator)
    Resolving Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder,LogWriterStructureHolder.__default__ (mapped from Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder, (none))
    Resolving parameter "traceSources" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder(System.Collections.Generic.IEnumerable`1[[Microsoft.Practices.EnterpriseLibrary.Logging.Filters.ILogFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]] filters, System.Collections.Generic.IEnumerable`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] traceSourceNames, System.Collections.Generic.IEnumerable`1[[Microsoft.Practices.EnterpriseLibrary.Logging.LogSource, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]] traceSources, Microsoft.Practices.EnterpriseLibrary.Logging.LogSource allEventsTraceSource, Microsoft.Practices.EnterpriseLibrary.Logging.LogSource notProcessedTraceSource, Microsoft.Practices.EnterpriseLibrary.Logging.LogSource errorsTraceSource, System.String defaultCategory, System.Boolean tracingEnabled, System.Boolean logWarningsWhenNoCategoriesMatch, System.Boolean revertImpersonation)
      Resolving Microsoft.Practices.EnterpriseLibrary.Logging.LogSource,General
      Resolving parameter "traceListeners" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.LogSource(System.String name, System.Collections.Generic.IEnumerable`1[[System.Diagnostics.TraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] traceListeners, System.Diagnostics.SourceLevels level, System.Boolean autoFlush, Microsoft.Practices.EnterpriseLibrary.Logging.Instrumentation.ILoggingInstrumentationProvider instrumentationProvider)
        Resolving Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.ReconfigurableTraceListenerWrapper,Email Trace Listener (mapped from System.Diagnostics.TraceListener, Email Trace Listener)
        Resolving parameter "wrappedTraceListener" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.ReconfigurableTraceListenerWrapper(System.Diagnostics.TraceListener wrappedTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.ILoggingUpdateCoordinator coordinator)
          Resolving Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.EmailTraceListener,Email Trace Listener‌implementation (mapped from System.Diagnostics.TraceListener, Email Trace Listener‌implementation)
          Resolving parameter "formatter" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.EmailTraceListener(System.String toAddress, System.String fromAddress, System.String subjectLineStarter, System.String subjectLineEnder, System.String smtpServer, System.Int32 smtpPort, Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.ILogFormatter formatter, Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.EmailAuthenticationMode authenticationMode, System.String userName, System.String password, System.Boolean useSSL)
            Resolving Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.ILogFormatter,Text Formatter
Here are codes
        builder.ConfigureLogging() _
               .WithOptions _
                 .DoNotRevertImpersonation() _
               .LogToCategoryNamed("General") _
                 .SendTo.Email("Email Trace Listener") _
                    .FormatWithSharedFormatter("Text Formatter") _
                    .To("ToAddress@email.com") _
                    .From("FromAddress@email.com") _
                    .UsingSmtpServer("smtp.test.com") _
                    .UsingSmtpServerPort(25) _
                    .UseSSL(False)

        Dim configSource = New DictionaryConfigurationSource()
        builder.UpdateConfigurationWithReplace(configSource)
        EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)

        Dim writer As LogWriter = EnterpriseLibraryContainer.Current.GetInstance(Of LogWriter)()
        writer.Write("My message")
Please advise.

Brew
Sep 12, 2014 at 4:09 PM
Edited Sep 12, 2014 at 4:12 PM
The issue is that a shared formatter is being used without defining the actual formatter. If you look at the stack trace you can get a clue to the issue (without explicitly letting you know!) because the message says a ILogFormatter couldn't be found.

The solution is to define the formatter you want (or omit the formatter entirely if the default format is sufficent). For example:
        Dim builder = New ConfigurationSourceBuilder()
        builder.ConfigureLogging() _
        .WithOptions _
          .DoNotRevertImpersonation() _
        .LogToCategoryNamed("General") _
          .SendTo.Email("Email Trace Listener") _
          .FormatWith(New FormatterBuilder() _
            .TextFormatterNamed("Text Formatter") _
              .UsingTemplate("Timestamp: {timestamp}...{newline})}")) _
          .To("ToAddress@email.com") _
          .From("FromAddress@email.com") _
          .UsingSmtpServer("smtp.test.com") _
          .UsingSmtpServerPort(25) _
          .UseSSL(False)

        Dim configSource = New DictionaryConfigurationSource()
        builder.UpdateConfigurationWithReplace(configSource)
        EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)

        Dim writer As LogWriter = EnterpriseLibraryContainer.Current.GetInstance(Of LogWriter)()
        writer.Write("My message")

Instead of using FormatWithSharedFormatter, use FormatWith with a formatter definition.

After that the formatter can be referenced as a shared formatter when configuring other trace listeners.
Sep 12, 2014 at 4:29 PM
Hi randylevy,

The error is gone but I don't received an email as expected. Is there something I'm missing?

Brew
Sep 12, 2014 at 4:54 PM
Try setting the category explicitly when logging:
writer.Write("My message", "General")
Or you can configure the default category:
        Dim builder = New ConfigurationSourceBuilder()
        builder.ConfigureLogging() _
        .WithOptions _
          .DoNotRevertImpersonation() _
        .LogToCategoryNamed("General") _
          .WithOptions _
            .SetAsDefaultCategory() _
          .SendTo.Email("Email Trace Listener") _
          .FormatWith(New FormatterBuilder() _
            .TextFormatterNamed("Text Formatter") _
              .UsingTemplate("Timestamp: {timestamp}...{newline})}")) _
          .To("ToAddress@email.com") _
          .From("FromAddress@email.com") _
          .UsingSmtpServer("smtp.test.com") _
          .UsingSmtpServerPort(25) _
          .UseSSL(False)
If you still have issues it is probably related to the mail server. I would recommend also configuring SpecialSources.LoggingErrorsAndWarningsCategory to capture any errors trying to send the email:
  .SpecialSources _
    .LoggingErrorsAndWarningsCategory _
    .SendTo.FlatFile("Flat File Trace Listener") _
    .ToFile("errors.log") _
Sep 12, 2014 at 7:12 PM
It works. This is a key
              .WithOptions _
                .SetAsDefaultCategory() _
Thank you Randylevy!