Accessing service proxy for SL integration pack LoggingService

Topics: Silverlight Integration Pack
Nov 30, 2011 at 4:39 AM
Edited Nov 30, 2011 at 4:41 AM

Is it possible to access the service proxy object for LoggingService Microsoft.Practices.EnterpriseLibrary.Logging.Service.LoggingService from SL integration pack? In normal implementation in Silverlight xaml.cs file, when I call Write method on LogWriter object then the service gets invoked automatically without the need to create a proxy and make 'completed' or 'async' calls. But is it possible to do this?

Nov 30, 2011 at 11:56 AM

I'm not sure I understand 100%.  Why is logWriter.Write not sufficient?  Or are you trying to use the proxy without Enterprise Library?

I don't think there is a way to get access to the RemoteServiceTraceListener proxy.  And there is no practical way to avoid the proxy class (Enterprise Library is using one under the covers) but you can create the proxy yourself and add some abstraction.

var logEntry = new LogEntry() { Message = "Test" };            
logEntry.Categories.Add("default");

LogHelper.Write(logEntry);


public static class LogHelper
{
    public static void Write(LogEntry logEntry)
    {
        var proxy = new LoggingServiceFactory() 
                    { 
                        EndpointConfigurationName = "CustomBinding_ILoggingService" 
                    }
                    .CreateChannel();
            
        proxy.Write(logEntry);            
    }
}

public static class ILoggingServiceExtension
{
    public static void Write(this ILoggingService proxy, LogEntry logEntry)
    {
        LogEntryMessage[] messages = new LogEntryMessage[] { logEntry.ToLogEntryMessage() };
        proxy.BeginAdd(messages, r =>
            {
                try
                {
                    proxy.EndAdd(r);
                }
                finally
                {
                    if (proxy != null)
                    {
                        ((IDisposable)proxy).Dispose();
                    }
                }
            }, null);
    }
}

-- 
Randy Levy
Enterprise Library support engineer
entlib.support@live.com

Nov 30, 2011 at 1:00 PM

I basically want to implement security for the ILoggingService so that no malicious user can send fake log messages to the service.

Actually I was thinking about implementing username security and set clientcredentials using the proxy.But I dont know if it is possible to use such a binding for the LoggingServiceFactory.

So right now I am trying to authenticate the user using wsHTTPBinding with which I am having a problem as below.

I tried using simple wsHTTPBinding for implementing security while transmitting the log messages using the ILoggingService with following endpoint :

<endpoint address="" binding="wsHttpBinding" bindingConfiguration="WsHTTPBinding_ILoggingService" contract="Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingService">

 defined in web.config of service project.

Following is system.servicemodel tag in web.config of WCF application :

<system.serviceModel>
    <bindings>
     </bindings>
    <services>
      <service name="Microsoft.Practices.EnterpriseLibrary.Logging.Service.LoggingService">
                <endpoint address="" binding="wsHttpBinding"   bindingConfiguration="WsHTTPBinding_ILoggingService"  
      contract="Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingService"/>
                  <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

 Following is my ServiceReferences.ClientConfig


<configuration>
  <system.serviceModel>
    <bindings>
      </bindings>
    <client>
      <endpoint address="http://localhost:63539/Service1.svc" binding="wsHttpBinding" 
	 bindingConfiguration="WsHTTPBinding_ILoggingService"   
     contract="Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingService"/>
    </client>
  </system.serviceModel>
</configuration>
 Now in this case I dont know what LoggingServiceFactory name I should use in Configuration.xaml. I tried 
using WsHTTPBinding_ILoggingService as the LoggingServiceFactory in Configuration.xaml and also as the bindingConfiguration 
in above endpoint definition but I am getting error trace as follows : 
{Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationErrorsException: The configuration content has an invalid format. The content should be in XAML format and the root element must be an instance of IDictionary. Each entry in the dictionary should correspond to each configuration section. ---> System.Windows.Markup.XamlParseException: Failed to create a 'Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingServiceFactory' from the text 'WsHTTPBinding_ILoggingService'. [Line: 5 Position: 64] ---> System.InvalidOperationException: Could not find endpoint element with name 'WsHTTPBinding_ILoggingService' and contract 'Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element.
   at System.ServiceModel.Description.ConfigLoader.LoadChannelBehaviors(ServiceEndpoint serviceEndpoint, String configurationName)
   at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName)
   at System.ServiceModel.ChannelFactory.InitializeEndpoint(String configurationName, EndpointAddress address)
   at System.ServiceModel.ChannelFactory`1..ctor(String endpointConfigurationName, EndpointAddress remoteAddress)
   at System.ServiceModel.ChannelFactory`1..ctor(String endpointConfigurationName)
   at Microsoft.Practices.EnterpriseLibrary.Logging.Service.LoggingServiceFactory.set_EndpointConfigurationName(String value)
   at Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingServiceFactoryEndpointConfigurationNameConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at MS.Internal.XamlManagedRuntimeRPInvokes.CreateFromValue(IntPtr inServiceContext, XamlTypeToken inTs, XamlQualifiedObject& qoValue, XamlPropertyToken inProperty, XamlTypeToken inType, XamlQualifiedObject& qoRootInstance, XamlQualifiedObject& qo)
   --- End of inner exception stack trace ---
   at MS.Internal.XcpImports.CreateFromXaml(String xamlString, Boolean createNamescope, Boolean requireDefaultNamespace, Boolean allowEventHandlers, Boolean expandTemplatesDuringParse)
   at MS.Internal.XcpImports.CreateFromXaml(String xamlString, Boolean createNamescope, Boolean requireDefaultNamespace, Boolean allowEventHandlers)
   at System.Windows.Markup.XamlReader.Load(String xaml)
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.DictionaryConfigurationSource.LoadResource(Uri uri, Boolean throwIfNotExists)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.DictionaryConfigurationSource.LoadResource(Uri uri, Boolean throwIfNotExists)
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.DictionaryConfigurationSource.CreateDefault()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceFactory.Create()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.CreateDefaultContainer()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.SetCurrentContainerIfNotSet()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.get_Current()
   at SL_Logger.MainPage.button1_Click(Object sender, RoutedEventArgs e)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)}
This error I am getting while creation of LogWriter object : 

LogWriter

 

writer = EnterpriseLibraryContainer.Current.GetInstance<LogWriter

>();

This was working fine for the customBinding.
 Is it that only customBinding can be used with the ILoggingService? Any idea what I might be doing wrong in above 
binding configuration? My main purpose is to authenticate the client to prevent fake logging.
Sorry if I am asking very simple questions :P
Any help would be greatly appreciated.
 
 
Dec 1, 2011 at 3:02 AM

I don't think these questions are simple; the subject is not documented that extensively and things have to be pieced together.

It's good that you are thinking about security.  :)

The issue is that Silverlight does not support wsHttpBinding.  Silverlight only supports BasicHttpBinding, PollingDuplexHttpBinding, and CustomBinding. 
See http://msdn.microsoft.com/en-us/library/cc896571(v=vs.95).aspx.

Look at using a CustomBinding along with HttpsTransportBinding for SSL, and SecurityBinding for sending username and password as SOAP headers.

Take a look at this article How to: Use Message Credentials to Secure a Service for Silverlight Applications for a good walkthrough.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com

Dec 1, 2011 at 1:05 PM

In the guidance for Silverlight Integration Pack it is given :

"If you wish to have more control over the way the WCF service is created, you can also supply an instance of a Logging Service Factory to the

Logging Service Factory property. For example, if you wish to secure your logging service, then you can use a custom Logging Service Factory to supply

credentials to the Logging Service. You can only supply a custom Logging Service Factory directly in a XAML configuration file or using the fluent

configuration API."

Is it possible to pass these credentials programatically? Or we use something like

<customBinding>
        <binding name="Microsoft.Practices.EnterpriseLibrary.Logging.Service.customBinding">          
          <binaryMessageEncoding />
          <httpsTransport authenticationScheme="Negotiate"/>
        </binding>
      </customBinding>
so as to implement Windows authentication.
Dec 2, 2011 at 12:19 AM

The current LoggingServiceFactory is setup to take a configuration name and retrieve the WCF settings for that name.  If you need to do anything else then you
will have to create a custom LoggingServicefactory.  Luckily this is not too hard.  For example, here's a LoggingServiceFactory that takes the end point URL so you 
don't need to use configuration:

    /// <summary>
    /// Factory that creates a transient WCF <see cref="IChannel"/> for accessing the logging service.
    /// </summary>
    public class MyLoggingServiceFactory : ILoggingServiceFactory, IDisposable
    {
        private ChannelFactory<ILoggingService> channelFactory;
        private string endpointUrl;

        public string EndpointUrl
        {
            get
            {
                return endpointUrl;
            }
        }

        public MyLoggingServiceFactory(string endpointUrl)
        {
            this.endpointUrl = endpointUrl;

            HttpTransportBindingElement httpTransport = new HttpTransportBindingElement
            {
                MaxBufferSize = int.MaxValue,
                MaxReceivedMessageSize = int.MaxValue
            };

            BinaryMessageEncodingBindingElement messageEncoding = new BinaryMessageEncodingBindingElement
            {
                MessageVersion = MessageVersion.Default
            };  

            //-- Use this binding incase your service required CustomBinding configuration.  
            CustomBinding binding = new CustomBinding(messageEncoding, httpTransport);

            this.channelFactory = new ChannelFactory<ILoggingService>(binding, new EndpointAddress(endpointUrl));
        }

        public virtual ILoggingService CreateChannel()
        {
            if (this.channelFactory == null)
            {
                throw new InvalidOperationException("LoggingServiceFactory_EndpointConfigurationNameNotSet");
            }

            return new LoggingServiceProxy(this.channelFactory);
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                using (this.channelFactory) { this.channelFactory = null; }
            }
        }

        ~MyLoggingServiceFactory()
        {
            this.Dispose(false);
        }
    }

The binding you posted looks like the service side binding (it gets confusing because people post both but rarely seem to
indicate if it is the client or the server).  It actually, looks like a non ASP.NET WCF service binding.  The Silverlight client CustomBinding schema can be found here.

If you want to use Windows Authentication the good news is that it looks like Silverlight 4 will send the windows credentials automatically via
the browser -- no intervention or programming required.  See How to: Use Windows Authentication to Secure a Service for Silverlight Applications
for the details.

See also Windows authentication with Silverlight custom binding for some other people's experience.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com

Dec 28, 2011 at 7:02 PM

I am having lot off issues with Silverlight Enterprise logging (5.0.505.0). I was able to resolve most of them, but there is one last issue. 

When try to access the loggingService.svc in the internet explorer (after enabling metadata exchange), i get a message to enable anonymous authentication. 

I did that and i was able to test the service using WCF test client. 

But I am not able to write to any logs to the file on network location. Writing to local log file, on C:Temp works fine. 

My questions:

Why should the service require anonymous authentication, when i am using the custom binding as described in documentation?

What should i do get it to use integrated windows authentication as is being used by the rest of the website?

Configuration files on both server and client side is much appreciated.

 

Regards

Dec 29, 2011 at 5:22 AM
Edited Dec 29, 2011 at 5:26 AM

Why should the service require anonymous authentication, when i am using the custom binding as described in documentation?

 It sounds like you have applied the default metadata service behavior:

      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True"/>
        </behavior>
      </serviceBehaviors>

By creating an anonymous service behavior, this enables metadata exchange on all endpoints for the service host.  The default binding for metadata exchange is MexHttpBinding which requires anonymous access.  That is why you see that message.  If you want to use a different binding read How to: Retrieve Metadata Over a non-MEX Binding

> What should i do get it to use integrated windows authentication as is being used by the rest of the website? 

If the browser is IE then Siliverlight will send the Windows Credentials automatically without prompting.  On the server side just set the authenticationScheme for the service:

    <bindings>
      <customBinding>
        <binding name="Microsoft.Practices.EnterpriseLibrary.Logging.Service.customBinding">
          <binaryMessageEncoding />
          <httpTransport authenticationScheme="Negotiate" />
        </binding>
      </customBinding>
    </bindings>

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Apr 26, 2012 at 4:52 PM
Edited Apr 26, 2012 at 4:57 PM

I've created MyLoggingServiceFactory class.  What are options for using this either in code or xaml configuration file?
Specific code snippets would be appreciated.

Tried the following,

 public class MyLoggingServiceFactory : ILoggingServiceFactory, IDisposable
    {
        private ChannelFactory<ILoggingService> channelFactory;
        private string endpointUrl;

        public string EndpointUrl
        {
            get
            {
                return endpointUrl;
            }
        }

        public MyLoggingServiceFactory()
            : this("http://localhost:58691/Logging/LoggingService.svc")
        {
        }

        public MyLoggingServiceFactory(string endpointUrl)
        {
            this.endpointUrl = endpointUrl;

            HttpTransportBindingElement httpTransport = new HttpTransportBindingElement
            {
                MaxBufferSize = int.MaxValue,
                MaxReceivedMessageSize = int.MaxValue
            };

            BinaryMessageEncodingBindingElement messageEncoding = new BinaryMessageEncodingBindingElement
            {
                MessageVersion = MessageVersion.Default
            };

            //-- Use this binding incase your service required CustomBinding configuration. 
            CustomBinding binding = new CustomBinding(messageEncoding, httpTransport);

            this.channelFactory = new ChannelFactory<ILoggingService>(binding, new EndpointAddress(endpointUrl));
        }

        public virtual ILoggingService CreateChannel()
        {
            if (this.channelFactory == null)
            {
                throw new InvalidOperationException("LoggingServiceFactory_EndpointConfigurationNameNotSet");
            }

            return new LoggingServiceProxy(this.channelFactory);
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                using (this.channelFactory) { this.channelFactory = null; }
            }
        }

        ~MyLoggingServiceFactory()
        {
            this.Dispose(false);
        }
    }

and,

 <?xml version="1.0" encoding="utf-8"?>
<el:ConfigurationDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:el="http://schemas.microsoft.com/practices/2011/entlib">
    <el:LoggingSettings DefaultCategory="Logging" x:Key="loggingConfiguration" LogWarningWhenNoCategoriesMatch="True">
        <el:LoggingSettings.TraceListeners>
            <el:RemoteServiceTraceListenerData LoggingServiceFactory="Services.MyLoggingServiceFactory" Name="remote" SendImmediately="True" />
        </el:LoggingSettings.TraceListeners>
        <el:LoggingSettings.TraceSources>
            <el:TraceSourceData Name="Logging" DefaultLevel="All">
                <el:TraceSourceData.TraceListeners>
                    <el:TraceListenerReferenceData Name="remote"/>
                </el:TraceSourceData.TraceListeners>
            </el:TraceSourceData>
            <el:TraceSourceData Name="Exception" DefaultLevel="All">
                <el:TraceSourceData.TraceListeners>
                    <el:TraceListenerReferenceData Name="remote"/>
                </el:TraceSourceData.TraceListeners>
            </el:TraceSourceData>
        </el:LoggingSettings.TraceSources>
        <el:LoggingSettings.SpecialTraceSources>
            <el:SpecialTraceSourcesData>
                <el:SpecialTraceSourcesData.ErrorsTraceSource>
                    <el:TraceSourceData DefaultLevel="Warning">
                        <el:TraceSourceData.TraceListeners>
                            <el:TraceListenerReferenceData Name="remote"/>
                        </el:TraceSourceData.TraceListeners>
                    </el:TraceSourceData>
                </el:SpecialTraceSourcesData.ErrorsTraceSource>
            </el:SpecialTraceSourcesData>
        </el:LoggingSettings.SpecialTraceSources>
    </el:LoggingSettings>
    <el:CachingSettings DefaultCache="In-Memory Cache" x:Key="cachingSilverlightConfiguration">
        <el:CachingSettings.Caches>
            <el:InMemoryCacheData ExpirationPollingInterval="00:02:00" Name="In-Memory Cache" />
            <el:IsolatedStorageCacheData MaxSizeInKilobytes="5120" PercentOfQuotaUsedBeforeScavenging="50" PercentOfQuotaUsedAfterScavenging="20" ExpirationPollingInterval="00:01:00" Name="Isolated-Storage Cache" />
        </el:CachingSettings.Caches>
    </el:CachingSettings>
</el:ConfigurationDictionary>

 and:

        private static void InitializeEnterpriseLibrary()
        {
            string configFileName = typeof(App).Namespace + ".EnterpriseLibraryConfig.xaml";

            string xaml;
            using (Stream s = typeof(App).Assembly.GetManifestResourceStream(configFileName))
            using (StreamReader sr = new StreamReader(s))
            {
                xaml = sr.ReadToEnd();
            }

            var configDictionary = (IDictionary)XamlReader.Load(xaml);
            var configSource = DictionaryConfigurationSource.FromDictionary(configDictionary);
            EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
        }

 but get

Failed to create a 'Microsoft.Practices.EnterpriseLibrary.Logging.Service.ILoggingServiceFactory' from the text 'Services.MyLoggingServiceFactory'. [Line: 7 Position: 70]

at =>  var configDictionary = (IDictionary)XamlReader.Load(xaml);

Apr 26, 2012 at 7:29 PM

From what I've seen despite what the documentation says LoggingServiceFactory is treated as a endpoint configuration name and not a type.  You can use the fluent configuration to configure the logging service factory.  You can stick with the configuration file (for caching) and then use the fluent interface to configure logging:

        private static void InitializeEnterpriseLibrary2()
        {
            string configFileName = typeof(App).Namespace + ".EnterpriseLibraryConfig.xaml";

            string xaml;
            using (Stream s = typeof(App).Assembly.GetManifestResourceStream(configFileName))
            using (StreamReader sr = new StreamReader(s))
            {
                xaml = sr.ReadToEnd();
            }

            var configDictionary = (IDictionary)XamlReader.Load(xaml);
            var configSource = DictionaryConfigurationSource.FromDictionary(configDictionary);

            var configBuilder = new ConfigurationSourceBuilder();
            configBuilder.ConfigureLogging()
                .LogToCategoryNamed("default")
                    .SendTo.RemoteService("remote")
                    .SendsImmediately()
                    .WithLoggingServiceFactory(new MyLoggingServiceFactory("http://localhost:51625/LogService.svc"))
                    ;
configBuilder.UpdateConfigurationWithReplace(configSource); EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource); }

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Apr 26, 2012 at 9:33 PM

Thanks.

New to fluent configuration API…

How to add another category name using the fluent API?

As well as adding specialtracesources?

Basically want to duplicate the configuration for Logging:

<el:LoggingSettings DefaultCategory="Logging" x:Key="loggingConfiguration" LogWarningWhenNoCategoriesMatch="True">

<el:LoggingSettings.TraceListeners>

<el:RemoteServiceTraceListenerData LoggingServiceFactory="Services.MyLoggingServiceFactory" Name="remote" SendImmediately="True" />

</el:LoggingSettings.TraceListeners>

<el:LoggingSettings.TraceSources>

<el:TraceSourceData Name="Logging" DefaultLevel="All">

<el:TraceSourceData.TraceListeners>

<el:TraceListenerReferenceData Name="remote"/>

</el:TraceSourceData.TraceListeners>

</el:TraceSourceData>

<el:TraceSourceData Name="Exception" DefaultLevel="All">

<el:TraceSourceData.TraceListeners>

<el:TraceListenerReferenceData Name="remote"/>

</el:TraceSourceData.TraceListeners>

</el:TraceSourceData>

</el:LoggingSettings.TraceSources>

<el:LoggingSettings.SpecialTraceSources>

<el:SpecialTraceSourcesData>

<el:SpecialTraceSourcesData.ErrorsTraceSource>

<el:TraceSourceData DefaultLevel="Warning">

<el:TraceSourceData.TraceListeners>

<el:TraceListenerReferenceData Name="remote"/>

</el:TraceSourceData.TraceListeners>

</el:TraceSourceData>

</el:SpecialTraceSourcesData.ErrorsTraceSource>

</el:SpecialTraceSourcesData>

</el:LoggingSettings.SpecialTraceSources>

</el:LoggingSettings>

From: randylevy [email removed]
Sent: Thursday, April 26, 2012 1:29 PM
To: Son, Edward
Subject: Re: Accessing service proxy for SL integration pack LoggingService [entlib:281264]

From: randylevy

From what I've seen despite what the documentation says LoggingServiceFactory is treated as a endpoint configuration name and not a type. You can use the fluent configuration to configure the logging service factory. You can stick with the configuration file (for caching) and then use the fluent interface to configure logging:

        private static void InitializeEnterpriseLibrary2()
        {
            string configFileName = typeof(App).Namespace + ".EnterpriseLibraryConfig.xaml";
 
            string xaml;
            using (Stream s = typeof(App).Assembly.GetManifestResourceStream(configFileName))
            using (StreamReader sr = new StreamReader(s))
            {
                xaml = sr.ReadToEnd();
            }
 
            var configDictionary = (IDictionary)XamlReader.Load(xaml);
            var configSource = DictionaryConfigurationSource.FromDictionary(configDictionary);
 
            var configBuilder = new ConfigurationSourceBuilder();
            configBuilder.ConfigureLogging()
                .LogToCategoryNamed("default")
                    .SendTo.RemoteService("remote")
                    .SendsImmediately()
                    .WithLoggingServiceFactory(new MyLoggingServiceFactory("http://localhost:51625/LogService.svc"))
                    ;

            configBuilder.UpdateConfigurationWithReplace(configSource);
 
            EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
        }

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com

This e-mail and any attachments are for the sole use of the intended recipient(s) and may contain information that is confidential. If you are not the intended recipient(s) and have received this e-mail in error, please immediately notify the sender by return e-mail and delete this e-mail from your computer. Any distribution, disclosure or the taking of any other action by anyone other than the intended recipient(s) is strictly prohibited


.
Apr 27, 2012 at 4:09 AM
Edited Apr 27, 2012 at 4:10 AM

See Using the Fluent Configuration API for some reading.

You can add other categories and special sources:

 

var configBuilder = new ConfigurationSourceBuilder();
    configBuilder.ConfigureLogging()
        .LogToCategoryNamed("default")
            .SendTo
                .RemoteService("remote")
                .SendsImmediately()
                .WithLoggingServiceFactory(
                    new MyLoggingServiceFactory("http://localhost:51625/LogService.svc"))
        .LogToCategoryNamed("AnotherCategory")
            .SendTo
                .SharedListenerNamed("remote")
        .SpecialSources.LoggingErrorsAndWarningsCategory
            .SendTo
                .IsolatedStorage("errors")
    ;

If you play with it in Visual Studio intellisense will show the available options -- it's pretty easy to follow.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com